From: Hannu Nyman Date: Tue, 1 May 2018 07:01:50 +0000 (+0300) Subject: Merge pull request #1690 from karlp/pagekite X-Git-Url: https://git.archive.openwrt.org/?p=project%2Fluci.git;a=commitdiff_plain;h=dcfc4569c483f4218cf41b26ef0f4dfed0441c55;hp=cc00b01c270ff48897a279cfc507e3dc758a2d30 Merge pull request #1690 from karlp/pagekite luci-app-pagekitec: new package --- diff --git a/applications/luci-app-adblock/luasrc/controller/adblock.lua b/applications/luci-app-adblock/luasrc/controller/adblock.lua index 700f187b3..10110666c 100644 --- a/applications/luci-app-adblock/luasrc/controller/adblock.lua +++ b/applications/luci-app-adblock/luasrc/controller/adblock.lua @@ -15,9 +15,9 @@ function index() entry({"admin", "services", "adblock", "tab_from_cbi"}, cbi("adblock/overview_tab", {hideresetbtn=true, hidesavebtn=true}), _("Overview"), 10).leaf = true entry({"admin", "services", "adblock", "logfile"}, call("logread"), _("View Logfile"), 20).leaf = true entry({"admin", "services", "adblock", "advanced"}, firstchild(), _("Advanced"), 100) - entry({"admin", "services", "adblock", "advanced", "blacklist"}, cbi("adblock/blacklist_tab"), _("Edit Blacklist"), 110).leaf = true - entry({"admin", "services", "adblock", "advanced", "whitelist"}, cbi("adblock/whitelist_tab"), _("Edit Whitelist"), 120).leaf = true - entry({"admin", "services", "adblock", "advanced", "configuration"}, cbi("adblock/configuration_tab"), _("Edit Configuration"), 130).leaf = true + entry({"admin", "services", "adblock", "advanced", "blacklist"}, form("adblock/blacklist_tab"), _("Edit Blacklist"), 110).leaf = true + entry({"admin", "services", "adblock", "advanced", "whitelist"}, form("adblock/whitelist_tab"), _("Edit Whitelist"), 120).leaf = true + entry({"admin", "services", "adblock", "advanced", "configuration"}, form("adblock/configuration_tab"), _("Edit Configuration"), 130).leaf = true entry({"admin", "services", "adblock", "advanced", "query"}, template("adblock/query"), _("Query domains"), 140).leaf = true entry({"admin", "services", "adblock", "advanced", "result"}, call("queryData"), nil, 150).leaf = true end @@ -36,8 +36,8 @@ end function queryData(domain) if domain then luci.http.prepare_content("text/plain") - local cmd = "/etc/init.d/adblock query %q 2>&1" - local util = io.popen(cmd % domain) + local cmd = "/etc/init.d/adblock query %s 2>&1" + local util = io.popen(cmd % util.shellquote(domain)) if util then while true do local line = util:read("*l") diff --git a/applications/luci-app-adblock/po/it/adblock.po b/applications/luci-app-adblock/po/it/adblock.po index 88adcc892..0a1b65ac3 100644 --- a/applications/luci-app-adblock/po/it/adblock.po +++ b/applications/luci-app-adblock/po/it/adblock.po @@ -275,8 +275,8 @@ msgid "" msgstr "" msgid "" -"Size of the download queue to handle downloads & list processing in parallel " -"(default '4').
" +"Size of the download queue to handle downloads & list processing in " +"parallel (default '4').
" msgstr "" msgid "Startup Trigger" diff --git a/applications/luci-app-adblock/po/ja/adblock.po b/applications/luci-app-adblock/po/ja/adblock.po index 60c5a9a54..dfd72cbf6 100644 --- a/applications/luci-app-adblock/po/ja/adblock.po +++ b/applications/luci-app-adblock/po/ja/adblock.po @@ -301,8 +301,8 @@ msgstr "" "処理エラーまたはドメイン カウントが0以下の場合、メールを送信します。
" msgid "" -"Size of the download queue to handle downloads & list processing in parallel " -"(default '4').
" +"Size of the download queue to handle downloads & list processing in " +"parallel (default '4').
" msgstr "" "ダウンロードの制御とリストの処理を同時並行的に行うダウンロード キューのサイズ" "です(既定値: '4')。
" diff --git a/applications/luci-app-adblock/po/pt-br/adblock.po b/applications/luci-app-adblock/po/pt-br/adblock.po index 7eb6e3ebc..c0d9d816d 100644 --- a/applications/luci-app-adblock/po/pt-br/adblock.po +++ b/applications/luci-app-adblock/po/pt-br/adblock.po @@ -267,8 +267,8 @@ msgid "" msgstr "" msgid "" -"Size of the download queue to handle downloads & list processing in parallel " -"(default '4').
" +"Size of the download queue to handle downloads & list processing in " +"parallel (default '4').
" msgstr "" msgid "Startup Trigger" diff --git a/applications/luci-app-adblock/po/ru/adblock.po b/applications/luci-app-adblock/po/ru/adblock.po index 6e80e80b3..17f39fdd8 100644 --- a/applications/luci-app-adblock/po/ru/adblock.po +++ b/applications/luci-app-adblock/po/ru/adblock.po @@ -303,8 +303,8 @@ msgstr "" "≤ 0.
" msgid "" -"Size of the download queue to handle downloads & list processing in parallel " -"(default '4').
" +"Size of the download queue to handle downloads & list processing in " +"parallel (default '4').
" msgstr "" "Значение очереди загрузки для выполнения параллельных загрузок (по умолчанию " "'4').
" diff --git a/applications/luci-app-adblock/po/templates/adblock.pot b/applications/luci-app-adblock/po/templates/adblock.pot index 5a93f8f07..6fbaa652a 100644 --- a/applications/luci-app-adblock/po/templates/adblock.pot +++ b/applications/luci-app-adblock/po/templates/adblock.pot @@ -248,8 +248,8 @@ msgid "" msgstr "" msgid "" -"Size of the download queue to handle downloads & list processing in parallel " -"(default '4').
" +"Size of the download queue to handle downloads & list processing in " +"parallel (default '4').
" msgstr "" msgid "Startup Trigger" diff --git a/applications/luci-app-adblock/po/zh-cn/adblock.po b/applications/luci-app-adblock/po/zh-cn/adblock.po index 1d7dc2b19..e26c44c4d 100644 --- a/applications/luci-app-adblock/po/zh-cn/adblock.po +++ b/applications/luci-app-adblock/po/zh-cn/adblock.po @@ -369,152 +369,3 @@ msgstr "已暂停" msgid "running" msgstr "" -#~ msgid "" -#~ "For SSL protected blocklist sources you need a suitable SSL library, e.g. " -#~ "'libustream-ssl' or the wget 'built-in'." -#~ msgstr "" -#~ "对于 SSL 保护的 blocklist 源,您需要一个合适的 SSL 库,例如'libustream-" -#~ "ssl'或 wget'built-in'。" - -#~ msgid "" -#~ "Caution: Please don't select big lists or many lists at once on low " -#~ "memory devices to prevent OOM exceptions!" -#~ msgstr "" -#~ "注意:请勿在内存较小的设备上选择过长的列表或同时选择多个列表,以防止 OOM " -#~ "异常!" - -#~ msgid "" -#~ "Create compressed blocklist backups, they will be used in case of " -#~ "download errors or during startup in manual mode." -#~ msgstr "创建压缩的 blocklist 备份,它们将在下载错误或手动模式下启动时使用。" - -#~ msgid "" -#~ "Enable memory intense overall sort / duplicate removal on low memory " -#~ "devices (< 64 MB RAM)" -#~ msgstr "在低内存设备上启用耗用内存的整体排序/重复规则删除(<64 MB RAM)" - -#~ msgid "" -#~ "For further information see online " -#~ "documentation" -#~ msgstr "有关更多信息,请参阅在线文档" - -#~ msgid "" -#~ "In OPKG use the '--force-maintainer' option to overwrite the pre-existing " -#~ "config file or download a fresh default config from here" -#~ msgstr "" -#~ "在 OPKG 中,使用“--force-maintainer”选项覆盖预先存在的配置文件,或从此处下载新的默认配置" - -#~ msgid "" -#~ "List of available network interfaces. By default the startup will be " -#~ "triggered by the 'wan' interface.
" -#~ msgstr "可用网络接口列表。默认情况下,将由“wan”界面触发启动。
" - -#~ msgid "Manual / Backup mode" -#~ msgstr "手动/备份模式" - -#~ msgid "Overall Blocked Domains" -#~ msgstr "整体封锁域名" - -#~ msgid "Please update your adblock config file to use this package." -#~ msgstr "请更新您的 adblock 配置文件以使用此软件包。" - -#~ msgid "" -#~ "Target directory for adblock backups. Please use only non-volatile disks, " -#~ "no ram/tmpfs drives." -#~ msgstr "" -#~ "adblock 备份的目标目录。请仅使用非易失性磁盘,不使用 ram/tmpfs 驱动器。" - -#~ msgid "DNS backend" -#~ msgstr "DNS 后端" - -#~ msgid "Enable verbose debug logging" -#~ msgstr "启用详细调试输出" - -#~ msgid "Resume adblock" -#~ msgstr "恢复 Adblock" - -#~ msgid "Status" -#~ msgstr "状态" - -#~ msgid "Suspend adblock" -#~ msgstr "暂停 Adblock" - -#~ msgid "active" -#~ msgstr "已启用" - -#~ msgid "no domains blocked" -#~ msgstr "没有被拦截的域名" - -#~ msgid "suspended" -#~ msgstr "已暂停" - -#~ msgid "." -#~ msgstr "." - -#~ msgid "For further information" -#~ msgstr "更多信息" - -#~ msgid "see online documentation" -#~ msgstr "查看在线文档" - -#~ msgid "Backup options" -#~ msgstr "备份选项" - -#~ msgid "" -#~ "). Note that list URLs and Shallalist category selections are not " -#~ "configurable via Luci." -#~ msgstr ")。需要注意的是列表URL和列表类别选项无法通过Luci设置。" - -#~ msgid "Available blocklist sources (" -#~ msgstr "可用拦截列表来源(" - -#~ msgid "" -#~ "File with whitelisted hosts/domains that are allowed despite being on a " -#~ "blocklist." -#~ msgstr "允许的主机/域名列表" - -#~ msgid "Global options" -#~ msgstr "全局选项" - -#~ msgid "Whitelist file" -#~ msgstr "白名单文件" - -#~ msgid "see list details" -#~ msgstr "查看列表详情" - -#~ msgid "Count" -#~ msgstr "数量" - -#~ msgid "IPv4 blackhole ip address" -#~ msgstr "IPv4禁止列表" - -#~ msgid "IPv6 blackhole ip address" -#~ msgstr "IPv6禁止列表" - -#~ msgid "List date/state" -#~ msgstr "列表日期/状态" - -#~ msgid "Name of the logical lan interface" -#~ msgstr "LAN接口名称" - -#~ msgid "Port of the adblock uhttpd instance" -#~ msgstr "Adblock uhttpd端口" - -#~ msgid "Redirect all DNS queries to the local resolver" -#~ msgstr "将所有DNS查询都重定向到本地解析器" - -#~ msgid "Timeout for blocklist fetch (seconds)" -#~ msgstr "列表查询超时时间(秒)" - -#~ msgid "Total count of blocked domains" -#~ msgstr "阻止域名总数" - -#~ msgid "" -#~ "When adblock is active, all DNS queries are redirected to the local " -#~ "resolver in this server by default. You can disable that to allow queries " -#~ "to external DNS servers." -#~ msgstr "" -#~ "当Adblock处于活动状态时,默认情况下会将所有的DNS查询重定向到此服务器的本地" -#~ "解析器。您可以禁用以允许查询外部DNS服务器。" diff --git a/applications/luci-app-adblock/po/zh-tw/adblock.po b/applications/luci-app-adblock/po/zh-tw/adblock.po index da00842d5..417fc6bcc 100644 --- a/applications/luci-app-adblock/po/zh-tw/adblock.po +++ b/applications/luci-app-adblock/po/zh-tw/adblock.po @@ -369,153 +369,3 @@ msgstr "已暫停" msgid "running" msgstr "" -#~ msgid "" -#~ "For SSL protected blocklist sources you need a suitable SSL library, e.g. " -#~ "'libustream-ssl' or the wget 'built-in'." -#~ msgstr "" -#~ "對於 SSL 保護的 blocklist 源,您需要一個合適的 SSL 庫,例如'libustream-" -#~ "ssl'或 wget'built-in'。" - -#~ msgid "" -#~ "Caution: Please don't select big lists or many lists at once on low " -#~ "memory devices to prevent OOM exceptions!" -#~ msgstr "" -#~ "注意:請勿在記憶體較小的裝置上選擇過長的列表或同時選擇多個列表,以防止 " -#~ "OOM 異常!" - -#~ msgid "" -#~ "Create compressed blocklist backups, they will be used in case of " -#~ "download errors or during startup in manual mode." -#~ msgstr "建立壓縮的 blocklist 備份,它們將在下載錯誤或手動模式下啟動時使用。" - -#~ msgid "" -#~ "Enable memory intense overall sort / duplicate removal on low memory " -#~ "devices (< 64 MB RAM)" -#~ msgstr "" -#~ "在低記憶體裝置上啟用耗用記憶體的整體排序/重複規則刪除(<64 MB RAM)" - -#~ msgid "" -#~ "For further information see online " -#~ "documentation" -#~ msgstr "有關更多資訊,請參閱線上文件" - -#~ msgid "" -#~ "In OPKG use the '--force-maintainer' option to overwrite the pre-existing " -#~ "config file or download a fresh default config from here" -#~ msgstr "" -#~ "在 OPKG 中,使用“--force-maintainer”選項覆蓋預先存在的配置檔案,或從此處下載新的預設配置" - -#~ msgid "" -#~ "List of available network interfaces. By default the startup will be " -#~ "triggered by the 'wan' interface.
" -#~ msgstr "可用網路介面列表。預設情況下,將由“wan”介面觸發啟動。
" - -#~ msgid "Manual / Backup mode" -#~ msgstr "手動/備份模式" - -#~ msgid "Overall Blocked Domains" -#~ msgstr "整體封鎖域名" - -#~ msgid "Please update your adblock config file to use this package." -#~ msgstr "請更新您的 adblock 配置檔案以使用此軟體包。" - -#~ msgid "" -#~ "Target directory for adblock backups. Please use only non-volatile disks, " -#~ "no ram/tmpfs drives." -#~ msgstr "" -#~ "adblock 備份的目標目錄。請僅使用非易失性磁碟,不使用 ram/tmpfs 驅動器。" - -#~ msgid "DNS backend" -#~ msgstr "DNS 後端" - -#~ msgid "Enable verbose debug logging" -#~ msgstr "啟用詳細除錯輸出" - -#~ msgid "Resume adblock" -#~ msgstr "恢復 Adblock" - -#~ msgid "Status" -#~ msgstr "狀態" - -#~ msgid "Suspend adblock" -#~ msgstr "暫停 Adblock" - -#~ msgid "active" -#~ msgstr "已啟用" - -#~ msgid "no domains blocked" -#~ msgstr "沒有被攔截的域名" - -#~ msgid "suspended" -#~ msgstr "已暫停" - -#~ msgid "." -#~ msgstr "." - -#~ msgid "For further information" -#~ msgstr "更多資訊" - -#~ msgid "see online documentation" -#~ msgstr "檢視線上文件" - -#~ msgid "Backup options" -#~ msgstr "備份選項" - -#~ msgid "" -#~ "). Note that list URLs and Shallalist category selections are not " -#~ "configurable via Luci." -#~ msgstr ")。需要注意的是列表URL和列表類別選項無法通過Luci設定。" - -#~ msgid "Available blocklist sources (" -#~ msgstr "可用攔截列表來源(" - -#~ msgid "" -#~ "File with whitelisted hosts/domains that are allowed despite being on a " -#~ "blocklist." -#~ msgstr "允許的主機/域名列表" - -#~ msgid "Global options" -#~ msgstr "全域性選項" - -#~ msgid "Whitelist file" -#~ msgstr "白名單檔案" - -#~ msgid "see list details" -#~ msgstr "檢視列表詳情" - -#~ msgid "Count" -#~ msgstr "數量" - -#~ msgid "IPv4 blackhole ip address" -#~ msgstr "IPv4禁止列表" - -#~ msgid "IPv6 blackhole ip address" -#~ msgstr "IPv6禁止列表" - -#~ msgid "List date/state" -#~ msgstr "列表日期/狀態" - -#~ msgid "Name of the logical lan interface" -#~ msgstr "LAN介面名稱" - -#~ msgid "Port of the adblock uhttpd instance" -#~ msgstr "Adblock uhttpd埠" - -#~ msgid "Redirect all DNS queries to the local resolver" -#~ msgstr "將所有DNS查詢都重定向到本地解析器" - -#~ msgid "Timeout for blocklist fetch (seconds)" -#~ msgstr "列表查詢超時時間(秒)" - -#~ msgid "Total count of blocked domains" -#~ msgstr "阻止域名總數" - -#~ msgid "" -#~ "When adblock is active, all DNS queries are redirected to the local " -#~ "resolver in this server by default. You can disable that to allow queries " -#~ "to external DNS servers." -#~ msgstr "" -#~ "當Adblock處於活動狀態時,預設情況下會將所有的DNS查詢重定向到此伺服器的本地" -#~ "解析器。您可以禁用以允許查詢外部DNS伺服器。" diff --git a/applications/luci-app-advanced-reboot/Makefile b/applications/luci-app-advanced-reboot/Makefile index bb545a204..d27049830 100644 --- a/applications/luci-app-advanced-reboot/Makefile +++ b/applications/luci-app-advanced-reboot/Makefile @@ -13,7 +13,7 @@ LUCI_DESCRIPTION:=Provides Web UI (found under System/Advanced Reboot) to reboot LUCI_DEPENDS:=+luci LUCI_PKGARCH:=all -PKG_RELEASE:=26 +PKG_RELEASE:=27 include ../../luci.mk diff --git a/applications/luci-app-advanced-reboot/README.md b/applications/luci-app-advanced-reboot/README.md index a938479d9..d4659c8dc 100644 --- a/applications/luci-app-advanced-reboot/README.md +++ b/applications/luci-app-advanced-reboot/README.md @@ -19,7 +19,7 @@ Currently supported dual-partition devices include: 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) -![screenshot](https://raw.githubusercontent.com/stangri/screenshots/master/luci-app-advanced-reboot/screenshot01.png "screenshot") +![screenshot](https://raw.githubusercontent.com/stangri/openwrt_packages/master/screenshots/luci-app-advanced-reboot/screenshot01.png "screenshot") ## How to install Install ```luci-app-advanced-reboot``` from Web UI or connect to your router via ssh and run the following commands: diff --git a/applications/luci-app-advanced-reboot/luasrc/controller/advanced_reboot.lua b/applications/luci-app-advanced-reboot/luasrc/controller/advanced_reboot.lua index 0f512df63..b5dd4fe0f 100644 --- a/applications/luci-app-advanced-reboot/luasrc/controller/advanced_reboot.lua +++ b/applications/luci-app-advanced-reboot/luasrc/controller/advanced_reboot.lua @@ -8,19 +8,20 @@ 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 EA9500", "linksys,panamera", "mtd3", "mtd6", 28, "boot_part", 1, 2}, + {"Linksys WRT1200AC", "linksys-caiman", "mtd4", "mtd6", 32, "boot_part", 1, 2, "bootcmd", "run nandboot", "run altnandboot"}, + {"Linksys WRT1900AC", "linksys-mamba", "mtd4", "mtd6", 32, "boot_part", 1, 2, "bootcmd", "run nandboot", "run altnandboot"}, + {"Linksys WRT1900ACv2", "linksys-cobra", "mtd4", "mtd6", 32, "boot_part", 1, 2, "bootcmd", "run nandboot", "run altnandboot"}, + {"Linksys WRT1900ACS", "linksys-shelby", "mtd4", "mtd6", 32, "boot_part", 1, 2, "bootcmd", "run nandboot", "run altnandboot"}, + {"Linksys WRT3200ACM", "linksys-rango", "mtd5", "mtd7", 32, "boot_part", 1, 2, "bootcmd", "run nandboot", "run altnandboot"}, {"ZyXEL NBG6817","nbg6817","mmcblk0p4","mmcblk0p7",32,nil,255,1} } errorMessage = "" device_board_name = luci.util.trim(luci.sys.exec("cat /tmp/sysinfo/board_name")) for i=1, #devices do - table_board_name = devices[i][2]:gsub('-','') - if device_board_name and device_board_name:gsub('-',''):match(table_board_name) then + table_board_name = devices[i][2]:gsub('%p','') + if device_board_name and device_board_name:gsub('%p',''):match(table_board_name) then device_name = devices[i][1] partition_one_mtd = devices[i][3] or nil partition_two_mtd = devices[i][4] or nil @@ -80,15 +81,17 @@ function index() end function action_reboot() + local uci = require "luci.model.uci".cursor() luci.template.render("admin_system/applyreboot", { title = luci.i18n.translate("Rebooting..."), msg = luci.i18n.translate("The system is rebooting now.
DO NOT POWER OFF THE DEVICE!
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" + addr = luci.ip.new(uci:get("network", "lan", "ipaddr")) or "192.168.1.1" }) luci.sys.reboot() end function action_altreboot() + local uci = require "luci.model.uci".cursor() local zyxelFlagPartition, zyxelBootFlag, zyxelNewBootFlag, errorCode, curEnvSetting, newEnvSetting errorMessage = "" errorCode = 0 @@ -162,7 +165,7 @@ function action_altreboot() luci.template.render("admin_system/applyreboot", { title = luci.i18n.translate("Rebooting..."), msg = luci.i18n.translate("The system is rebooting to an alternative partition now.
DO NOT POWER OFF THE DEVICE!
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" + addr = luci.ip.new(uci:get("network", "lan", "ipaddr")) or "192.168.1.1" }) luci.sys.reboot() else @@ -179,6 +182,7 @@ function action_altreboot() end function action_poweroff() + local uci = require "luci.model.uci".cursor() if luci.http.formvalue("cancel") then luci.http.redirect(luci.dispatcher.build_url('admin/system/advanced_reboot')) return @@ -194,7 +198,7 @@ function action_poweroff() luci.template.render("admin_system/applyreboot", { title = luci.i18n.translate("Shutting down..."), msg = luci.i18n.translate("The system is shutting down now.
DO NOT POWER OFF THE DEVICE!
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" + addr = luci.ip.new(uci:get("network", "lan", "ipaddr")) or "192.168.1.1" }) luci.sys.call("/sbin/poweroff") end diff --git a/applications/luci-app-advanced-reboot/po/ru/advanced-reboot.po b/applications/luci-app-advanced-reboot/po/ru/advanced-reboot.po index be9d2d782..75d463677 100644 --- a/applications/luci-app-advanced-reboot/po/ru/advanced-reboot.po +++ b/applications/luci-app-advanced-reboot/po/ru/advanced-reboot.po @@ -12,8 +12,6 @@ msgstr "" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" "Language: ru\n" -"Project-Info: Это технический перевод, не дословный. Главное-удобный русский " -"интерфейс, все проверялось в графическом режиме, совместим с другими apps\n" msgid "Action" msgstr "Действие" @@ -162,4 +160,4 @@ msgid "Warning: This system does not support powering off!" msgstr "Внимание: Эта система не поддерживает отключение питания!" msgid "to" -msgstr "к" +msgstr "" 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 index 604074ad3..60f586ded 100644 --- a/applications/luci-app-attendedsysupgrade/root/www/luci-static/resources/attendedsysupgrade.js +++ b/applications/luci-app-attendedsysupgrade/root/www/luci-static/resources/attendedsysupgrade.js @@ -373,7 +373,7 @@ function server_request(request_dict, path, callback) { error_box("No firmware created due to image size. Try again with less packages selected.") } else if (request.status === 422) { - var package_missing = response.getResponseHeader("X-Unknown-Package"); + var package_missing = request.getResponseHeader("X-Unknown-Package"); error_box("Unknown package in request: " + package_missing + "") } else if (request.status === 500) { request_json = JSON.parse(request_text) diff --git a/applications/luci-app-commands/luasrc/view/commands.htm b/applications/luci-app-commands/luasrc/view/commands.htm index f094e186d..3b361558e 100644 --- a/applications/luci-app-commands/luasrc/view/commands.htm +++ b/applications/luci-app-commands/luasrc/view/commands.htm @@ -136,7 +136,7 @@ uci:foreach("luci", "command", function(s) commands[#commands+1] = s end) %> -
"> +

<%:Custom Commands%>

diff --git a/applications/luci-app-cshark/luasrc/controller/cshark.lua b/applications/luci-app-cshark/luasrc/controller/cshark.lua index 4d9bbba29..43410a004 100644 --- a/applications/luci-app-cshark/luasrc/controller/cshark.lua +++ b/applications/luci-app-cshark/luasrc/controller/cshark.lua @@ -53,7 +53,13 @@ function cshark_iface_dump_start(ifname, value, flag, filter) luci.http.prepare_content("text/plain") - local res = os.execute("(/sbin/cshark -i " .. ifname .. " -" .. flag .. " " .. value .. " -p /tmp/cshark-luci.pid " .. filter .. " > /tmp/cshark-luci.out 2>&1) &") + local res = os.execute("(/sbin/cshark -i %s -%s %s -p /tmp/cshark-luci.pid %s > /tmp/cshark-luci.out 2>&1) &" %{ + luci.util.shellquote(ifname), + luci.util.shellquote(flag), + luci.util.shellquote(value), + luci.util.shellquote(filter) + }) + luci.http.write(tostring(res)) end diff --git a/applications/luci-app-ddns/Makefile b/applications/luci-app-ddns/Makefile index 50365e521..06dbefbcf 100644 --- a/applications/luci-app-ddns/Makefile +++ b/applications/luci-app-ddns/Makefile @@ -16,7 +16,7 @@ PKG_VERSION:=2.4.9 # Release == build # increase on changes of translation files -PKG_RELEASE:=1 +PKG_RELEASE:=2 PKG_LICENSE:=Apache-2.0 PKG_MAINTAINER:=Christian Schoenebeck diff --git a/applications/luci-app-ddns/luasrc/controller/ddns.lua b/applications/luci-app-ddns/luasrc/controller/ddns.lua index 3d31e4e0b..5f4a5118c 100755 --- a/applications/luci-app-ddns/luasrc/controller/ddns.lua +++ b/applications/luci-app-ddns/luasrc/controller/ddns.lua @@ -301,7 +301,7 @@ function startstop(section, enabled) uci:unload("ddns") -- start ddns-updater for section - local command = luci_helper .. [[ -S ]] .. section .. [[ -- start]] + local command = "%s -S %s -- start" %{ luci_helper, UTIL.shellquote(section) } os.execute(command) NX.nanosleep(3) -- 3 seconds "show time" diff --git a/applications/luci-app-ddns/luasrc/model/cbi/ddns/detail.lua b/applications/luci-app-ddns/luasrc/model/cbi/ddns/detail.lua index a8f4cbf7a..977dbe34b 100644 --- a/applications/luci-app-ddns/luasrc/model/cbi/ddns/detail.lua +++ b/applications/luci-app-ddns/luasrc/model/cbi/ddns/detail.lua @@ -1229,7 +1229,7 @@ if DDNS.has_proxy or ( ( m:get(section, "proxy") or "" ) ~= "" ) then elseif DDNS.has_proxy then local ipv6 = usev6:formvalue(section) or "0" local force = fipv:formvalue(section) or "0" - local command = CRTL.luci_helper .. [[ -]] + local command = CTRL.luci_helper .. [[ -]] if (ipv6 == 1) then command = command .. [[6]] end if (force == 1) then command = command .. [[f]] end command = command .. [[p ]] .. value .. [[ -- verify_proxy]] diff --git a/applications/luci-app-dnscrypt-proxy/Makefile b/applications/luci-app-dnscrypt-proxy/Makefile index 4b632b8d0..d34fec87d 100644 --- a/applications/luci-app-dnscrypt-proxy/Makefile +++ b/applications/luci-app-dnscrypt-proxy/Makefile @@ -5,7 +5,7 @@ include $(TOPDIR)/rules.mk LUCI_TITLE:=LuCI support for DNSCrypt-Proxy -LUCI_DEPENDS:=+uclient-fetch +dnscrypt-proxy +LUCI_DEPENDS:=+uclient-fetch +dnscrypt-proxy +luci-lib-httpprotoutils LUCI_PKGARCH:=all include ../../luci.mk diff --git a/applications/luci-app-dnscrypt-proxy/luasrc/controller/dnscrypt-proxy.lua b/applications/luci-app-dnscrypt-proxy/luasrc/controller/dnscrypt-proxy.lua index 9f6472e7d..ca078f0cd 100644 --- a/applications/luci-app-dnscrypt-proxy/luasrc/controller/dnscrypt-proxy.lua +++ b/applications/luci-app-dnscrypt-proxy/luasrc/controller/dnscrypt-proxy.lua @@ -15,9 +15,9 @@ function index() entry({"admin", "services", "dnscrypt-proxy", "tab_from_cbi"}, cbi("dnscrypt-proxy/overview_tab", {hideresetbtn=true, hidesavebtn=true}), _("Overview"), 10).leaf = true entry({"admin", "services", "dnscrypt-proxy", "logfile"}, call("logread"), _("View Logfile"), 20).leaf = true entry({"admin", "services", "dnscrypt-proxy", "advanced"}, firstchild(), _("Advanced"), 100) - entry({"admin", "services", "dnscrypt-proxy", "advanced", "configuration"}, cbi("dnscrypt-proxy/configuration_tab"), _("Edit DNSCrypt-Proxy Configuration"), 110).leaf = true - entry({"admin", "services", "dnscrypt-proxy", "advanced", "cfg_dnsmasq"}, cbi("dnscrypt-proxy/cfg_dnsmasq_tab"), _("Edit Dnsmasq Configuration"), 120).leaf = true - entry({"admin", "services", "dnscrypt-proxy", "advanced", "cfg_resolvcrypt"}, cbi("dnscrypt-proxy/cfg_resolvcrypt_tab"), _("Edit Resolvcrypt Configuration"), 130).leaf = true + entry({"admin", "services", "dnscrypt-proxy", "advanced", "configuration"}, form("dnscrypt-proxy/configuration_tab"), _("Edit DNSCrypt-Proxy Configuration"), 110).leaf = true + entry({"admin", "services", "dnscrypt-proxy", "advanced", "cfg_dnsmasq"}, form("dnscrypt-proxy/cfg_dnsmasq_tab"), _("Edit Dnsmasq Configuration"), 120).leaf = true + entry({"admin", "services", "dnscrypt-proxy", "advanced", "cfg_resolvcrypt"}, form("dnscrypt-proxy/cfg_resolvcrypt_tab"), _("Edit Resolvcrypt Configuration"), 130).leaf = true entry({"admin", "services", "dnscrypt-proxy", "advanced", "view_reslist"}, call("view_reslist"), _("View Resolver List"), 140).leaf = true end diff --git a/applications/luci-app-dnscrypt-proxy/luasrc/model/cbi/dnscrypt-proxy/overview_tab.lua b/applications/luci-app-dnscrypt-proxy/luasrc/model/cbi/dnscrypt-proxy/overview_tab.lua index 999c81dee..8f0e3224b 100644 --- a/applications/luci-app-dnscrypt-proxy/luasrc/model/cbi/dnscrypt-proxy/overview_tab.lua +++ b/applications/luci-app-dnscrypt-proxy/luasrc/model/cbi/dnscrypt-proxy/overview_tab.lua @@ -4,7 +4,6 @@ local fs = require("nixio.fs") local uci = require("luci.model.uci").cursor() local util = require("luci.util") -local date = require("luci.http.protocol.date") local res_input = "/usr/share/dnscrypt-proxy/dnscrypt-resolvers.csv" local res_dir = fs.dirname(res_input) local dump = util.ubus("network.interface", "dump", {}) @@ -12,6 +11,11 @@ local plug_cnt = tonumber(luci.sys.exec("env -i /usr/sbin/dnscrypt-proxy --vers local res_list = {} local url = "https://raw.githubusercontent.com/dyne/dnscrypt-proxy/master/dnscrypt-resolvers.csv" +local _, date = pcall(require, "luci.http.date") +if not date then + _, date = pcall(require, "luci.http.protocol.date") +end + if not fs.access(res_input) then if not fs.access("/lib/libustream-ssl.so") then m = SimpleForm("error", nil, translate("No default resolver list and no SSL support available.
") diff --git a/applications/luci-app-dnscrypt-proxy/po/ja/dnscrypt-proxy.po b/applications/luci-app-dnscrypt-proxy/po/ja/dnscrypt-proxy.po index 3a081a352..e35efa871 100644 --- a/applications/luci-app-dnscrypt-proxy/po/ja/dnscrypt-proxy.po +++ b/applications/luci-app-dnscrypt-proxy/po/ja/dnscrypt-proxy.po @@ -7,7 +7,7 @@ msgstr "" "Language-Team: \n" "MIME-Version: 1.0\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: Poedit 2.0.4\n" +"X-Generator: Poedit 2.0.7\n" "Last-Translator: INAGAKI Hiroshi \n" "Plural-Forms: nplurals=1; plural=0;\n" "Language: ja\n" @@ -79,6 +79,8 @@ msgstr "Dnsmasq オプション" msgid "" "Download the current resolver list from 'github.com/dyne/dnscrypt-proxy'." msgstr "" +"現在のリゾルバ リストを 'github.com/dyne/dnscrypt-proxy' からダウンロードしま" +"す。" msgid "Edit DNSCrypt-Proxy Configuration" msgstr "DNSCrypt-Proxy 設定の編集" @@ -164,6 +166,8 @@ msgid "" "Please install a 'libustream-ssl' library to download the current resolver " "list from 'github.com/dyne/dnscrypt-proxy'." msgstr "" +"現在のリゾルバ リストを 'github.com/dyne/dnscrypt-proxy' からダウンロードする" +"ために、 'libustream-ssl' ライブラリをインストールしてください。" msgid "" "Please install a resolver list to '/usr/share/dnscrypt-proxy/dnscrypt-" @@ -275,14 +279,3 @@ msgstr "ログファイルの確認" msgid "View Resolver List" msgstr "リゾルバ リストの確認" - -#~ msgid "Download the current resolver list from 'download.dnscrypt.org'." -#~ msgstr "" -#~ "現在のリゾルバ リストを 'download.dnscrypt.org' からダウンロードします。" - -#~ msgid "" -#~ "Please install a 'libustream-ssl' library to download the current " -#~ "resolver list from 'download.dnscrypt.org'." -#~ msgstr "" -#~ "現在のリゾルバ リストを 'download.dnscrypt.org' からダウンロードするため" -#~ "に、 'libustream-ssl' ライブラリをインストールしてください。" diff --git a/applications/luci-app-firewall/luasrc/controller/firewall.lua b/applications/luci-app-firewall/luasrc/controller/firewall.lua index 5a6ab0ad3..4fe7770ef 100644 --- a/applications/luci-app-firewall/luasrc/controller/firewall.lua +++ b/applications/luci-app-firewall/luasrc/controller/firewall.lua @@ -18,6 +18,6 @@ function index() _("Traffic Rules"), 30).leaf = true entry({"admin", "network", "firewall", "custom"}, - cbi("firewall/custom"), + form("firewall/custom"), _("Custom Rules"), 40).leaf = true end diff --git a/applications/luci-app-freifunk-diagnostics/luasrc/controller/freifunk/diag.lua b/applications/luci-app-freifunk-diagnostics/luasrc/controller/freifunk/diag.lua index 7bb47612b..92b3afc80 100644 --- a/applications/luci-app-freifunk-diagnostics/luasrc/controller/freifunk/diag.lua +++ b/applications/luci-app-freifunk-diagnostics/luasrc/controller/freifunk/diag.lua @@ -33,7 +33,7 @@ function diag_command(cmd, addr) if addr and addr:match("^[a-zA-Z0-9%-%.:_]+$") then luci.http.prepare_content("text/plain") - local util = io.popen(cmd % addr) + local util = io.popen(cmd % luci.util.shellquote(addr)) if util then while true do local ln = util:read("*l") @@ -52,21 +52,21 @@ function diag_command(cmd, addr) end function diag_ping(addr) - diag_command("ping -c 5 -W 1 %q 2>&1", addr) + diag_command("ping -c 5 -W 1 %s 2>&1", addr) end function diag_traceroute(addr) - diag_command("traceroute -q 1 -w 1 -n %q 2>&1", addr) + diag_command("traceroute -q 1 -w 1 -n %s 2>&1", addr) end function diag_nslookup(addr) - diag_command("nslookup %q 2>&1", addr) + diag_command("nslookup %s 2>&1", addr) end function diag_ping6(addr) - diag_command("ping6 -c 5 %q 2>&1", addr) + diag_command("ping6 -c 5 %s 2>&1", addr) end function diag_traceroute6(addr) - diag_command("traceroute6 -q 1 -w 2 -n %q 2>&1", addr) + diag_command("traceroute6 -q 1 -w 2 -n %s 2>&1", addr) end diff --git a/applications/luci-app-freifunk-diagnostics/luasrc/view/freifunk/diagnostics.htm b/applications/luci-app-freifunk-diagnostics/luasrc/view/freifunk/diagnostics.htm index fe205d053..eac1ecdcf 100644 --- a/applications/luci-app-freifunk-diagnostics/luasrc/view/freifunk/diagnostics.htm +++ b/applications/luci-app-freifunk-diagnostics/luasrc/view/freifunk/diagnostics.htm @@ -53,7 +53,7 @@ local has_traceroute6 = fs.access("/usr/bin/traceroute6") } //]]> -"> +

<%:Diagnostics%>

diff --git a/applications/luci-app-lxc/Makefile b/applications/luci-app-lxc/Makefile index 9f313dfb1..85cae5c40 100644 --- a/applications/luci-app-lxc/Makefile +++ b/applications/luci-app-lxc/Makefile @@ -7,7 +7,7 @@ include $(TOPDIR)/rules.mk LUCI_TITLE:=LXC management Web UI -LUCI_DEPENDS:=+luci-mod-admin-full +lxc +lxc-create +liblxc +rpcd-mod-lxc +getopt +xz +LUCI_DEPENDS:=+luci-mod-admin-full +lxc +lxc-attach +lxc-console +lxc-create +liblxc +rpcd-mod-lxc +getopt LUCI_PKGARCH:=all PKG_MAINTAINER:=Petar Koretic diff --git a/applications/luci-app-lxc/luasrc/controller/lxc.lua b/applications/luci-app-lxc/luasrc/controller/lxc.lua index ea7adbafb..cc490f0b8 100644 --- a/applications/luci-app-lxc/luasrc/controller/lxc.lua +++ b/applications/luci-app-lxc/luasrc/controller/lxc.lua @@ -14,14 +14,11 @@ Author: Petar Koretic ]]-- -module("luci.controller.lxc", package.seeall) - -require "ubus" -local conn = ubus.connect() -if not conn then - error("Failed to connect to ubus") -end +local uci = require "luci.model.uci" +local util = require "luci.util" +local nixio = require "nixio" +module("luci.controller.lxc", package.seeall) function fork_exec(command) local pid = nixio.fork() @@ -71,55 +68,52 @@ function index() end function lxc_get_downloadable() - luci.http.prepare_content("application/json") - - local f = io.popen('uname -m', 'r') - local target = f:read('*a') - f:close() - target = target:gsub("^%s*(.-)%s*$", "%1") - + local target = lxc_get_arch_target() local templates = {} - local f = io.popen('lxc-create -n just_want_to_list_available_lxc_templates -t download -- --list', 'r') + local f = io.popen('sh /usr/share/lxc/templates/lxc-download --list --no-validate --server %s' + % util.shellquote(uci.cursor():get("lxc", "lxc", "url")), 'r') + local line for line in f:lines() do - local dist,version = line:match("^(%S+)%s+(%S+)%s+" .. target .. "%s+default%s+%S+$") - if dist~=nil and version~=nil then templates[#templates + 1] = dist .. ":" .. version end + local dist, version, dist_target = line:match("^(%S+)%s+(%S+)%s+(%S+)%s+default%s+%S+$") + if dist and version and dist_target == target then + templates[#templates+1] = "%s:%s" %{ dist, version } + end end f:close() + + luci.http.prepare_content("application/json") luci.http.write_json(templates) end function lxc_create(lxc_name, lxc_template) luci.http.prepare_content("text/plain") - local uci = require("uci").cursor() - - local url = uci:get("lxc", "lxc", "url") - if not pcall(dofile, "/etc/openwrt_release") then return luci.http.write("1") end - local f = io.popen('uname -m', 'r') - local target = f:read('*a') - f:close() - target = target:gsub("^%s*(.-)%s*$", "%1") - - local lxc_dist = lxc_template:gsub("(.*):(.*)", '%1') - local lxc_release = lxc_template:gsub("(.*):(.*)", '%2') - - local data = conn:call("lxc", "create", { name = lxc_name, template = "download", args = { "--server", url, "--no-validate", "--dist", lxc_dist, "--release", lxc_release, "--arch", target } } ) - - luci.http.write(data) + local lxc_dist, lxc_release = lxc_template:match("^(.+):(.+)$") + + luci.http.write(util.ubus("lxc", "create", { + name = lxc_name, + template = "download", + args = { + "--server", uci.cursor():get("lxc", "lxc", "url"), + "--no-validate", + "--dist", lxc_dist, + "--release", lxc_release, + "--arch", lxc_get_arch_target() + } + })) end function lxc_action(lxc_action, lxc_name) - luci.http.prepare_content("application/json") - - local data, ec = conn:call("lxc", lxc_action, lxc_name and { name = lxc_name} or {} ) + local data, ec = util.ubus("lxc", lxc_action, lxc_name and { name = lxc_name } or {}) + luci.http.prepare_content("application/json") luci.http.write_json(ec and {} or data) end @@ -165,3 +159,22 @@ function lxc_configuration_set(lxc_name) luci.http.write("0") end +function lxc_get_arch_target() + local target = nixio.uname().machine + local target_map = { + armv5 = "armel", + armv6 = "armel", + armv7 = "armhf", + armv8 = "arm64", + x86_64 = "amd64" + } + + local k, v + for k, v in pairs(target_map) do + if target:find(k) then + return v + end + end + + return target +end diff --git a/applications/luci-app-lxc/root/etc/config/lxc b/applications/luci-app-lxc/root/etc/config/lxc index 5572c735f..3b35951e1 100644 --- a/applications/luci-app-lxc/root/etc/config/lxc +++ b/applications/luci-app-lxc/root/etc/config/lxc @@ -1,6 +1,3 @@ -# -# lxc uci configuration -# config lxc 'lxc' - option url 'virtualwrt.org/containers/' + option url 'images.linuxcontainers.org' diff --git a/applications/luci-app-mwan3/Makefile b/applications/luci-app-mwan3/Makefile index d65cd3af1..c719cb134 100644 --- a/applications/luci-app-mwan3/Makefile +++ b/applications/luci-app-mwan3/Makefile @@ -7,7 +7,7 @@ include $(TOPDIR)/rules.mk LUCI_TITLE:=LuCI support for the MWAN3 multiwan hotplug script -LUCI_DEPENDS:=+mwan3 +luci-mod-admin-full +luci-app-firewall +luci-lib-nixio +LUCI_DEPENDS:=+mwan3 +libuci-lua +luci-mod-admin-full +luci-app-firewall +luci-lib-nixio LUCI_PKGARCH:=all PKG_LICENSE:=GPLv2 diff --git a/applications/luci-app-mwan3/luasrc/controller/mwan3.lua b/applications/luci-app-mwan3/luasrc/controller/mwan3.lua index 64ee9f548..d5fc4a3ed 100644 --- a/applications/luci-app-mwan3/luasrc/controller/mwan3.lua +++ b/applications/luci-app-mwan3/luasrc/controller/mwan3.lua @@ -56,7 +56,7 @@ function index() arcombine(cbi("mwan/rule"), cbi("mwan/ruleconfig")), _("Rules"), 40).leaf = true entry({"admin", "network", "mwan", "notify"}, - cbi("mwan/notify"), + form("mwan/notify"), _("Notification"), 50).leaf = true end @@ -85,7 +85,8 @@ function diagnosticsData(interface, task) function getInterfaceNumber(interface) local number = 0 local interfaceNumber - uci.cursor():foreach("mwan3", "interface", + local uci = require "luci.model.uci".cursor() + uci:foreach("mwan3", "interface", function (section) number = number+1 if section[".name"] == interface then @@ -98,7 +99,7 @@ function diagnosticsData(interface, task) function diag_command(cmd, addr) if addr and addr:match("^[a-zA-Z0-9%-%.:_]+$") then - local util = io.popen(cmd % addr) + local util = io.popen(cmd % ut.shellquote(addr)) if util then while true do local ln = util:read("*l") @@ -130,7 +131,7 @@ function diagnosticsData(interface, task) local results = "" local number = getInterfaceNumber(interface) - local uci = uci.cursor(nil, "/var/state") + local uci = require "luci.model.uci".cursor(nil, "/var/state") local device = uci:get("network", interface, "ifname") luci.http.prepare_content("text/plain") @@ -138,7 +139,7 @@ function diagnosticsData(interface, task) if task == "ping_gateway" then local gateway = get_gateway(interface) if gateway ~= nil then - diag_command("ping -c 5 -W 1 %q 2>&1", gateway) + diag_command("ping -c 5 -W 1 %s 2>&1", gateway) else luci.http.prepare_content("text/plain") luci.http.write(string.format("No gateway for interface %s found.", interface)) @@ -147,7 +148,7 @@ function diagnosticsData(interface, task) local trackips = uci:get("mwan3", interface, "track_ip") if #trackips > 0 then for i in pairs(trackips) do - diag_command("ping -c 5 -W 1 %q 2>&1", trackips[i]) + diag_command("ping -c 5 -W 1 %s 2>&1", trackips[i]) end else luci.http.write(string.format("No tracking Hosts for interface %s defined.", interface)) @@ -185,10 +186,10 @@ function diagnosticsData(interface, task) luci.http.write(string.format("Routing table %s for interface %s not found", number, interface)) end elseif task == "hotplug_ifup" then - os.execute(string.format("/usr/sbin/mwan3 ifup %s", interface)) + os.execute(string.format("/usr/sbin/mwan3 ifup %s", ut.shellquote(interface))) luci.http.write(string.format("Hotplug ifup sent to interface %s", interface)) elseif task == "hotplug_ifdown" then - os.execute(string.format("/usr/sbin/mwan3 ifdown %s", interface)) + os.execute(string.format("/usr/sbin/mwan3 ifdown %s", ut.shellquote(interface))) luci.http.write(string.format("Hotplug ifdown sent to interface %s", interface)) else luci.http.write("Unknown task") diff --git a/applications/luci-app-mwan3/luasrc/model/cbi/mwan/interface.lua b/applications/luci-app-mwan3/luasrc/model/cbi/mwan/interface.lua index 4b1a070d1..162b388d1 100644 --- a/applications/luci-app-mwan3/luasrc/model/cbi/mwan/interface.lua +++ b/applications/luci-app-mwan3/luasrc/model/cbi/mwan/interface.lua @@ -3,42 +3,43 @@ -- Licensed to the public under the GNU General Public License v2. dsp = require "luci.dispatcher" +uci = require "uci" -function interfaceWarnings(overview, count) +function interfaceWarnings(overview, count, iface_max) local warnings = "" - if count <= 250 then - warnings = string.format("%s
", - translatef("There are currently %d of 250 supported interfaces configured", count) + if count <= iface_max then + warnings = string.format("%s
", + translatef("There are currently %d of %d supported interfaces configured", count, iface_max) ) else - warnings = string.format("%s
", - translatef("WARNING: %d interfaces are configured exceeding the maximum of 250!", count) + warnings = string.format("%s
", + translatef("WARNING: %d interfaces are configured exceeding the maximum of %d!", count, iface_max) ) end for i, k in pairs(overview) do if overview[i]["network"] == false then - warnings = warnings .. string.format("%s
", + warnings = warnings .. string.format("%s
", translatef("WARNING: Interface %s are not found in /etc/config/network", i) ) end if overview[i]["default_route"] == false then - warnings = warnings .. string.format("%s
", + warnings = warnings .. string.format("%s
", translatef("WARNING: Interface %s has no default route in the main routing table", i) ) end if overview[i]["reliability"] == false then - warnings = warnings .. string.format("%s
", + warnings = warnings .. string.format("%s
", translatef("WARNING: Interface %s has a higher reliability " .. "requirement than tracking hosts (%d)", i, overview[i]["tracking"]) ) end if overview[i]["duplicate_metric"] == true then - warnings = warnings .. string.format("%s
", + warnings = warnings .. string.format("%s
", translatef("WARNING: Interface %s has a duplicate metric %s configured", i, overview[i]["metric"]) ) end @@ -103,16 +104,43 @@ function configCheck() end end ) - return overview, count + + -- calculate iface_max usage from firewall mmx_mask + function bit(p) + return 2 ^ (p - 1) + end + function hasbit(x, p) + return x % (p + p) >= p + end + function setbit(x, p) + return hasbit(x, p) and x or x + p + end + + local uci = require("uci").cursor(nil, "/var/state") + local mmx_mask = uci:get("mwan3", "globals", "mmx_mask") or "0x3F00" + local number = tonumber(mmx_mask, 16) + local bits = 0 + local iface_max = 0 + for i=1,16 do + if hasbit(number, bit(i)) then + bits = bits + 1 + iface_max = setbit( iface_max, bit(bits)) + end + end + + -- subtract blackhole, unreachable and default table from iface_max + iface_max = iface_max - 3 + + return overview, count, iface_max end m5 = Map("mwan3", translate("MWAN - Interfaces"), interfaceWarnings(configCheck())) mwan_interface = m5:section(TypedSection, "interface", nil, - translate("MWAN supports up to 250 physical and/or logical interfaces
" .. + translate("MWAN supports up to 252 physical and/or logical interfaces
" .. "MWAN requires that all interfaces have a unique metric configured in /etc/config/network
" .. - "Names must match the interface name found in /etc/config/network (see advanced tab)
" .. + "Names must match the interface name found in /etc/config/network
" .. "Names may contain characters A-Z, a-z, 0-9, _ and no spaces
" .. "Interfaces may not share the same name as configured members, policies or rules")) mwan_interface.addremove = true @@ -142,7 +170,7 @@ track_method.rawhtml = true function track_method.cfgvalue(self, s) local tracked = self.map:get(s, "track_ip") if tracked then - return self.map:get(s, "track_method") or "—" + return self.map:get(s, "track_method") or "ping" else return "—" end @@ -153,7 +181,7 @@ reliability.rawhtml = true function reliability.cfgvalue(self, s) local tracked = self.map:get(s, "track_ip") if tracked then - return self.map:get(s, "reliability") or "—" + return self.map:get(s, "reliability") or "1" else return "—" end @@ -168,7 +196,7 @@ function interval.cfgvalue(self, s) if intervalValue then return intervalValue .. "s" else - return "—" + return "5s" end else return "—" @@ -180,7 +208,7 @@ down.rawhtml = true function down.cfgvalue(self, s) local tracked = self.map:get(s, "track_ip") if tracked then - return self.map:get(s, "down") or "—" + return self.map:get(s, "down") or "3" else return "—" end @@ -191,7 +219,7 @@ up.rawhtml = true function up.cfgvalue(self, s) local tracked = self.map:get(s, "track_ip") if tracked then - return self.map:get(s, "up") or "—" + return self.map:get(s, "up") or "3" else return "—" end diff --git a/applications/luci-app-mwan3/luasrc/model/cbi/mwan/interfaceconfig.lua b/applications/luci-app-mwan3/luasrc/model/cbi/mwan/interfaceconfig.lua index 3a896d3bc..a43950267 100644 --- a/applications/luci-app-mwan3/luasrc/model/cbi/mwan/interfaceconfig.lua +++ b/applications/luci-app-mwan3/luasrc/model/cbi/mwan/interfaceconfig.lua @@ -171,7 +171,7 @@ metric = mwan_interface:option(DummyValue, "metric", translate("Metric"), translate("This displays the metric assigned to this interface in /etc/config/network")) metric.rawhtml = true function metric.cfgvalue(self, s) - local uci = uci.cursor(nil, "/var/state") + local uci = require "luci.model.uci".cursor(nil, "/var/state") local metric = uci:get("network", arg[1], "metric") if metric then return metric diff --git a/applications/luci-app-mwan3/luasrc/model/cbi/mwan/notify.lua b/applications/luci-app-mwan3/luasrc/model/cbi/mwan/notify.lua index 6f87a3d75..4c6e21003 100644 --- a/applications/luci-app-mwan3/luasrc/model/cbi/mwan/notify.lua +++ b/applications/luci-app-mwan3/luasrc/model/cbi/mwan/notify.lua @@ -23,7 +23,11 @@ f = m5:section(SimpleSection, nil, "
" .. "There are three main environment variables that are passed to this script.
" .. "
" .. - "$ACTION Either \"ifup\" or \"ifdown\"
" .. + "$ACTION
" .. + "* \"ifup\" Is called by netifd and mwan3track
" .. + "* \"ifdown\" Is called by netifd and mwan3track
" .. + "* \"connected\" Is only called by mwan3track if tracking was successful
" .. + "* \"disconnected\" Is only called by mwan3track if tracking has failed
" .. "$INTERFACE Name of the interface which went up or down (e.g. \"wan\" or \"wwan\")
" .. "$DEVICE Physical device name which interface went up or down (e.g. \"eth0\" or \"wwan0\")
" .. "
")) diff --git a/applications/luci-app-mwan3/luasrc/model/cbi/mwan/policy.lua b/applications/luci-app-mwan3/luasrc/model/cbi/mwan/policy.lua index 7f1278206..4543260f6 100644 --- a/applications/luci-app-mwan3/luasrc/model/cbi/mwan/policy.lua +++ b/applications/luci-app-mwan3/luasrc/model/cbi/mwan/policy.lua @@ -3,6 +3,7 @@ -- Licensed to the public under the GNU General Public License v2. dsp = require "luci.dispatcher" +uci = require "uci" function policyCheck() @@ -24,8 +25,8 @@ function policyError(policy_error) local warnings = "" for i, k in pairs(policy_error) do if policy_error[i] == true then - warnings = warnings .. string.format("%s
", - translatef("WARNING: Policie %s has exceeding the maximum name of 15 characters", i) + warnings = warnings .. string.format("%s
", + translatef("WARNING: Policy %s has exceeding the maximum name of 15 characters", i) ) end end @@ -38,9 +39,11 @@ m5 = Map("mwan3", translate("MWAN - Policies"), mwan_policy = m5:section(TypedSection, "policy", nil, translate("Policies are profiles grouping one or more members controlling how MWAN distributes traffic
" .. - "Member interfaces with lower metrics are used first. Interfaces with the same metric load-balance
" .. + "Member interfaces with lower metrics are used first
" .. + "Member interfaces with the same metric will be load-balanced
" .. "Load-balanced member interfaces distribute more traffic out those with higher weights
" .. - "Names may contain characters A-Z, a-z, 0-9, _ and no spaces. Names must be 15 characters or less
" .. + "Names may contain characters A-Z, a-z, 0-9, _ and no spaces
" .. + "Names must be 15 characters or less
" .. "Policies may not share the same name as configured interfaces, members or rules")) mwan_policy.addremove = true mwan_policy.dynamic = false diff --git a/applications/luci-app-mwan3/luasrc/model/cbi/mwan/rule.lua b/applications/luci-app-mwan3/luasrc/model/cbi/mwan/rule.lua index cb2a99537..f0b94bd0b 100644 --- a/applications/luci-app-mwan3/luasrc/model/cbi/mwan/rule.lua +++ b/applications/luci-app-mwan3/luasrc/model/cbi/mwan/rule.lua @@ -3,6 +3,7 @@ -- Licensed to the public under the GNU General Public License v2. dsp = require "luci.dispatcher" +uci = require "uci" function ruleCheck() @@ -28,7 +29,7 @@ function ruleWarn(rule_error) local warnings = "" for i, k in pairs(rule_error) do if rule_error[i] == true then - warnings = warnings .. string.format("%s
", + warnings = warnings .. string.format("%s
", translatef("WARNING: Rule %s have a port configured with no or improper protocol specified!", i) ) end diff --git a/applications/luci-app-mwan3/luasrc/view/mwan/overview_status_interface.htm b/applications/luci-app-mwan3/luasrc/view/mwan/overview_status_interface.htm index 86b5ac696..49d120c1a 100644 --- a/applications/luci-app-mwan3/luasrc/view/mwan/overview_status_interface.htm +++ b/applications/luci-app-mwan3/luasrc/view/mwan/overview_status_interface.htm @@ -15,29 +15,35 @@ XHR.poll(5, '<%=luci.dispatcher.build_url("admin", "status", "mwan", "interface_ for ( var iface in status.interfaces) { var state = ''; + var css = '' switch (status.interfaces[iface].status) { case 'online': - state = '<%:Online (tracking active)%>'; - break; - case 'notMonitored': - state = '<%:Online (tracking off)%>'; + state = '<%:Online%>'; + css = 'success'; break; case 'offline': state = '<%:Offline%>'; + css = 'danger'; break; default: state = '<%:Disabled%>'; + css = 'warning'; break; } statusview += String.format( + '
', + css + ); + statusview += String.format( '
Interface: %s
', iface ); statusview += String.format( - '
Status: %s


', + '
Status: %s
', state ); + statusview += '
' } statusDiv.innerHTML = statusview; } @@ -49,9 +55,21 @@ XHR.poll(5, '<%=luci.dispatcher.build_url("admin", "status", "mwan", "interface_ ); //]]> + +
<%:MWAN Interfaces%>
- <%:Loading%><%:Collecting data...%> + <%:Loading%> + <%:Collecting data...%>
diff --git a/applications/luci-app-mwan3/luasrc/view/mwan/status_detail.htm b/applications/luci-app-mwan3/luasrc/view/mwan/status_detail.htm index 70eac7252..bcc23beb3 100644 --- a/applications/luci-app-mwan3/luasrc/view/mwan/status_detail.htm +++ b/applications/luci-app-mwan3/luasrc/view/mwan/status_detail.htm @@ -18,9 +18,7 @@ XHR.poll(5, '<%=luci.dispatcher.build_url("admin", "status", "mwan", "detailed_status")%>', null, function(x) { - var legend = document.getElementById('diag-rc-legend'); var output = document.getElementById('diag-rc-output'); - legend.style.display = 'none'; output.innerHTML = String.format('
%h
', x.responseText); } ); @@ -32,9 +30,9 @@
<%:INFO: MWAN not running%>
<%end%>
- <%:Collecting data...%> <%:Loading%> + <%:Collecting data...%>
diff --git a/applications/luci-app-mwan3/luasrc/view/mwan/status_diagnostics.htm b/applications/luci-app-mwan3/luasrc/view/mwan/status_diagnostics.htm index f1c5d8fd9..22f4734dd 100644 --- a/applications/luci-app-mwan3/luasrc/view/mwan/status_diagnostics.htm +++ b/applications/luci-app-mwan3/luasrc/view/mwan/status_diagnostics.htm @@ -31,7 +31,6 @@ function update_status(iface, task) { - var legend = document.getElementById('diag-rc-legend'); var output = document.getElementById('diag-rc-output'); output.innerHTML = @@ -45,7 +44,6 @@ stxhr.post('<%=url('admin/status/mwan')%>/diagnostics_display' + '/' + iface + '/' + task, { token: '<%=token%>' }, function(x) { - legend.style.display = 'none'; output.innerHTML = String.format('
%h
', x.responseText); } ); @@ -86,7 +84,6 @@
diff --git a/applications/luci-app-mwan3/luasrc/view/mwan/status_interface.htm b/applications/luci-app-mwan3/luasrc/view/mwan/status_interface.htm index cb476967f..4518bd658 100644 --- a/applications/luci-app-mwan3/luasrc/view/mwan/status_interface.htm +++ b/applications/luci-app-mwan3/luasrc/view/mwan/status_interface.htm @@ -15,6 +15,7 @@ -<%+mwan/overview_status_interface%> - +
+ <%+mwan/overview_status_interface%> +
<%+footer%> diff --git a/applications/luci-app-mwan3/luasrc/view/mwan/status_troubleshooting.htm b/applications/luci-app-mwan3/luasrc/view/mwan/status_troubleshooting.htm index 77d009231..f60e0da0a 100644 --- a/applications/luci-app-mwan3/luasrc/view/mwan/status_troubleshooting.htm +++ b/applications/luci-app-mwan3/luasrc/view/mwan/status_troubleshooting.htm @@ -18,9 +18,7 @@ XHR.poll(15, '<%=luci.dispatcher.build_url("admin", "status", "mwan", "troubleshooting_display")%>', null, function(x) { - var legend = document.getElementById('diag-rc-legend'); var output = document.getElementById('diag-rc-output'); - legend.style.display = 'none'; output.innerHTML = String.format('
%h
', x.responseText); } ); @@ -32,9 +30,9 @@
<%:INFO: MWAN not running%>
<%end%>
- <%:Collecting data...%> <%:Loading%> + <%:Collecting data...%>
diff --git a/applications/luci-app-mwan3/po/ja/mwan3.po b/applications/luci-app-mwan3/po/ja/mwan3.po index 4b3662a42..6ee351c4c 100644 --- a/applications/luci-app-mwan3/po/ja/mwan3.po +++ b/applications/luci-app-mwan3/po/ja/mwan3.po @@ -103,6 +103,9 @@ msgstr "ホットプラグ ifdown" msgid "Hotplug ifup" msgstr "ホットプラグ ifup" +msgid "INFO: MWAN not running" +msgstr "" + msgid "IPset" msgstr "IPset" @@ -174,8 +177,8 @@ msgstr "" msgid "MWAN Interface Configuration - %s" msgstr "MWAN インターフェース設定 - %s" -msgid "MWAN Interface Live Status" -msgstr "MWAN インターフェース Live ステータス" +msgid "MWAN Interfaces" +msgstr "" msgid "MWAN Member Configuration - %s" msgstr "MWAN メンバー設定 - %s" @@ -195,24 +198,21 @@ msgstr "" msgid "MWAN Status - Troubleshooting" msgstr "" -msgid "MWAN status - Interface Live Status" -msgstr "" - msgid "" -"MWAN supports up to 250 physical and/or logical interfaces
MWAN " +"MWAN supports up to 252 physical and/or logical interfaces
MWAN " "requires that all interfaces have a unique metric configured in /etc/config/" "network
Names must match the interface name found in /etc/config/" -"network (see advanced tab)
Names may contain characters A-Z, a-z, 0-9, " -"_ and no spaces
Interfaces may not share the same name as configured " -"members, policies or rules" +"network
Names may contain characters A-Z, a-z, 0-9, _ and no spaces
Interfaces may not share the same name as configured members, policies or " +"rules" msgstr "" -"MWAN は、250個までの物理または論理、あるいは両方のインターフェースをサポート" +"MWAN は、252個までの物理または論理、あるいは両方のインターフェースをサポート" "します。
MWAN は、全てのインターフェースが /etc/config/network で設定さ" "れるユニークなメトリックを持つことを必要とします。
下記 \"インターフェー" "ス\" の名前は、 /etc/config/network に存在するインターフェース名と同じでなけ" -"ればなりません(詳細設定タブを確認)。
名前は A-Z, a-z, 0-9, _ を含むこ" -"とができますが、スペースは使用できません。
インターフェースには、設定済" -"みのメンバーやポリシー、ルールと同じ名前を使用することはできません。" +"ればなりません。
名前は A-Z, a-z, 0-9, _ を含むことができますが、スペー" +"スは使用できません。
インターフェースには、設定済みのメンバーやポリ" +"シー、ルールと同じ名前を使用することはできません。" msgid "" "May be entered as a single or multiple port(s) (eg \"22\" or \"80,443\") or " @@ -268,12 +268,6 @@ msgstr "オフライン" msgid "Online" msgstr "オンライン" -msgid "Online (tracking active)" -msgstr "オンライン(追跡実行中)" - -msgid "Online (tracking off)" -msgstr "オンライン(追跡オフ)" - msgid "Ping count" msgstr "Ping 回数" @@ -304,11 +298,11 @@ msgstr "ポリシー" msgid "" "Policies are profiles grouping one or more members controlling how MWAN " "distributes traffic
Member interfaces with lower metrics are used " -"first. Interfaces with the same metric load-balance
Load-balanced " -"member interfaces distribute more traffic out those with higher weights
Names may contain characters A-Z, a-z, 0-9, _ and no spaces. Names must be " -"15 characters or less
Policies may not share the same name as " -"configured interfaces, members or rules" +"first
Member interfaces with the same metric will be load-balanced
Load-balanced member interfaces distribute more traffic out those with " +"higher weights
Names may contain characters A-Z, a-z, 0-9, _ and no " +"spaces
Names must be 15 characters or less
Policies may not share " +"the same name as configured interfaces, members or rules" msgstr "" "ポリシーは、MWANがどのようにトラフィックの分配を行うかを制御する、1つ以上のメ" "ンバーをグループ化するプロファイルです。
最小のメトリックを持つメンバー " @@ -370,8 +364,8 @@ msgstr "CIDR 表記のサポート(例: \"192.168.100.0/24\")" msgid "Task" msgstr "" -msgid "There are currently %d of 250 supported interfaces configured" -msgstr "現在、250個中 %d 個のサポートされたインターフェースが設定済みです。" +msgid "There are currently %d of %d supported interfaces configured" +msgstr "現在、%d 個中 %d 個のサポートされたインターフェースが設定済みです。" msgid "" "This displays the metric assigned to this interface in /etc/config/network" @@ -395,21 +389,14 @@ msgid "" "will
be executed with each netifd hotplug interface event
on " "interfaces for which mwan3 is enabled.

There are three main " "environment variables that are passed to this script.

$ACTION " -"Either \"ifup\" or \"ifdown\"
$INTERFACE Name of the interface which " -"went up or down (e.g. \"wan\" or \"wwan\")
$DEVICE Physical device name " -"which interface went up or down (e.g. \"eth0\" or \"wwan0\")

" -msgstr "" -"このセクションでは、 \"/etc/mwan3.user\" の内容を変更することができます。" -"
このファイルは、 sysupgrade 時に保持されます。

注意:
" -"このファイルは、シェルスクリプトとして解釈されます。
スクリプトの1行目" -"は、"#!bin/sh" である必要があります(クォーテーション不要)。
# " -"で始まる行はコメントであり、実行されません。
mwan3 のカスタム動作をここ" -"に入力してください。これらは、 mwan3 が有効なインターフェースの
netifd " -"ホットプラグ インターフェース イベント毎に実行されます。

主に3つの" -"環境変数が利用可能です。

$ACTION - \"ifup\" および \"ifdown\"
$INTERFACE - Up または Down が行われたインターフェース名(例: \"wan\" や " -"\"wwan\")
$DEVICE - Up または Down が行われた物理デバイス名(例: " -"\"eth0\" や \"wwan0\")

" +"
* \"ifup\" Is called by netifd and mwan3track
* \"ifdown\" Is " +"called by netifd and mwan3track
* \"connected\" Is only called by " +"mwan3track if tracking was successful
* \"disconnected\" Is only " +"called by mwan3track if tracking has failed
$INTERFACE Name of the " +"interface which went up or down (e.g. \"wan\" or \"wwan\")
$DEVICE " +"Physical device name which interface went up or down (e.g. \"eth0\" or " +"\"wwan0\")

" +msgstr "" msgid "Tracking hostname or IP address" msgstr "追跡ホスト名または IP アドレス" @@ -441,9 +428,9 @@ msgstr "" msgid "View the content of /etc/protocols for protocol description" msgstr "" -msgid "WARNING: %d interfaces are configured exceeding the maximum of 250!" +msgid "WARNING: %d interfaces are configured exceeding the maximum of %d!" msgstr "" -"警告: %d 個のインターフェースが、最大個数の 250個 を超えて設定されています!" +"警告: %d 個のインターフェースが、最大個数の %d 個 を超えて設定されています!" msgid "WARNING: Interface %s are not found in /etc/config/network" msgstr "" @@ -459,7 +446,7 @@ msgstr "" msgid "WARNING: Interface %s has no default route in the main routing table" msgstr "" -msgid "WARNING: Policie %s has exceeding the maximum name of 15 characters" +msgid "WARNING: Policy %s has exceeding the maximum name of 15 characters" msgstr "" msgid "" @@ -503,6 +490,41 @@ msgstr "never" msgid "unreachable (reject)" msgstr "unreachable (reject)" +#~ msgid "Online (tracking active)" +#~ msgstr "オンライン(追跡実行中)" + +#~ msgid "MWAN Interface Live Status" +#~ msgstr "MWAN インターフェース Live ステータス" + +#~ msgid "Online (tracking off)" +#~ msgstr "オンライン(追跡オフ)" + +#~ msgid "" +#~ "This section allows you to modify the content of \"/etc/mwan3.user\".
The file is also preserved during sysupgrade.

Notes:
This file is interpreted as a shell script.
The first line of the " +#~ "script must be "#!/bin/sh" without quotes.
Lines beginning " +#~ "with # are comments and are not executed.
Put your custom mwan3 " +#~ "action here, they will
be executed with each netifd hotplug " +#~ "interface event
on interfaces for which mwan3 is enabled.

There are three main environment variables that are passed to this " +#~ "script.

$ACTION Either \"ifup\" or \"ifdown\"
$INTERFACE " +#~ "Name of the interface which went up or down (e.g. \"wan\" or \"wwan" +#~ "\")
$DEVICE Physical device name which interface went up or down (e." +#~ "g. \"eth0\" or \"wwan0\")

" +#~ msgstr "" +#~ "このセクションでは、 \"/etc/mwan3.user\" の内容を変更することができます。" +#~ "
このファイルは、 sysupgrade 時に保持されます。

注意: " +#~ "
このファイルは、シェルスクリプトとして解釈されます。
スクリプト" +#~ "の1行目は、"#!bin/sh" である必要があります(クォーテーション不" +#~ "要)。
# で始まる行はコメントであり、実行されません。
mwan3 のカ" +#~ "スタム動作をここに入力してください。これらは、 mwan3 が有効なインター" +#~ "フェースの
netifd ホットプラグ インターフェース イベント毎に実行され" +#~ "ます。

主に3つの環境変数が利用可能です。

$ACTION - " +#~ "\"ifup\" および \"ifdown\"
$INTERFACE - Up または Down が行われたイン" +#~ "ターフェース名(例: \"wan\" や \"wwan\")
$DEVICE - Up または Down が" +#~ "行われた物理デバイス名(例: \"eth0\" や \"wwan0\")

" + #~ msgid "Currently Configured Interfaces" #~ msgstr "設定済みインターフェース" diff --git a/applications/luci-app-mwan3/po/ru/mwan3.po b/applications/luci-app-mwan3/po/ru/mwan3.po index 8d5742c7e..11721ecc5 100644 --- a/applications/luci-app-mwan3/po/ru/mwan3.po +++ b/applications/luci-app-mwan3/po/ru/mwan3.po @@ -107,6 +107,9 @@ msgstr "Hotplug ifdown" msgid "Hotplug ifup" msgstr "Hotplug ifup" +msgid "INFO: MWAN not running" +msgstr "" + msgid "IPset" msgstr "IPset" @@ -177,8 +180,8 @@ msgstr "MWAN - Правила" msgid "MWAN Interface Configuration - %s" msgstr "Настройка интерфейсов MWAN - %s" -msgid "MWAN Interface Live Status" -msgstr "Состояние интерфейса MWAN в настоящее время" +msgid "MWAN Interfaces" +msgstr "" msgid "MWAN Member Configuration - %s" msgstr "MWAN настройка узлов - %s" @@ -198,24 +201,20 @@ msgstr "Состояние MWAN - Диагностика" msgid "MWAN Status - Troubleshooting" msgstr "Состояние MWAN - Устранение неполадок" -msgid "MWAN status - Interface Live Status" -msgstr "Состояние MWAN - Интерфейс в настоящее время" - msgid "" -"MWAN supports up to 250 physical and/or logical interfaces
MWAN " +"MWAN supports up to 252 physical and/or logical interfaces
MWAN " "requires that all interfaces have a unique metric configured in /etc/config/" "network
Names must match the interface name found in /etc/config/" -"network (see advanced tab)
Names may contain characters A-Z, a-z, 0-9, " -"_ and no spaces
Interfaces may not share the same name as configured " -"members, policies or rules" +"network
Names may contain characters A-Z, a-z, 0-9, _ and no spaces
Interfaces may not share the same name as configured members, policies or " +"rules" msgstr "" -"MWAN поддерживает до 250 физических и / или логических интерфейсов.
MWAN требует, чтобы все интерфейсы имели уникальную метрику, настроенную в " "config файле /etc/config/network.
Имена должны соответствовать имени " -"интерфейса, найденному в /etc/config/network (см. соответствующую страницу)." -"
Имена могут содержать символы A-Z, a-z, 0-9, _ и пробелы.
Интерфейсы не могут иметь одинаковые имена с настроенными узлами, " -"политиками или правилами." +"интерфейса, найденному в /etc/config/network.
Имена могут содержать " +"символы A-Z, a-z, 0-9, _ и пробелы.
Интерфейсы не могут иметь " +"одинаковые имена с настроенными узлами, политиками или правилами." msgid "" "May be entered as a single or multiple port(s) (eg \"22\" or \"80,443\") or " @@ -270,12 +269,6 @@ msgstr "Отключен" msgid "Online" msgstr "Онлайн" -msgid "Online (tracking active)" -msgstr "Онлайн (отслеживание активно)" - -msgid "Online (tracking off)" -msgstr "Онлайн (отслеживание отключено)" - msgid "Ping count" msgstr "Кол-во пинг-запросов" @@ -306,11 +299,11 @@ msgstr "Политики" msgid "" "Policies are profiles grouping one or more members controlling how MWAN " "distributes traffic
Member interfaces with lower metrics are used " -"first. Interfaces with the same metric load-balance
Load-balanced " -"member interfaces distribute more traffic out those with higher weights
Names may contain characters A-Z, a-z, 0-9, _ and no spaces. Names must be " -"15 characters or less
Policies may not share the same name as " -"configured interfaces, members or rules" +"first
Member interfaces with the same metric will be load-balanced
Load-balanced member interfaces distribute more traffic out those with " +"higher weights
Names may contain characters A-Z, a-z, 0-9, _ and no " +"spaces
Names must be 15 characters or less
Policies may not share " +"the same name as configured interfaces, members or rules" msgstr "" "Политики это профили, объединяющие один или несколько узлов, контролирующих, " "как MWAN распределяет трафик.
Сначала используются интерфейсы-узлы с " @@ -385,8 +378,8 @@ msgstr "Поддерживает CIDR нотацию (например '192.168. msgid "Task" msgstr "Задача" -msgid "There are currently %d of 250 supported interfaces configured" -msgstr "В настоящее время настроено %d из 250 поддерживаемых интерфейсов." +msgid "There are currently %d of %d supported interfaces configured" +msgstr "В настоящее время настроено %d из %d поддерживаемых интерфейсов." msgid "" "This displays the metric assigned to this interface in /etc/config/network" @@ -411,23 +404,14 @@ msgid "" "will
be executed with each netifd hotplug interface event
on " "interfaces for which mwan3 is enabled.

There are three main " "environment variables that are passed to this script.

$ACTION " -"Either \"ifup\" or \"ifdown\"
$INTERFACE Name of the interface which " -"went up or down (e.g. \"wan\" or \"wwan\")
$DEVICE Physical device name " -"which interface went up or down (e.g. \"eth0\" or \"wwan0\")

" +"
* \"ifup\" Is called by netifd and mwan3track
* \"ifdown\" Is " +"called by netifd and mwan3track
* \"connected\" Is only called by " +"mwan3track if tracking was successful
* \"disconnected\" Is only " +"called by mwan3track if tracking has failed
$INTERFACE Name of the " +"interface which went up or down (e.g. \"wan\" or \"wwan\")
$DEVICE " +"Physical device name which interface went up or down (e.g. \"eth0\" or " +"\"wwan0\")

" msgstr "" -"Страница позволяет изменять содержимое файла mwan3.user (/etc/mwan3.user)." -"
Файл также сохраняется во время перепрошивки sysupgrade-совместимым " -"образом.

Примечание:
Этот файл интерпретируется как shell " -"скрипт.
Первая строка скрипта должна быть "#!/bin/sh" без " -"кавычек.
Строки начинающиеся с #, являются комментариями и не " -"исполняются.
Поместите свои пользовательские действия mwan3 здесь, они " -"будут
выполняться с каждым событием netifd hotplug интерфейса
на " -"интерфейсах, для которых включен mwan3.

В этот сценарий " -"передаются три основные переменные среды.

$ACTION либо \"ifup\" " -"или \"ifdown\"
$INTERFACE - имя интерфейса, который включили или " -"отключили (например, 'wan' или 'wwan')
$DEVICE - имя физического " -"устройства, чей интерфейс включили или отключили (например, 'eth0' или " -"'wwan0')

." msgid "Tracking hostname or IP address" msgstr "Отслеживание имени хоста или IP-адреса" @@ -459,10 +443,10 @@ msgstr "" msgid "View the content of /etc/protocols for protocol description" msgstr "Просмотр содержимого файла /etc/protocols для описания протокола." -msgid "WARNING: %d interfaces are configured exceeding the maximum of 250!" +msgid "WARNING: %d interfaces are configured exceeding the maximum of %d!" msgstr "" "ВНИМАНИЕ: Интерфейсы %d настроены, превышая установленное ограничение в " -"количестве 250шт.!" +"количестве %dшт.!" msgid "WARNING: Interface %s are not found in /etc/config/network" msgstr "ВНИМАНИЕ: Интерфейс %s не настроен в config файле /etc/config/network." @@ -483,7 +467,7 @@ msgstr "" "ВНИМАНИЕ: Интерфейс %s не имеет маршрута по умолчанию в основной таблице " "маршрутизации." -msgid "WARNING: Policie %s has exceeding the maximum name of 15 characters" +msgid "WARNING: Policy %s has exceeding the maximum name of 15 characters" msgstr "" "ВНИМАНИЕ: Имя политики %s превышает установленное ограничение в 15 символов." @@ -527,3 +511,43 @@ msgstr "никогда" msgid "unreachable (reject)" msgstr "недоступен (отклонить)" + +#~ msgid "Online (tracking active)" +#~ msgstr "Онлайн (отслеживание активно)" + +#~ msgid "MWAN Interface Live Status" +#~ msgstr "Состояние интерфейса MWAN в настоящее время" + +#~ msgid "MWAN status - Interface Live Status" +#~ msgstr "Состояние MWAN - Интерфейс в настоящее время" + +#~ msgid "Online (tracking off)" +#~ msgstr "Онлайн (отслеживание отключено)" + +#~ msgid "" +#~ "This section allows you to modify the content of \"/etc/mwan3.user\".
The file is also preserved during sysupgrade.

Notes:
This file is interpreted as a shell script.
The first line of the " +#~ "script must be "#!/bin/sh" without quotes.
Lines beginning " +#~ "with # are comments and are not executed.
Put your custom mwan3 " +#~ "action here, they will
be executed with each netifd hotplug " +#~ "interface event
on interfaces for which mwan3 is enabled.

There are three main environment variables that are passed to this " +#~ "script.

$ACTION Either \"ifup\" or \"ifdown\"
$INTERFACE " +#~ "Name of the interface which went up or down (e.g. \"wan\" or \"wwan" +#~ "\")
$DEVICE Physical device name which interface went up or down (e." +#~ "g. \"eth0\" or \"wwan0\")

" +#~ msgstr "" +#~ "Страница позволяет изменять содержимое файла mwan3.user (/etc/mwan3.user)." +#~ "
Файл также сохраняется во время перепрошивки sysupgrade-совместимым " +#~ "образом.

Примечание:
Этот файл интерпретируется как shell " +#~ "скрипт.
Первая строка скрипта должна быть "#!/bin/sh" без " +#~ "кавычек.
Строки начинающиеся с #, являются комментариями и не " +#~ "исполняются.
Поместите свои пользовательские действия mwan3 здесь, " +#~ "они будут
выполняться с каждым событием netifd hotplug " +#~ "интерфейса
на интерфейсах, для которых включен mwan3.

В " +#~ "этот сценарий передаются три основные переменные среды.

" +#~ "$ACTION либо \"ifup\" или \"ifdown\"
$INTERFACE - имя интерфейса, " +#~ "который включили или отключили (например, 'wan' или 'wwan')
$DEVICE " +#~ "- имя физического устройства, чей интерфейс включили или отключили " +#~ "(например, 'eth0' или 'wwan0')

." diff --git a/applications/luci-app-mwan3/po/templates/mwan3.pot b/applications/luci-app-mwan3/po/templates/mwan3.pot index b7266240f..f6b3a1b38 100644 --- a/applications/luci-app-mwan3/po/templates/mwan3.pot +++ b/applications/luci-app-mwan3/po/templates/mwan3.pot @@ -88,6 +88,9 @@ msgstr "" msgid "Hotplug ifup" msgstr "" +msgid "INFO: MWAN not running" +msgstr "" + msgid "IPset" msgstr "" @@ -157,7 +160,7 @@ msgstr "" msgid "MWAN Interface Configuration - %s" msgstr "" -msgid "MWAN Interface Live Status" +msgid "MWAN Interfaces" msgstr "" msgid "MWAN Member Configuration - %s" @@ -178,16 +181,13 @@ msgstr "" msgid "MWAN Status - Troubleshooting" msgstr "" -msgid "MWAN status - Interface Live Status" -msgstr "" - msgid "" -"MWAN supports up to 250 physical and/or logical interfaces
MWAN " +"MWAN supports up to 252 physical and/or logical interfaces
MWAN " "requires that all interfaces have a unique metric configured in /etc/config/" "network
Names must match the interface name found in /etc/config/" -"network (see advanced tab)
Names may contain characters A-Z, a-z, 0-9, " -"_ and no spaces
Interfaces may not share the same name as configured " -"members, policies or rules" +"network
Names may contain characters A-Z, a-z, 0-9, _ and no spaces
Interfaces may not share the same name as configured members, policies or " +"rules" msgstr "" msgid "" @@ -236,12 +236,6 @@ msgstr "" msgid "Online" msgstr "" -msgid "Online (tracking active)" -msgstr "" - -msgid "Online (tracking off)" -msgstr "" - msgid "Ping count" msgstr "" @@ -272,11 +266,11 @@ msgstr "" msgid "" "Policies are profiles grouping one or more members controlling how MWAN " "distributes traffic
Member interfaces with lower metrics are used " -"first. Interfaces with the same metric load-balance
Load-balanced " -"member interfaces distribute more traffic out those with higher weights
Names may contain characters A-Z, a-z, 0-9, _ and no spaces. Names must be " -"15 characters or less
Policies may not share the same name as " -"configured interfaces, members or rules" +"first
Member interfaces with the same metric will be load-balanced
Load-balanced member interfaces distribute more traffic out those with " +"higher weights
Names may contain characters A-Z, a-z, 0-9, _ and no " +"spaces
Names must be 15 characters or less
Policies may not share " +"the same name as configured interfaces, members or rules" msgstr "" msgid "Policy" @@ -330,7 +324,7 @@ msgstr "" msgid "Task" msgstr "" -msgid "There are currently %d of 250 supported interfaces configured" +msgid "There are currently %d of %d supported interfaces configured" msgstr "" msgid "" @@ -351,9 +345,13 @@ msgid "" "will
be executed with each netifd hotplug interface event
on " "interfaces for which mwan3 is enabled.

There are three main " "environment variables that are passed to this script.

$ACTION " -"Either \"ifup\" or \"ifdown\"
$INTERFACE Name of the interface which " -"went up or down (e.g. \"wan\" or \"wwan\")
$DEVICE Physical device name " -"which interface went up or down (e.g. \"eth0\" or \"wwan0\")

" +"
* \"ifup\" Is called by netifd and mwan3track
* \"ifdown\" Is " +"called by netifd and mwan3track
* \"connected\" Is only called by " +"mwan3track if tracking was successful
* \"disconnected\" Is only " +"called by mwan3track if tracking has failed
$INTERFACE Name of the " +"interface which went up or down (e.g. \"wan\" or \"wwan\")
$DEVICE " +"Physical device name which interface went up or down (e.g. \"eth0\" or " +"\"wwan0\")

" msgstr "" msgid "Tracking hostname or IP address" @@ -381,7 +379,7 @@ msgstr "" msgid "View the content of /etc/protocols for protocol description" msgstr "" -msgid "WARNING: %d interfaces are configured exceeding the maximum of 250!" +msgid "WARNING: %d interfaces are configured exceeding the maximum of %d!" msgstr "" msgid "WARNING: Interface %s are not found in /etc/config/network" @@ -398,7 +396,7 @@ msgstr "" msgid "WARNING: Interface %s has no default route in the main routing table" msgstr "" -msgid "WARNING: Policie %s has exceeding the maximum name of 15 characters" +msgid "WARNING: Policy %s has exceeding the maximum name of 15 characters" msgstr "" msgid "" diff --git a/applications/luci-app-mwan3/po/zh-cn/mwan3.po b/applications/luci-app-mwan3/po/zh-cn/mwan3.po index c838bdb56..ef5933986 100644 --- a/applications/luci-app-mwan3/po/zh-cn/mwan3.po +++ b/applications/luci-app-mwan3/po/zh-cn/mwan3.po @@ -99,6 +99,9 @@ msgstr "Hotplug ifdown" msgid "Hotplug ifup" msgstr "Hotplug ifup" +msgid "INFO: MWAN not running" +msgstr "" + msgid "IPset" msgstr "IPset" @@ -168,8 +171,8 @@ msgstr "" msgid "MWAN Interface Configuration - %s" msgstr "MWAN 接口配置 - %s" -msgid "MWAN Interface Live Status" -msgstr "MWAN 接口实时状态" +msgid "MWAN Interfaces" +msgstr "" msgid "MWAN Member Configuration - %s" msgstr "MWAN 成员配置 - %s" @@ -189,22 +192,18 @@ msgstr "" msgid "MWAN Status - Troubleshooting" msgstr "" -msgid "MWAN status - Interface Live Status" -msgstr "" - msgid "" -"MWAN supports up to 250 physical and/or logical interfaces
MWAN " +"MWAN supports up to 252 physical and/or logical interfaces
MWAN " "requires that all interfaces have a unique metric configured in /etc/config/" "network
Names must match the interface name found in /etc/config/" -"network (see advanced tab)
Names may contain characters A-Z, a-z, 0-9, " -"_ and no spaces
Interfaces may not share the same name as configured " -"members, policies or rules" +"network
Names may contain characters A-Z, a-z, 0-9, _ and no spaces
Interfaces may not share the same name as configured members, policies or " +"rules" msgstr "" -"MWAN 支持最多 250 个物理或逻辑接口。
MWAN 要求所有接口必须在 /etc/" +"MWAN 支持最多 252 个物理或逻辑接口。
MWAN 要求所有接口必须在 /etc/" "config/network 中设定唯一的网关跃点。
名称必须与 /etc/config/network 中" -"的接口名称匹配。(可查看“高级”选项卡)
名称允许包括 A-Z、a-z、0-9、_ 但" -"是不能有空格。
接口不应该与成员、策略、规则中的任意一个设置项使用相同的" -"名称" +"的接口名称匹配。
名称允许包括 A-Z、a-z、0-9、_ 但是不能有空格。
接" +"口不应该与成员、策略、规则中的任意一个设置项使用相同的名称" msgid "" "May be entered as a single or multiple port(s) (eg \"22\" or \"80,443\") or " @@ -259,12 +258,6 @@ msgstr "离线" msgid "Online" msgstr "在线" -msgid "Online (tracking active)" -msgstr "在线(跟踪启用中)" - -msgid "Online (tracking off)" -msgstr "在线(跟踪已关闭)" - msgid "Ping count" msgstr "Ping 计数" @@ -295,11 +288,11 @@ msgstr "策略" msgid "" "Policies are profiles grouping one or more members controlling how MWAN " "distributes traffic
Member interfaces with lower metrics are used " -"first. Interfaces with the same metric load-balance
Load-balanced " -"member interfaces distribute more traffic out those with higher weights
Names may contain characters A-Z, a-z, 0-9, _ and no spaces. Names must be " -"15 characters or less
Policies may not share the same name as " -"configured interfaces, members or rules" +"first
Member interfaces with the same metric will be load-balanced
Load-balanced member interfaces distribute more traffic out those with " +"higher weights
Names may contain characters A-Z, a-z, 0-9, _ and no " +"spaces
Names must be 15 characters or less
Policies may not share " +"the same name as configured interfaces, members or rules" msgstr "" "“策略”把成员进行分组,告诉 MWAN 如何分配“规则”中使用这一策略的流量
拥有" "较低跃点数的成员将会被优先使用。拥有相同跃点数的成员把流量进行负载均衡。
be executed with each netifd hotplug interface event
on " "interfaces for which mwan3 is enabled.

There are three main " "environment variables that are passed to this script.

$ACTION " -"Either \"ifup\" or \"ifdown\"
$INTERFACE Name of the interface which " -"went up or down (e.g. \"wan\" or \"wwan\")
$DEVICE Physical device name " -"which interface went up or down (e.g. \"eth0\" or \"wwan0\")

" -msgstr "" -"这里允许您修改“/etc/mwan3.user”的内容。
该文件在 sysupgrade 期间也会保" -"留。

注意:
该文件会作为 shell 脚本解释。
脚本的第一行必" -"须是"#!/bin/sh",不带引号。
以#开头的行是注释,不会执行。
" -"将您的自定义 mwan3 动作放在这里,他们将
在启用 mwan3 的接口上
在 " -"netifd hotplug 接口事件时执行。

有三个主要的环境变量传递给这个脚" -"本。

$ACTION “ifup”或“ifdown”
$INTERFACE 启动或停止的接口名" -"(例如“wan”或“wwan”)
$DEVICE 启动或停止接口的物理设备名(例" -"如“eth0”或“wwan0”)

" +"
* \"ifup\" Is called by netifd and mwan3track
* \"ifdown\" Is " +"called by netifd and mwan3track
* \"connected\" Is only called by " +"mwan3track if tracking was successful
* \"disconnected\" Is only " +"called by mwan3track if tracking has failed
$INTERFACE Name of the " +"interface which went up or down (e.g. \"wan\" or \"wwan\")
$DEVICE " +"Physical device name which interface went up or down (e.g. \"eth0\" or " +"\"wwan0\")

" +msgstr "" msgid "Tracking hostname or IP address" msgstr "跟踪的主机或 IP 地址" @@ -419,8 +408,8 @@ msgstr "使用该接口的 IP 地址作为路由器本身发起的流量的源 I msgid "View the content of /etc/protocols for protocol description" msgstr "" -msgid "WARNING: %d interfaces are configured exceeding the maximum of 250!" -msgstr "警告:已配置 %d 个接口,超过最大值 250!" +msgid "WARNING: %d interfaces are configured exceeding the maximum of %d!" +msgstr "警告:已配置 %d 个接口,超过最大值 %d!" msgid "WARNING: Interface %s are not found in /etc/config/network" msgstr "" @@ -436,7 +425,7 @@ msgstr "" msgid "WARNING: Interface %s has no default route in the main routing table" msgstr "" -msgid "WARNING: Policie %s has exceeding the maximum name of 15 characters" +msgid "WARNING: Policy %s has exceeding the maximum name of 15 characters" msgstr "" msgid "" @@ -478,6 +467,38 @@ msgstr "从不" msgid "unreachable (reject)" msgstr "不可达(拒绝)" +#~ msgid "Online (tracking active)" +#~ msgstr "在线(跟踪启用中)" + +#~ msgid "MWAN Interface Live Status" +#~ msgstr "MWAN 接口实时状态" + +#~ msgid "Online (tracking off)" +#~ msgstr "在线(跟踪已关闭)" + +#~ msgid "" +#~ "This section allows you to modify the content of \"/etc/mwan3.user\".
The file is also preserved during sysupgrade.

Notes:
This file is interpreted as a shell script.
The first line of the " +#~ "script must be "#!/bin/sh" without quotes.
Lines beginning " +#~ "with # are comments and are not executed.
Put your custom mwan3 " +#~ "action here, they will
be executed with each netifd hotplug " +#~ "interface event
on interfaces for which mwan3 is enabled.

There are three main environment variables that are passed to this " +#~ "script.

$ACTION Either \"ifup\" or \"ifdown\"
$INTERFACE " +#~ "Name of the interface which went up or down (e.g. \"wan\" or \"wwan" +#~ "\")
$DEVICE Physical device name which interface went up or down (e." +#~ "g. \"eth0\" or \"wwan0\")

" +#~ msgstr "" +#~ "这里允许您修改“/etc/mwan3.user”的内容。
该文件在 sysupgrade 期间也会" +#~ "保留。

注意:
该文件会作为 shell 脚本解释。
脚本的第" +#~ "一行必须是"#!/bin/sh",不带引号。
以#开头的行是注释,不会执" +#~ "行。
将您的自定义 mwan3 动作放在这里,他们将
在启用 mwan3 的接口" +#~ "上
在 netifd hotplug 接口事件时执行。

有三个主要的环境变量" +#~ "传递给这个脚本。

$ACTION “ifup”或“ifdown”
$INTERFACE 启动" +#~ "或停止的接口名(例如“wan”或“wwan”)
$DEVICE 启动或停止接口的物理设备" +#~ "名(例如“eth0”或“wwan0”)

" + #~ msgid "Currently Configured Interfaces" #~ msgstr "当前配置的接口" diff --git a/applications/luci-app-mwan3/po/zh-tw/mwan3.po b/applications/luci-app-mwan3/po/zh-tw/mwan3.po index d28bd82bd..6af9fae7e 100644 --- a/applications/luci-app-mwan3/po/zh-tw/mwan3.po +++ b/applications/luci-app-mwan3/po/zh-tw/mwan3.po @@ -99,6 +99,9 @@ msgstr "Hotplug ifdown" msgid "Hotplug ifup" msgstr "Hotplug ifup" +msgid "INFO: MWAN not running" +msgstr "" + msgid "IPset" msgstr "IPset" @@ -168,8 +171,8 @@ msgstr "" msgid "MWAN Interface Configuration - %s" msgstr "MWAN 介面配置 - %s" -msgid "MWAN Interface Live Status" -msgstr "MWAN 介面實時狀態" +msgid "MWAN Interfaces" +msgstr "" msgid "MWAN Member Configuration - %s" msgstr "MWAN 成員配置 - %s" @@ -189,22 +192,18 @@ msgstr "" msgid "MWAN Status - Troubleshooting" msgstr "" -msgid "MWAN status - Interface Live Status" -msgstr "" - msgid "" -"MWAN supports up to 250 physical and/or logical interfaces
MWAN " +"MWAN supports up to 252 physical and/or logical interfaces
MWAN " "requires that all interfaces have a unique metric configured in /etc/config/" "network
Names must match the interface name found in /etc/config/" -"network (see advanced tab)
Names may contain characters A-Z, a-z, 0-9, " -"_ and no spaces
Interfaces may not share the same name as configured " -"members, policies or rules" +"network
Names may contain characters A-Z, a-z, 0-9, _ and no spaces
Interfaces may not share the same name as configured members, policies or " +"rules" msgstr "" -"MWAN 支援最多 250 個物理或邏輯介面。
MWAN 要求所有介面必須在 /etc/" +"MWAN 支援最多 252 個物理或邏輯介面。
MWAN 要求所有介面必須在 /etc/" "config/network 中設定唯一的閘道器躍點。
名稱必須與 /etc/config/network " -"中的介面名稱匹配。(可檢視“高階”選項卡)
名稱允許包括 A-Z、a-z、0-9、_ " -"但是不能有空格。
介面不應該與成員、策略、規則中的任意一個設定項使用相同" -"的名稱" +"中的介面名稱匹配。
名稱允許包括 A-Z、a-z、0-9、_ 但是不能有空格。
" +"介面不應該與成員、策略、規則中的任意一個設定項使用相同的名稱" msgid "" "May be entered as a single or multiple port(s) (eg \"22\" or \"80,443\") or " @@ -259,12 +258,6 @@ msgstr "離線" msgid "Online" msgstr "線上" -msgid "Online (tracking active)" -msgstr "線上(跟蹤啟用中)" - -msgid "Online (tracking off)" -msgstr "線上(跟蹤已關閉)" - msgid "Ping count" msgstr "Ping 計數" @@ -295,11 +288,11 @@ msgstr "策略" msgid "" "Policies are profiles grouping one or more members controlling how MWAN " "distributes traffic
Member interfaces with lower metrics are used " -"first. Interfaces with the same metric load-balance
Load-balanced " -"member interfaces distribute more traffic out those with higher weights
Names may contain characters A-Z, a-z, 0-9, _ and no spaces. Names must be " -"15 characters or less
Policies may not share the same name as " -"configured interfaces, members or rules" +"first
Member interfaces with the same metric will be load-balanced
Load-balanced member interfaces distribute more traffic out those with " +"higher weights
Names may contain characters A-Z, a-z, 0-9, _ and no " +"spaces
Names must be 15 characters or less
Policies may not share " +"the same name as configured interfaces, members or rules" msgstr "" "“策略”把成員進行分組,告訴 MWAN 如何分配“規則”中使用這一策略的流量
擁有" "較低躍點數的成員將會被優先使用。擁有相同躍點數的成員把流量進行負載均衡。
be executed with each netifd hotplug interface event
on " "interfaces for which mwan3 is enabled.

There are three main " "environment variables that are passed to this script.

$ACTION " -"Either \"ifup\" or \"ifdown\"
$INTERFACE Name of the interface which " -"went up or down (e.g. \"wan\" or \"wwan\")
$DEVICE Physical device name " -"which interface went up or down (e.g. \"eth0\" or \"wwan0\")

" -msgstr "" -"這裡允許您修改“/etc/mwan3.user”的內容。
該檔案在 sysupgrade 期間也會保" -"留。

注意:
該檔案會作為 shell 指令碼解釋。
指令碼的第一" -"行必須是"#!/bin/sh",不帶引號。
以#開頭的行是註釋,不會執行。" -"
將您的自定義 mwan3 動作放在這裡,他們將
在啟用 mwan3 的介面上
在 netifd hotplug 介面事件時執行。

有三個主要的環境變數傳遞給這個" -"腳本。

$ACTION “ifup”或“ifdown”
$INTERFACE 啟動或停止的介面名" -"(例如“wan”或“wwan”)
$DEVICE 啟動或停止介面的物理裝置名(例" -"如“eth0”或“wwan0”)

" +"
* \"ifup\" Is called by netifd and mwan3track
* \"ifdown\" Is " +"called by netifd and mwan3track
* \"connected\" Is only called by " +"mwan3track if tracking was successful
* \"disconnected\" Is only " +"called by mwan3track if tracking has failed
$INTERFACE Name of the " +"interface which went up or down (e.g. \"wan\" or \"wwan\")
$DEVICE " +"Physical device name which interface went up or down (e.g. \"eth0\" or " +"\"wwan0\")

" +msgstr "" msgid "Tracking hostname or IP address" msgstr "跟蹤的主機或 IP 位址" @@ -419,8 +408,8 @@ msgstr "使用該介面的 IP 位址作為路由器本身發起的流量的源 I msgid "View the content of /etc/protocols for protocol description" msgstr "" -msgid "WARNING: %d interfaces are configured exceeding the maximum of 250!" -msgstr "警告:已配置 %d 個介面,超過最大值 250!" +msgid "WARNING: %d interfaces are configured exceeding the maximum of %d!" +msgstr "警告:已配置 %d 個介面,超過最大值 %d!" msgid "WARNING: Interface %s are not found in /etc/config/network" msgstr "" @@ -436,7 +425,7 @@ msgstr "" msgid "WARNING: Interface %s has no default route in the main routing table" msgstr "" -msgid "WARNING: Policie %s has exceeding the maximum name of 15 characters" +msgid "WARNING: Policy %s has exceeding the maximum name of 15 characters" msgstr "" msgid "" @@ -478,6 +467,38 @@ msgstr "從不" msgid "unreachable (reject)" msgstr "不可達(拒絕)" +#~ msgid "Online (tracking active)" +#~ msgstr "線上(跟蹤啟用中)" + +#~ msgid "MWAN Interface Live Status" +#~ msgstr "MWAN 介面實時狀態" + +#~ msgid "Online (tracking off)" +#~ msgstr "線上(跟蹤已關閉)" + +#~ msgid "" +#~ "This section allows you to modify the content of \"/etc/mwan3.user\".
The file is also preserved during sysupgrade.

Notes:
This file is interpreted as a shell script.
The first line of the " +#~ "script must be "#!/bin/sh" without quotes.
Lines beginning " +#~ "with # are comments and are not executed.
Put your custom mwan3 " +#~ "action here, they will
be executed with each netifd hotplug " +#~ "interface event
on interfaces for which mwan3 is enabled.

There are three main environment variables that are passed to this " +#~ "script.

$ACTION Either \"ifup\" or \"ifdown\"
$INTERFACE " +#~ "Name of the interface which went up or down (e.g. \"wan\" or \"wwan" +#~ "\")
$DEVICE Physical device name which interface went up or down (e." +#~ "g. \"eth0\" or \"wwan0\")

" +#~ msgstr "" +#~ "這裡允許您修改“/etc/mwan3.user”的內容。
該檔案在 sysupgrade 期間也會" +#~ "保留。

注意:
該檔案會作為 shell 指令碼解釋。
指令碼" +#~ "的第一行必須是"#!/bin/sh",不帶引號。
以#開頭的行是註釋,不會" +#~ "執行。
將您的自定義 mwan3 動作放在這裡,他們將
在啟用 mwan3 的介" +#~ "面上
在 netifd hotplug 介面事件時執行。

有三個主要的環境變" +#~ "數傳遞給這個腳本。

$ACTION “ifup”或“ifdown”
$INTERFACE 啟" +#~ "動或停止的介面名(例如“wan”或“wwan”)
$DEVICE 啟動或停止介面的物理裝" +#~ "置名(例如“eth0”或“wwan0”)

" + #~ msgid "Currently Configured Interfaces" #~ msgstr "當前配置的介面" diff --git a/applications/luci-app-olsr/luasrc/controller/olsr.lua b/applications/luci-app-olsr/luasrc/controller/olsr.lua index 229f3d61b..c5fb2b2a5 100644 --- a/applications/luci-app-olsr/luasrc/controller/olsr.lua +++ b/applications/luci-app-olsr/luasrc/controller/olsr.lua @@ -84,11 +84,11 @@ function action_json() local jsonreq4 local jsonreq6 - local v4_port = uci:get("olsrd", "olsrd_jsoninfo", "port") or 9090 - local v6_port = uci:get("olsrd6", "olsrd_jsoninfo", "port") or 9090 + local v4_port = tonumber(uci:get("olsrd", "olsrd_jsoninfo", "port") or "") or 9090 + local v6_port = tonumber(uci:get("olsrd6", "olsrd_jsoninfo", "port") or "") or 9090 - jsonreq4 = utl.exec("(echo /status | nc 127.0.0.1 " .. v4_port .. " | sed -n '/^[}{ ]/p') 2>/dev/null" ) - jsonreq6 = utl.exec("(echo /status | nc ::1 " .. v6_port .. " | sed -n '/^[}{ ]/p') 2>/dev/null") + jsonreq4 = utl.exec("(echo /status | nc 127.0.0.1 %d | sed -n '/^[}{ ]/p') 2>/dev/null" % v4_port) + jsonreq6 = utl.exec("(echo /status | nc ::1 %d | sed -n '/^[}{ ]/p') 2>/dev/null" % v6_port) http.prepare_content("application/json") if not jsonreq4 or jsonreq4 == "" then jsonreq4 = "{}" @@ -150,7 +150,7 @@ function action_neigh(json) for _, dev in ipairs(devices) do for _, net in ipairs(dev:get_wifinets()) do local radio = net:get_device() - assoclist[#assoclist+1] = {} + assoclist[#assoclist+1] = {} assoclist[#assoclist]['ifname'] = net:ifname() assoclist[#assoclist]['network'] = net:network()[1] assoclist[#assoclist]['device'] = radio and radio:name() or nil @@ -165,7 +165,7 @@ function action_neigh(json) local mac = "" local ip local neihgt = {} - + if resolve == "1" then hostname = nixio.getnameinfo(v.remoteIP, nil, 100) if hostname then @@ -350,11 +350,11 @@ function fetch_jsoninfo(otable) local IpVersion = uci:get_first("olsrd", "olsrd","IpVersion") local jsonreq4 = "" local jsonreq6 = "" - local v4_port = uci:get("olsrd", "olsrd_jsoninfo", "port") or 9090 - local v6_port = uci:get("olsrd6", "olsrd_jsoninfo", "port") or 9090 + local v4_port = tonumber(uci:get("olsrd", "olsrd_jsoninfo", "port") or "") or 9090 + local v6_port = tonumber(uci:get("olsrd6", "olsrd_jsoninfo", "port") or "") or 9090 - jsonreq4 = utl.exec("(echo /" .. otable .. " | nc 127.0.0.1 " .. v4_port .. " | sed -n '/^[}{ ]/p') 2>/dev/null") - jsonreq6 = utl.exec("(echo /" .. otable .. " | nc ::1 " .. v6_port .. " | sed -n '/^[}{ ]/p') 2>/dev/null") + jsonreq4 = utl.exec("(echo /%s | nc 127.0.0.1 %d | sed -n '/^[}{ ]/p') 2>/dev/null" %{ otable, v4_port }) + jsonreq6 = utl.exec("(echo /%s | nc ::1 %d | sed -n '/^[}{ ]/p') 2>/dev/null" %{ otable, v6_port }) local jsondata4 = {} local jsondata6 = {} local data4 = {} diff --git a/applications/luci-app-openvpn/luasrc/model/cbi/openvpn.lua b/applications/luci-app-openvpn/luasrc/model/cbi/openvpn.lua index 719145b88..d2b5d32c0 100644 --- a/applications/luci-app-openvpn/luasrc/model/cbi/openvpn.lua +++ b/applications/luci-app-openvpn/luasrc/model/cbi/openvpn.lua @@ -26,9 +26,9 @@ uci:foreach( "openvpn_recipes", "openvpn_recipe", ) function s.getPID(section) -- Universal function which returns valid pid # or nil - local pid = sys.exec("%s | grep -w %s | grep openvpn | grep -v grep | awk '{print $1}'" % { psstring,section} ) - if pid and #pid > 0 and tonumber(pid) ~= nil then - return tonumber(pid) + local pid = sys.exec("%s | grep -w '[o]penvpn(%s)'" % { psstring, section }) + if pid and #pid > 0 then + return tonumber(pid:match("^%s*(%d+)")) else return nil end diff --git a/applications/luci-app-splash/luasrc/controller/splash/splash.lua b/applications/luci-app-splash/luasrc/controller/splash/splash.lua index b4fdbd53a..af7a3a3c0 100644 --- a/applications/luci-app-splash/luasrc/controller/splash/splash.lua +++ b/applications/luci-app-splash/luasrc/controller/splash/splash.lua @@ -9,7 +9,7 @@ function index() entry({"admin", "services", "splash", "splashtext" }, form("splash/splashtext"), _("Splashtext"), 10) local e - + e = node("splash") e.target = call("action_dispatch") @@ -82,7 +82,7 @@ function action_activate() end end) - if blacklisted then + if blacklisted then luci.http.redirect(luci.dispatcher.build_url("splash" ,"blocked")) else local id = tostring(mac):gsub(':', ''):lower() @@ -106,7 +106,7 @@ function action_status_admin() local uci = luci.model.uci.cursor_state() local macs = luci.http.formvaluetable("save") - local changes = { + local changes = { whitelist = { }, blacklist = { }, lease = { }, @@ -129,22 +129,22 @@ function action_status_admin() if #changes.whitelist > 0 then os.execute("luci-splash whitelist %s >/dev/null" - % table.concat(changes.whitelist)) + % util.shellquote(table.concat(changes.whitelist))) end if #changes.blacklist > 0 then os.execute("luci-splash blacklist %s >/dev/null" - % table.concat(changes.blacklist)) + % util.shellquote(table.concat(changes.blacklist))) end if #changes.lease > 0 then os.execute("luci-splash lease %s >/dev/null" - % table.concat(changes.lease)) + % util.shellquote(table.concat(changes.lease))) end if #changes.remove > 0 then os.execute("luci-splash remove %s >/dev/null" - % table.concat(changes.remove)) + % util.shellquote(table.concat(changes.remove))) end luci.template.render("admin_status/splash", { is_admin = true }) diff --git a/applications/luci-app-splash/root/usr/sbin/luci-splash b/applications/luci-app-splash/root/usr/sbin/luci-splash index 2870dbe6a..9ec9f3a9e 100755 --- a/applications/luci-app-splash/root/usr/sbin/luci-splash +++ b/applications/luci-app-splash/root/usr/sbin/luci-splash @@ -36,6 +36,10 @@ function call(cmd) os.execute(cmd) end +function esc(str) + return utl.shellquote(str) +end + function lock() call("lock /var/run/luci_splash.lock") @@ -84,14 +88,14 @@ end function get_physdev(interface) local dev - dev = utl.trim(sys.exec(". /lib/functions/network.sh; network_get_device IFNAME '" .. interface .. "'; echo $IFNAME")) + dev = utl.trim(sys.exec(". /lib/functions/network.sh; network_get_device IFNAME %s; echo $IFNAME" % esc(interface))) return dev end function get_filter_handle(parent, direction, device, mac) - local input = utl.split(sys.exec('/usr/sbin/tc filter show dev ' .. device .. ' parent ' .. parent) or {}) + local input = utl.split(sys.exec('/usr/sbin/tc filter show dev %s parent %s' %{ esc(device), esc(parent) }) or {}) local tbl = {} local handle for k, v in pairs(input) do @@ -264,7 +268,7 @@ function main(argv) elseif whitelist_macs[mac] then print("Removing %s from whitelist" % mac) remove_whitelist(mac) - whitelist_macs[mac] = nil + whitelist_macs[mac] = nil elseif blacklist_macs[mac] then print("Removing %s from blacklist" % mac) remove_blacklist(mac) @@ -295,7 +299,7 @@ function main(argv) print("\n luci-splash remove \n Remove given address from the lease-, black- or whitelist") print("") - os.exit(1) + os.exit(1) end end @@ -338,8 +342,8 @@ function ipt_delete_all(args, comp, off) off[r.table] = off[r.table] or { } off[r.table][r.chain] = off[r.table][r.chain] or 0 - exec("iptables -t %q -D %q %d 2>/dev/null" - %{ r.table, r.chain, r.index - off[r.table][r.chain] }) + exec("iptables -t %s -D %s %d 2>/dev/null" + %{ esc(r.table), esc(r.chain), r.index - off[r.table][r.chain] }) off[r.table][r.chain] = off[r.table][r.chain] + 1 end @@ -353,8 +357,8 @@ function ipt6_delete_all(args, comp, off) off[r.table] = off[r.table] or { } off[r.table][r.chain] = off[r.table][r.chain] or 0 - exec("ip6tables -t %q -D %q %d 2>/dev/null" - %{ r.table, r.chain, r.index - off[r.table][r.chain] }) + exec("ip6tables -t %s -D %s %d 2>/dev/null" + %{ esc(r.table), esc(r.chain), r.index - off[r.table][r.chain] }) off[r.table][r.chain] = off[r.table][r.chain] + 1 end @@ -460,13 +464,13 @@ function remove_whitelist_tc(mac) end local handle = get_filter_handle('ffff:', 'src', device, mac) if handle then - exec('tc filter del dev "%s" parent ffff: protocol ip prio 1 handle %s u32' % { device, handle }) + exec('tc filter del dev %s parent ffff: protocol ip prio 1 handle %s u32' % { esc(device), esc(handle) }) else print('Warning! Could not get a handle for %s parent :ffff on interface %s' % { mac, device }) end local handle = get_filter_handle('1:', 'dest', device, mac) if handle then - exec('tc filter del dev "%s" parent 1:0 protocol ip prio 1 handle %s u32' % { device, handle }) + exec('tc filter del dev %s parent 1:0 protocol ip prio 1 handle %s u32' % { esc(device), esc(handle) }) else print('Warning! Could not get a handle for %s parent 1:0 on interface %s' % { mac, device }) end @@ -492,37 +496,37 @@ function add_lease_rule(mac, ipaddr, device) id = get_id(ipaddr) end - exec("iptables -t mangle -I luci_splash_mark_out -m mac --mac-source %q -j RETURN" % mac) + exec("iptables -t mangle -I luci_splash_mark_out -m mac --mac-source %s -j RETURN" % esc(mac)) -- Mark incoming packets to a splashed host -- for ipv4 - by iptables and destination if id and device then - exec("iptables -t mangle -I luci_splash_mark_in -d %q -j MARK --set-mark 0x1%s -m comment --comment %s" % {ipaddr, id, mac:upper()}) + exec("iptables -t mangle -I luci_splash_mark_in -d %s -j MARK --set-mark 0x1%s -m comment --comment %s" % { esc(ipaddr), esc(id), esc(mac:upper())}) end --for ipv6: need to use the mac here if has_ipv6 then - exec("ip6tables -t mangle -I luci_splash_mark_out -m mac --mac-source %q -j MARK --set-mark 79" % mac) + exec("ip6tables -t mangle -I luci_splash_mark_out -m mac --mac-source %s -j MARK --set-mark 79" % esc(mac)) if id and device and tonumber(limit_down) then - exec("tc filter add dev %s parent 1:0 protocol ipv6 prio 1 u32 match ether dst %s classid 1:%s" % {device, mac:lower(), id}) + exec("tc filter add dev %s parent 1:0 protocol ipv6 prio 1 u32 match ether dst %s classid 1:%s" % { esc(device), esc(mac:lower()), esc(id) }) end end if device and tonumber(limit_up) > 0 then - exec('tc filter add dev "%s" parent ffff: protocol all prio 2 u32 match ether src %s police rate %skbit mtu 6k burst 6k drop' % {device, mac, limit_up}) + exec('tc filter add dev %s parent ffff: protocol all prio 2 u32 match ether src %s police rate %skbit mtu 6k burst 6k drop' % { esc(device), esc(mac), esc(limit_up) }) end if id and device and tonumber(limit_down) > 0 then - exec("tc class add dev %s parent 1: classid 1:0x%s htb rate %skbit" % { device, id, limit_down }) - exec("tc qdisc add dev %s parent 1:%s sfq perturb 10" % { device, id }) + exec("tc class add dev %s parent 1: classid 1:0x%s htb rate %skbit" % { esc(device), esc(id), esc(limit_down) }) + exec("tc qdisc add dev %s parent 1:%s sfq perturb 10" % { esc(device), esc(id) }) end - exec("iptables -t filter -I luci_splash_filter -m mac --mac-source %q -j RETURN" % mac) - exec("iptables -t nat -I luci_splash_leases -m mac --mac-source %q -j RETURN" % mac) + exec("iptables -t filter -I luci_splash_filter -m mac --mac-source %s -j RETURN" % esc(mac)) + exec("iptables -t nat -I luci_splash_leases -m mac --mac-source %s -j RETURN" % esc(mac)) if has_ipv6 then - exec("ip6tables -t filter -I luci_splash_filter -m mac --mac-source %q -j RETURN" % mac) + exec("ip6tables -t filter -I luci_splash_filter -m mac --mac-source %s -j RETURN" % esc(mac)) end end @@ -548,32 +552,32 @@ function remove_lease_rule(mac, ipaddr, device, limit_up, limit_down) if device and tonumber(limit_up) > 0 then local handle = get_filter_handle('ffff:', 'src', device, mac) if handle then - exec('tc filter del dev "%s" parent ffff: protocol all prio 2 handle %s u32 police rate %skbit mtu 6k burst 6k drop' % {device, handle, limit_up}) + exec('tc filter del dev %s parent ffff: protocol all prio 2 handle %s u32 police rate %skbit mtu 6k burst 6k drop' % { esc(device), esc(handle), esc(limit_up) }) else print('Warning! Could not get a handle for %s parent :ffff on interface %s' % { mac, device }) end end -- remove clients class if device and id then - exec('tc class del dev "%s" classid 1:%s' % {device, id}) - exec('tc filter del dev "%s" parent 1:0 prio 1' % device) -- ipv6 rule - --exec('tc qdisc del dev "%s" parent 1:%s sfq perturb 10' % { device, id }) + exec('tc class del dev %s classid 1:%s' % { esc(device), esc(id) }) + exec('tc filter del dev %s parent 1:0 prio 1' % esc(device)) -- ipv6 rule + --exec('tc qdisc del dev %s parent 1:%s sfq perturb 10' % { esc(device), esc(id) }) end end -- Add whitelist rules function add_whitelist_rule(mac) - exec("iptables -t filter -I luci_splash_filter -m mac --mac-source %q -j RETURN" % mac) - exec("iptables -t nat -I luci_splash_leases -m mac --mac-source %q -j RETURN" % mac) + exec("iptables -t filter -I luci_splash_filter -m mac --mac-source %s -j RETURN" % esc(mac)) + exec("iptables -t nat -I luci_splash_leases -m mac --mac-source %s -j RETURN" % esc(mac)) if has_ipv6 then - exec("ip6tables -t filter -I luci_splash_filter -m mac --mac-source %q -j RETURN" % mac) + exec("ip6tables -t filter -I luci_splash_filter -m mac --mac-source %s -j RETURN" % esc(mac)) end uci:foreach("luci_splash", "iface", function(s) local device = get_physdev(s['.name']) if device and device ~= "" then - exec('tc filter add dev "%s" parent ffff: protocol ip prio 1 u32 match ether src %s police pass' % { device, mac }) - exec('tc filter add dev "%s" parent 1:0 protocol ip prio 1 u32 match ether dst %s classid 1:1' % { device, mac }) + exec('tc filter add dev %s parent ffff: protocol ip prio 1 u32 match ether src %s police pass' % { esc(device), esc(mac) }) + exec('tc filter add dev %s parent 1:0 protocol ip prio 1 u32 match ether dst %s classid 1:1' % { esc(device), esc(mac) }) end end) end @@ -581,9 +585,9 @@ end -- Add blacklist rules function add_blacklist_rule(mac) - exec("iptables -t filter -I luci_splash_filter -m mac --mac-source %q -j DROP" % mac) + exec("iptables -t filter -I luci_splash_filter -m mac --mac-source %s -j DROP" % esc(mac)) if has_ipv6 then - exec("ip6tables -t filter -I luci_splash_filter -m mac --mac-source %q -j DROP" % mac) + exec("ip6tables -t filter -I luci_splash_filter -m mac --mac-source %s -j DROP" % esc(mac)) end end @@ -596,15 +600,15 @@ function sync() -- Current leases in state files local leases = uci:get_all("luci_splash_leases") - + -- Convert leasetime to seconds local leasetime = tonumber(uci:get("luci_splash", "general", "leasetime")) * 3600 - + -- Clean state file uci:load("luci_splash_leases") uci:revert("luci_splash_leases") - + local blackwhitelist = uci:get_all("luci_splash") local whitelist_total = 0 local whitelist_online = 0 @@ -628,7 +632,7 @@ function sync() end -- Rewrite state - uci:section("luci_splash_leases", "lease", convert_mac_to_secname(v.mac), { + uci:section("luci_splash_leases", "lease", convert_mac_to_secname(v.mac), { mac = v.mac, ipaddr = v.ipaddr, device = v.device, @@ -639,7 +643,7 @@ function sync() end end end - + -- Whitelist, Blacklist for _, s in utl.spairs(blackwhitelist, function(a,b) return blackwhitelist[a][".type"] > blackwhitelist[b][".type"] end @@ -666,7 +670,7 @@ function sync() -- ToDo: -- include a new field "leases_online" in stats to differ between active clients and leases: - -- update_stats(leasecount, leases_online, whitelist_online, whitelist_total, blacklist_online, blacklist_total) later: + -- update_stats(leasecount, leases_online, whitelist_online, whitelist_total, blacklist_online, blacklist_total) later: update_stats(leases_online, whitelist_online, whitelist_total, blacklist_online, blacklist_total) uci:save("luci_splash_leases") diff --git a/applications/luci-app-statistics/luasrc/statistics/rrdtool.lua b/applications/luci-app-statistics/luasrc/statistics/rrdtool.lua index e29a2e17d..47e1696ec 100644 --- a/applications/luci-app-statistics/luasrc/statistics/rrdtool.lua +++ b/applications/luci-app-statistics/luasrc/statistics/rrdtool.lua @@ -87,7 +87,7 @@ function Graph._rrdtool( self, def, rrd ) fs.mkdirr( dir ) -- construct commandline - local cmdline = "rrdtool graph" + local cmdline = { "rrdtool", "graph" } -- copy default arguments to def stack for i, opt in ipairs(self.args) do @@ -102,15 +102,11 @@ function Graph._rrdtool( self, def, rrd ) opt = opt:gsub( "{file}", rrd ) end - if opt:match("[^%w]") then - cmdline = cmdline .. " '" .. opt .. "'" - else - cmdline = cmdline .. " " .. opt - end + cmdline[#cmdline+1] = luci.util.shellquote(opt) end -- execute rrdtool - local rrdtool = io.popen( cmdline ) + local rrdtool = io.popen(table.concat(cmdline, " ")) rrdtool:close() end diff --git a/applications/luci-app-tinyproxy/luasrc/view/tinyproxy_status.htm b/applications/luci-app-tinyproxy/luasrc/view/tinyproxy_status.htm index d43a887b0..2ba9dddb8 100644 --- a/applications/luci-app-tinyproxy/luasrc/view/tinyproxy_status.htm +++ b/applications/luci-app-tinyproxy/luasrc/view/tinyproxy_status.htm @@ -13,7 +13,11 @@ if luci.http.formvalue("frame") == "1" then end) local data = false - local wget = io.popen("wget -qO- http://%s:%s" % { addr, port }) + local wget = io.popen("wget -qO- http://%s:%s" %{ + luci.util.shellquote(addr), + luci.util.shellquote(port) + }) + if wget then while true do local l = wget:read("*l") @@ -30,7 +34,10 @@ if luci.http.formvalue("frame") == "1" then if not data then luci.http.write(translate("Failed to retrieve statistics from url:")) - luci.http.write(" http://%s:%s" % { addr, port }) + luci.http.write(" http://%s:%s" %{ + luci.util.pcdata(addr), + luci.util.pcdata(port) + }) end return @@ -43,7 +50,7 @@ end

<%:Tinyproxy Status%>

- +
diff --git a/applications/luci-app-travelmate/Makefile b/applications/luci-app-travelmate/Makefile index 2bd25bc17..58d9bf37d 100644 --- a/applications/luci-app-travelmate/Makefile +++ b/applications/luci-app-travelmate/Makefile @@ -5,7 +5,7 @@ include $(TOPDIR)/rules.mk LUCI_TITLE:=LuCI support for Travelmate -LUCI_DEPENDS:=+travelmate +luci-lib-jsonc +qrencode +LUCI_DEPENDS:=+travelmate +luci-lib-jsonc LUCI_PKGARCH:=all include ../../luci.mk diff --git a/applications/luci-app-travelmate/luasrc/controller/travelmate.lua b/applications/luci-app-travelmate/luasrc/controller/travelmate.lua index 14b8d77ff..493a387c3 100644 --- a/applications/luci-app-travelmate/luasrc/controller/travelmate.lua +++ b/applications/luci-app-travelmate/luasrc/controller/travelmate.lua @@ -14,27 +14,27 @@ function index() entry({"admin", "services", "travelmate"}, firstchild(), _("Travelmate"), 40).dependent = false entry({"admin", "services", "travelmate", "tab_from_cbi"}, cbi("travelmate/overview_tab", {hideresetbtn=true, hidesavebtn=true}), _("Overview"), 10).leaf = true entry({"admin", "services", "travelmate", "stations"}, template("travelmate/stations"), _("Wireless Stations"), 20).leaf = true - entry({"admin", "services", "travelmate", "apqr"}, template("travelmate/ap_qr"), _("AP QR-Codes"), 30).leaf = true - entry({"admin", "services", "travelmate", "logfile"}, call("logread"), _("View Logfile"), 40).leaf = true + entry({"admin", "services", "travelmate", "logfile"}, call("logread"), _("View Logfile"), 30).leaf = true entry({"admin", "services", "travelmate", "advanced"}, firstchild(), _("Advanced"), 100) - entry({"admin", "services", "travelmate", "advanced", "configuration"}, cbi("travelmate/configuration_tab"), _("Edit Travelmate Configuration"), 110).leaf = true - entry({"admin", "services", "travelmate", "advanced", "cfg_wireless"}, cbi("travelmate/cfg_wireless_tab"), _("Edit Wireless Configuration"), 120).leaf = true - entry({"admin", "services", "travelmate", "advanced", "cfg_network"}, cbi("travelmate/cfg_network_tab"), _("Edit Network Configuration"), 130).leaf = true - entry({"admin", "services", "travelmate", "advanced", "cfg_firewall"}, cbi("travelmate/cfg_firewall_tab"), _("Edit Firewall Configuration"), 140).leaf = true + entry({"admin", "services", "travelmate", "advanced", "configuration"}, form("travelmate/configuration_tab"), _("Edit Travelmate Configuration"), 110).leaf = true + entry({"admin", "services", "travelmate", "advanced", "cfg_wireless"}, form("travelmate/cfg_wireless_tab"), _("Edit Wireless Configuration"), 120).leaf = true + entry({"admin", "services", "travelmate", "advanced", "cfg_network"}, form("travelmate/cfg_network_tab"), _("Edit Network Configuration"), 130).leaf = true + entry({"admin", "services", "travelmate", "advanced", "cfg_firewall"}, form("travelmate/cfg_firewall_tab"), _("Edit Firewall Configuration"), 140).leaf = true + entry({"admin", "services", "travelmate", "apqr"}, template("travelmate/ap_qr")).leaf = true entry({"admin", "services", "travelmate", "wifiscan"}, template("travelmate/wifi_scan")).leaf = true - entry({"admin", "services", "travelmate", "wifiadd"}, cbi("travelmate/wifi_add", {hideresetbtn=true, hidesavebtn=true})).leaf = true - entry({"admin", "services", "travelmate", "wifiedit"}, cbi("travelmate/wifi_edit", {hideresetbtn=true, hidesavebtn=true})).leaf = true - entry({"admin", "services", "travelmate", "wifidelete"}, cbi("travelmate/wifi_delete", {hideresetbtn=true, hidesavebtn=true})).leaf = true - entry({"admin", "services", "travelmate", "wifiorder"}, cbi("travelmate/wifi_order", {hideresetbtn=true, hidesavebtn=true})).leaf = true + entry({"admin", "services", "travelmate", "wifiadd"}, form("travelmate/wifi_add", {hideresetbtn=true, hidesavebtn=true})).leaf = true + entry({"admin", "services", "travelmate", "wifiedit"}, form("travelmate/wifi_edit", {hideresetbtn=true, hidesavebtn=true})).leaf = true + entry({"admin", "services", "travelmate", "wifidelete"}, form("travelmate/wifi_delete", {hideresetbtn=true, hidesavebtn=true})).leaf = true + entry({"admin", "services", "travelmate", "wifiorder"}, form("travelmate/wifi_order", {hideresetbtn=true, hidesavebtn=true})).leaf = true end function logread() - local logfile + local logfile = "" if nixio.fs.access("/var/log/messages") then logfile = util.trim(util.exec("grep -F 'travelmate-' /var/log/messages")) - else + elseif nixio.fs.access("/sbin/logread") then logfile = util.trim(util.exec("logread -e 'travelmate-'")) end templ.render("travelmate/logread", {title = i18n.translate("Travelmate Logfile"), content = logfile}) diff --git a/applications/luci-app-travelmate/luasrc/model/cbi/travelmate/overview_tab.lua b/applications/luci-app-travelmate/luasrc/model/cbi/travelmate/overview_tab.lua index 860ce2295..7b6b9658c 100644 --- a/applications/luci-app-travelmate/luasrc/model/cbi/travelmate/overview_tab.lua +++ b/applications/luci-app-travelmate/luasrc/model/cbi/travelmate/overview_tab.lua @@ -73,45 +73,34 @@ o1 = s:option(Flag, "trm_enabled", translate("Enable travelmate")) o1.default = o1.disabled o1.rmempty = false -o2 = s:option(Flag, "trm_automatic", translate("Enable 'automatic' mode"), - translate("Keep travelmate in an active state. Check every n seconds the connection status, i.e. the uplink availability.")) +o2 = s:option(Flag, "trm_captive", translate("Captive Portal Detection"), + translate("Check the internet availability, log captive portal redirections and keep the uplink connection 'alive'.")) o2.default = o2.enabled o2.rmempty = false -o3 = s:option(Flag, "trm_captive", translate("Captive Portal Detection"), - translate("Check the internet availability, log captive portal redirections and keep the uplink connection 'alive'.")) -o3.default = o3.enabled -o3.rmempty = false - -o4 = s:option(ListValue, "trm_iface", translate("Uplink / Trigger interface"), +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 - o4:value(v.interface) + o3:value(v.interface) end end end -o4.default = trmiface -o4.rmempty = false +o3.default = trmiface +o3.rmempty = false -o5 = s:option(Value, "trm_triggerdelay", translate("Trigger Delay"), - translate("Additional trigger delay in seconds before travelmate processing begins.")) -o5.datatype = "range(1,60)" -o5.default = 2 -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")) +if fs.access("/usr/bin/qrencode") then + btn = s:option(Button, "btn", translate("View AP QR-Codes"), + translate("Connect your Android or iOS devices to your router's WiFi using the shown QR code.")) + btn.inputtitle = translate("QR-Codes") + btn.inputstyle = "apply" + btn.disabled = false + + function btn.write() + luci.http.redirect(luci.dispatcher.build_url("admin", "services", "travelmate", "apqr")) + end end -- Runtime information @@ -180,28 +169,34 @@ e2 = e:option(Value, "trm_radio", translate("Radio selection"), e2.datatype = "and(uciname,rangelength(6,6))" e2.rmempty = true -e3 = e:option(Value, "trm_maxretry", translate("Connection Limit"), - translate("Retry limit to connect to an uplink.")) -e3.default = 3 -e3.datatype = "range(1,10)" +e3 = e:option(Value, "trm_triggerdelay", translate("Trigger Delay"), + translate("Additional trigger delay in seconds before travelmate processing begins.")) +e3.datatype = "range(1,60)" +e3.default = 2 e3.rmempty = false -e4 = e:option(Value, "trm_minquality", translate("Signal Quality Threshold"), - translate("Minimum signal quality threshold as percent for conditional uplink (dis-) connections.")) -e4.default = 35 -e4.datatype = "range(20,80)" +e4 = e:option(Value, "trm_maxretry", translate("Connection Limit"), + translate("Retry limit to connect to an uplink.")) +e4.default = 3 +e4.datatype = "range(1,10)" e4.rmempty = false -e5 = e:option(Value, "trm_maxwait", translate("Interface Timeout"), - translate("How long should travelmate wait for a successful wlan uplink connection.")) -e5.default = 30 -e5.datatype = "range(20,40)" +e5 = e:option(Value, "trm_minquality", translate("Signal Quality Threshold"), + translate("Minimum signal quality threshold as percent for conditional uplink (dis-) connections.")) +e5.default = 35 +e5.datatype = "range(20,80)" e5.rmempty = false -e6 = e:option(Value, "trm_timeout", translate("Overall Timeout"), - translate("Timeout in seconds between retries in 'automatic' mode.")) -e6.default = 60 -e6.datatype = "range(30,300)" +e6 = e:option(Value, "trm_maxwait", translate("Interface Timeout"), + translate("How long should travelmate wait for a successful wlan uplink connection.")) +e6.default = 30 +e6.datatype = "range(20,40)" e6.rmempty = false +e7 = e:option(Value, "trm_timeout", translate("Overall Timeout"), + translate("Overall retry timeout in seconds.")) +e7.default = 60 +e7.datatype = "range(30,300)" +e7.rmempty = false + return m diff --git a/applications/luci-app-travelmate/luasrc/model/cbi/travelmate/wifi_add.lua b/applications/luci-app-travelmate/luasrc/model/cbi/travelmate/wifi_add.lua index 50edd17bb..83011e9dd 100644 --- a/applications/luci-app-travelmate/luasrc/model/cbi/travelmate/wifi_add.lua +++ b/applications/luci-app-travelmate/luasrc/model/cbi/travelmate/wifi_add.lua @@ -26,18 +26,23 @@ m.hidden = { wpa_version = http.formvalue("wpa_version") } -if m.hidden.ssid ~= "" then - wssid = m:field(Value, "ssid", translate("SSID")) - wssid.datatype = "rangelength(1,32)" - wssid.default = m.hidden.ssid or "" -else +if m.hidden.ssid == "" then wssid = m:field(Value, "ssid", translate("SSID (hidden)")) +else + wssid = m:field(Value, "ssid", translate("SSID")) end +wssid.datatype = "rangelength(1,32)" +wssid.default = m.hidden.ssid or "" nobssid = m:field(Flag, "no_bssid", translate("Ignore BSSID")) -nobssid.default = nobssid.enabled +if m.hidden.ssid == "" then + nobssid.default = nobssid.disabled +else + nobssid.default = nobssid.enabled +end -bssid = m:field(Value, "bssid", translate("BSSID")) +bssid = m:field(Value, "bssid", translate("BSSID"), + translatef("The BSSID information '%s' is optional and only required for hidden networks", m.hidden.bssid or "")) bssid:depends("no_bssid", 0) bssid.datatype = "macaddr" bssid.default = m.hidden.bssid or "" @@ -171,6 +176,7 @@ function wssid.write(self, section, value) end uci:save("wireless") uci:commit("wireless") + luci.sys.call("env -i /bin/ubus call network reload >/dev/null 2>&1") http.redirect(luci.dispatcher.build_url("admin/services/travelmate/stations")) end diff --git a/applications/luci-app-travelmate/luasrc/model/cbi/travelmate/wifi_delete.lua b/applications/luci-app-travelmate/luasrc/model/cbi/travelmate/wifi_delete.lua index 0c3cc1865..0a7678f7e 100644 --- a/applications/luci-app-travelmate/luasrc/model/cbi/travelmate/wifi_delete.lua +++ b/applications/luci-app-travelmate/luasrc/model/cbi/travelmate/wifi_delete.lua @@ -9,5 +9,6 @@ if cfg ~= nil then uci:delete("wireless", cfg) uci:save("wireless") uci:commit("wireless") + luci.sys.call("env -i /bin/ubus call network reload >/dev/null 2>&1") end http.redirect(luci.dispatcher.build_url("admin/services/travelmate/stations")) diff --git a/applications/luci-app-travelmate/luasrc/model/cbi/travelmate/wifi_edit.lua b/applications/luci-app-travelmate/luasrc/model/cbi/travelmate/wifi_edit.lua index ee4d342ea..f3ad76259 100644 --- a/applications/luci-app-travelmate/luasrc/model/cbi/travelmate/wifi_edit.lua +++ b/applications/luci-app-travelmate/luasrc/model/cbi/travelmate/wifi_edit.lua @@ -162,6 +162,7 @@ function wssid.write(self, section, value) end uci:save("wireless") uci:commit("wireless") + luci.sys.call("env -i /bin/ubus call network reload >/dev/null 2>&1") m.on_cancel() end diff --git a/applications/luci-app-travelmate/luasrc/view/travelmate/ap_qr.htm b/applications/luci-app-travelmate/luasrc/view/travelmate/ap_qr.htm index 13342a3e6..a92dbe146 100644 --- a/applications/luci-app-travelmate/luasrc/view/travelmate/ap_qr.htm +++ b/applications/luci-app-travelmate/luasrc/view/travelmate/ap_qr.htm @@ -44,9 +44,7 @@ This is free software, licensed under the Apache License, Version 2.0 local e_ssid = string.gsub(ssid,"[\"\\';:, ]",[[\\\%1]]) local e_key = string.gsub(key,"[\"\\';:, ]",[[\\\%1]]) local qrcode = "" - if nixio.fs.access("/usr/bin/qrencode") then - qrcode = luci.sys.exec("/usr/bin/qrencode --inline --8bit --type=SVG --output=- 'WIFI:S:\"'" .. e_ssid .. "'\";T:'" .. enc .. "';P:\"'" .. e_key .. "'\";H:'" .. hidden .. "';'") - end + qrcode = luci.sys.exec("/usr/bin/qrencode --inline --8bit --type=SVG --output=- 'WIFI:S:\"'" .. e_ssid .. "'\";T:'" .. enc .. "';P:\"'" .. e_key .. "'\";H:'" .. hidden .. "';'") -%>
AP on <%=device%> with SSID "<%=ssid%>" @@ -58,5 +56,10 @@ This is free software, licensed under the Apache License, Version 2.0 end) %> +
+
+ +
+
<%+footer%> diff --git a/applications/luci-app-travelmate/po/ja/travelmate.po b/applications/luci-app-travelmate/po/ja/travelmate.po index 30f34ef30..535a9db26 100644 --- a/applications/luci-app-travelmate/po/ja/travelmate.po +++ b/applications/luci-app-travelmate/po/ja/travelmate.po @@ -12,9 +12,6 @@ msgstr "" "Plural-Forms: nplurals=1; plural=0;\n" "Language: ja\n" -msgid "AP QR-Codes" -msgstr "AP QR-コード" - msgid "Actions" msgstr "操作" @@ -65,6 +62,12 @@ msgid "" msgstr "" "トラベル ルーター機能を有効化するための、 Travelmate パッケージの設定です。" +msgid "" +"Connect your Android or iOS devices to your router's WiFi using the shown QR " +"code." +msgstr "" +"Android や iOS デバイスを、表示される QR コードを使用して WiFi に接続します。" + msgid "Connection Limit" msgstr "接続制限" @@ -110,9 +113,6 @@ msgstr "無線アップリンク設定の編集" msgid "Edit this Uplink" msgstr "このアップリンクを編集" -msgid "Enable 'automatic' mode" -msgstr "'automatic' モードの有効化" - msgid "Enable travelmate" msgstr "Travelmate の有効化" @@ -144,10 +144,6 @@ 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 "" "Here you'll find the QR codes from all of your configured Access Points. It " "allows you to connect your Android or iOS devices to your router's WiFi " @@ -176,19 +172,9 @@ msgstr "インターフェース タイムアウト" msgid "Interface Wizard" msgstr "インターフェース ウィザード" -msgid "" -"Keep travelmate in an active state. Check every n seconds the connection " -"status, i.e. the uplink availability." -msgstr "" -"Travelmate をアクティブ状態で維持します。\"実行間隔\" で設定された時間毎" -"(秒)に、アップリンクの可用性を確認するために接続状態をチェックします" - msgid "Last rundate" msgstr "最終実行日時" -msgid "Manual Rescan" -msgstr "手動再スキャン" - msgid "" "Minimum signal quality threshold as percent for conditional uplink (dis-) " "connections." @@ -215,6 +201,9 @@ msgstr "デフォルトの設定が適切でない場合、さらに設定する msgid "Overall Timeout" msgstr "実行間隔" +msgid "Overall retry timeout in seconds." +msgstr "" + msgid "Overview" msgstr "概要" @@ -246,15 +235,15 @@ msgstr "" "ンクを追加することができます。現在使用されているアップリンクは、青色で強調さ" "れます。" +msgid "QR-Codes" +msgstr "QR-コード" + msgid "Radio selection" msgstr "無線の選択" msgid "Repeat scan" msgstr "再スキャン" -msgid "Rescan" -msgstr "再スキャン" - msgid "Restrict travelmate to a dedicated radio, e.g. 'radio0'." msgstr "Travelmate が指定された無線に接続するよう制御します。(例: 'radio0')" @@ -292,6 +281,10 @@ msgid "Station Radio" msgstr "ステーション電波" msgid "" +"The BSSID information '%s' is optional and only required for hidden networks" +msgstr "" + +msgid "" "This form allows you to modify the content of the main firewall " "configuration file (/etc/config/firewall)." msgstr "" @@ -326,9 +319,6 @@ msgstr "" "このフォームには、システムログ内の Travelmate に関するメッセージのみが表示さ" "れます。" -msgid "Timeout in seconds between retries in 'automatic' mode." -msgstr "'automatic' モード時に接続を確認または再試行する間隔(秒)です。" - msgid "Travelmate" msgstr "Travelmate" @@ -359,6 +349,9 @@ msgstr "アップリンク SSID" msgid "Uplink interface" msgstr "アップリンク インターフェース" +msgid "View AP QR-Codes" +msgstr "AP QR-コードを確認" + msgid "View Logfile" msgstr "ログファイルの確認" @@ -397,3 +390,26 @@ msgstr "(不明)" msgid "n/a" msgstr "利用不可" + +#~ msgid "Enable 'automatic' mode" +#~ msgstr "'automatic' モードの有効化" + +#~ msgid "Force a manual uplink rescan / reconnect in 'trigger' mode." +#~ msgstr "" +#~ "'trigger' モード時に、手動でアップリンクの再スキャンと再接続を行います。" + +#~ msgid "" +#~ "Keep travelmate in an active state. Check every n seconds the connection " +#~ "status, i.e. the uplink availability." +#~ msgstr "" +#~ "Travelmate をアクティブ状態で維持します。\"実行間隔\" で設定された時間毎" +#~ "(秒)に、アップリンクの可用性を確認するために接続状態をチェックします" + +#~ msgid "Manual Rescan" +#~ msgstr "手動再スキャン" + +#~ msgid "Rescan" +#~ msgstr "再スキャン" + +#~ msgid "Timeout in seconds between retries in 'automatic' mode." +#~ msgstr "'automatic' モード時に接続を確認または再試行する間隔(秒)です。" diff --git a/applications/luci-app-travelmate/po/pt-br/travelmate.po b/applications/luci-app-travelmate/po/pt-br/travelmate.po index 7cb6ac061..5ea4d4a0d 100644 --- a/applications/luci-app-travelmate/po/pt-br/travelmate.po +++ b/applications/luci-app-travelmate/po/pt-br/travelmate.po @@ -12,9 +12,6 @@ msgstr "" "Plural-Forms: nplurals=2; plural=(n > 1);\n" "Language: pt_BR\n" -msgid "AP QR-Codes" -msgstr "" - msgid "Actions" msgstr "" @@ -62,6 +59,11 @@ msgid "" "functionality." msgstr "" +msgid "" +"Connect your Android or iOS devices to your router's WiFi using the shown QR " +"code." +msgstr "" + msgid "Connection Limit" msgstr "" @@ -105,9 +107,6 @@ msgstr "" msgid "Edit this Uplink" msgstr "" -msgid "Enable 'automatic' mode" -msgstr "" - msgid "Enable travelmate" msgstr "" @@ -137,9 +136,6 @@ msgstr "" msgid "Force TKIP and CCMP (AES)" msgstr "" -msgid "Force a manual uplink rescan / reconnect in 'trigger' mode." -msgstr "" - msgid "" "Here you'll find the QR codes from all of your configured Access Points. It " "allows you to connect your Android or iOS devices to your router's WiFi " @@ -165,17 +161,9 @@ msgstr "" msgid "Interface Wizard" msgstr "" -msgid "" -"Keep travelmate in an active state. Check every n seconds the connection " -"status, i.e. the uplink availability." -msgstr "" - msgid "Last rundate" msgstr "" -msgid "Manual Rescan" -msgstr "" - msgid "" "Minimum signal quality threshold as percent for conditional uplink (dis-) " "connections." @@ -200,6 +188,9 @@ msgstr "" msgid "Overall Timeout" msgstr "" +msgid "Overall retry timeout in seconds." +msgstr "" + msgid "Overview" msgstr "" @@ -227,13 +218,13 @@ msgid "" "one. The currently used uplink is emphasized in blue." msgstr "" -msgid "Radio selection" +msgid "QR-Codes" msgstr "" -msgid "Repeat scan" +msgid "Radio selection" msgstr "" -msgid "Rescan" +msgid "Repeat scan" msgstr "" msgid "Restrict travelmate to a dedicated radio, e.g. 'radio0'." @@ -273,6 +264,10 @@ msgid "Station Radio" msgstr "" msgid "" +"The BSSID information '%s' is optional and only required for hidden networks" +msgstr "" + +msgid "" "This form allows you to modify the content of the main firewall " "configuration file (/etc/config/firewall)." msgstr "" @@ -297,9 +292,6 @@ msgid "" "messages only." msgstr "" -msgid "Timeout in seconds between retries in 'automatic' mode." -msgstr "" - msgid "Travelmate" msgstr "Travelmate" @@ -330,6 +322,9 @@ msgstr "" msgid "Uplink interface" msgstr "" +msgid "View AP QR-Codes" +msgstr "" + msgid "View Logfile" msgstr "" diff --git a/applications/luci-app-travelmate/po/ru/travelmate.po b/applications/luci-app-travelmate/po/ru/travelmate.po index 0b04e2783..fad31bb84 100644 --- a/applications/luci-app-travelmate/po/ru/travelmate.po +++ b/applications/luci-app-travelmate/po/ru/travelmate.po @@ -15,9 +15,6 @@ msgstr "" "Project-Info: Это технический перевод, не дословный. Главное-удобный русский " "интерфейс, все проверялось в графическом режиме, совместим с другими apps\n" -msgid "AP QR-Codes" -msgstr "" - msgid "Actions" msgstr "Действия" @@ -65,6 +62,11 @@ msgid "" "functionality." msgstr "Настройка утилиты TravelMate - помощника путешественника. " +msgid "" +"Connect your Android or iOS devices to your router's WiFi using the shown QR " +"code." +msgstr "" + msgid "Connection Limit" msgstr "Ограничение соединений" @@ -110,9 +112,6 @@ msgstr "Редактировать настройки беспроводной msgid "Edit this Uplink" msgstr "Редактировать настройки сети" -msgid "Enable 'automatic' mode" -msgstr "Включить режим 'автоматически'" - msgid "Enable travelmate" msgstr "Включить Travelmate" @@ -144,11 +143,6 @@ msgstr "Назначить TKIP" msgid "Force TKIP and CCMP (AES)" msgstr "Назначить TKIP и CCMP (AES)" -msgid "Force a manual uplink rescan / reconnect in 'trigger' mode." -msgstr "" -"Принудительно выполнить повторное сканирование/повторное подключение внешних " -"сетей в режиме 'ручной'." - msgid "" "Here you'll find the QR codes from all of your configured Access Points. It " "allows you to connect your Android or iOS devices to your router's WiFi " @@ -174,19 +168,9 @@ msgstr "Временная задержка интерфейса" msgid "Interface Wizard" msgstr "Помощник настройки интерфейса" -msgid "" -"Keep travelmate in an active state. Check every n seconds the connection " -"status, i.e. the uplink availability." -msgstr "" -"Поддержка TravelMate в активном состоянии.
Проверка состояния " -"соединения каждые n секунд, т.е. доступность внешней сети." - msgid "Last rundate" msgstr "Дата последнего запуска" -msgid "Manual Rescan" -msgstr "Поиск сети вручную" - msgid "" "Minimum signal quality threshold as percent for conditional uplink (dis-) " "connections." @@ -213,6 +197,9 @@ msgstr "" msgid "Overall Timeout" msgstr "Общее время ожидания" +msgid "Overall retry timeout in seconds." +msgstr "" + msgid "Overview" msgstr "Главное меню" @@ -244,15 +231,15 @@ msgstr "" "упорядочивать существующий список внешних сетей или выполнять их поиск.
Используемое сетевое соединение выделено синим цветом." +msgid "QR-Codes" +msgstr "" + msgid "Radio selection" msgstr "Выбор Wi-Fi устройства" msgid "Repeat scan" msgstr "Повторить поиск" -msgid "Rescan" -msgstr "Пересканировать" - msgid "Restrict travelmate to a dedicated radio, e.g. 'radio0'." msgstr "Выделить TravelMate-у конкретное Wi-Fi устройство, например 'radio0'." @@ -290,6 +277,10 @@ msgid "Station Radio" msgstr "Wi-Fi устройство клиента" msgid "" +"The BSSID information '%s' is optional and only required for hidden networks" +msgstr "" + +msgid "" "This form allows you to modify the content of the main firewall " "configuration file (/etc/config/firewall)." msgstr "" @@ -324,11 +315,6 @@ msgstr "" "Страница просмотра системного журнала, показаны только события связанные с " "работой утилиты TravelMate." -msgid "Timeout in seconds between retries in 'automatic' mode." -msgstr "" -"Время ожидания в секундах между повторными попытками соединения в режиме " -"'автоматически'." - msgid "Travelmate" msgstr "TravelMate" @@ -359,6 +345,9 @@ msgstr "SSID внешней сети" msgid "Uplink interface" msgstr "Интерфейс внешней сети" +msgid "View AP QR-Codes" +msgstr "" + msgid "View Logfile" msgstr "Показать системный журнал" @@ -396,6 +385,32 @@ msgstr "скрытый" msgid "n/a" msgstr "нет данных" +#~ msgid "Enable 'automatic' mode" +#~ msgstr "Включить режим 'автоматически'" + +#~ msgid "Force a manual uplink rescan / reconnect in 'trigger' mode." +#~ msgstr "" +#~ "Принудительно выполнить повторное сканирование/повторное подключение " +#~ "внешних сетей в режиме 'ручной'." + +#~ msgid "" +#~ "Keep travelmate in an active state. Check every n seconds the connection " +#~ "status, i.e. the uplink availability." +#~ msgstr "" +#~ "Поддержка TravelMate в активном состоянии.
Проверка состояния " +#~ "соединения каждые n секунд, т.е. доступность внешней сети." + +#~ msgid "Manual Rescan" +#~ msgstr "Поиск сети вручную" + +#~ msgid "Rescan" +#~ msgstr "Пересканировать" + +#~ msgid "Timeout in seconds between retries in 'automatic' mode." +#~ msgstr "" +#~ "Время ожидания в секундах между повторными попытками соединения в режиме " +#~ "'автоматически'." + #~ msgid "" #~ "How long should travelmate wait for a successful wlan interface reload." #~ msgstr "" diff --git a/applications/luci-app-travelmate/po/templates/travelmate.pot b/applications/luci-app-travelmate/po/templates/travelmate.pot index e27c61a9d..8ba17668e 100644 --- a/applications/luci-app-travelmate/po/templates/travelmate.pot +++ b/applications/luci-app-travelmate/po/templates/travelmate.pot @@ -1,9 +1,6 @@ msgid "" msgstr "Content-Type: text/plain; charset=UTF-8" -msgid "AP QR-Codes" -msgstr "" - msgid "Actions" msgstr "" @@ -51,6 +48,11 @@ msgid "" "functionality." msgstr "" +msgid "" +"Connect your Android or iOS devices to your router's WiFi using the shown QR " +"code." +msgstr "" + msgid "Connection Limit" msgstr "" @@ -94,9 +96,6 @@ msgstr "" msgid "Edit this Uplink" msgstr "" -msgid "Enable 'automatic' mode" -msgstr "" - msgid "Enable travelmate" msgstr "" @@ -126,9 +125,6 @@ msgstr "" msgid "Force TKIP and CCMP (AES)" msgstr "" -msgid "Force a manual uplink rescan / reconnect in 'trigger' mode." -msgstr "" - msgid "" "Here you'll find the QR codes from all of your configured Access Points. It " "allows you to connect your Android or iOS devices to your router's WiFi " @@ -154,17 +150,9 @@ msgstr "" msgid "Interface Wizard" msgstr "" -msgid "" -"Keep travelmate in an active state. Check every n seconds the connection " -"status, i.e. the uplink availability." -msgstr "" - msgid "Last rundate" msgstr "" -msgid "Manual Rescan" -msgstr "" - msgid "" "Minimum signal quality threshold as percent for conditional uplink (dis-) " "connections." @@ -189,6 +177,9 @@ msgstr "" msgid "Overall Timeout" msgstr "" +msgid "Overall retry timeout in seconds." +msgstr "" + msgid "Overview" msgstr "" @@ -216,13 +207,13 @@ msgid "" "one. The currently used uplink is emphasized in blue." msgstr "" -msgid "Radio selection" +msgid "QR-Codes" msgstr "" -msgid "Repeat scan" +msgid "Radio selection" msgstr "" -msgid "Rescan" +msgid "Repeat scan" msgstr "" msgid "Restrict travelmate to a dedicated radio, e.g. 'radio0'." @@ -262,6 +253,10 @@ msgid "Station Radio" msgstr "" msgid "" +"The BSSID information '%s' is optional and only required for hidden networks" +msgstr "" + +msgid "" "This form allows you to modify the content of the main firewall " "configuration file (/etc/config/firewall)." msgstr "" @@ -286,9 +281,6 @@ msgid "" "messages only." msgstr "" -msgid "Timeout in seconds between retries in 'automatic' mode." -msgstr "" - msgid "Travelmate" msgstr "" @@ -319,6 +311,9 @@ msgstr "" msgid "Uplink interface" msgstr "" +msgid "View AP QR-Codes" +msgstr "" + msgid "View Logfile" msgstr "" diff --git a/applications/luci-app-unbound/luasrc/controller/unbound.lua b/applications/luci-app-unbound/luasrc/controller/unbound.lua index b44bf038e..730ca724a 100644 --- a/applications/luci-app-unbound/luasrc/controller/unbound.lua +++ b/applications/luci-app-unbound/luasrc/controller/unbound.lua @@ -47,12 +47,12 @@ function index() if valman ~= "1" then entry({"admin", "services", "unbound", "files", "base"}, call("ShowUnboundConf"), _("UCI: Unbound"), 10).leaf = true else - entry({"admin", "services", "unbound", "files", "base"}, cbi("unbound/manual"), _("Edit: Unbound"), 10).leaf = true + entry({"admin", "services", "unbound", "files", "base"}, form("unbound/manual"), _("Edit: Unbound"), 10).leaf = true end - entry({"admin", "services", "unbound", "files", "server"}, cbi("unbound/server"), _("Edit: Server"), 20).leaf = true - entry({"admin", "services", "unbound", "files", "extended"}, cbi("unbound/extended"), _("Edit: Extended"), 30).leaf = true + entry({"admin", "services", "unbound", "files", "server"}, form("unbound/server"), _("Edit: Server"), 20).leaf = true + entry({"admin", "services", "unbound", "files", "extended"}, form("unbound/extended"), _("Edit: Extended"), 30).leaf = true if nixio.fs.access("/var/lib/unbound/unbound_dhcp.conf") then diff --git a/applications/luci-app-unbound/luasrc/model/cbi/unbound/configure.lua b/applications/luci-app-unbound/luasrc/model/cbi/unbound/configure.lua index cdf7757e3..c92e37995 100644 --- a/applications/luci-app-unbound/luasrc/model/cbi/unbound/configure.lua +++ b/applications/luci-app-unbound/luasrc/model/cbi/unbound/configure.lua @@ -4,9 +4,12 @@ -- Licensed to the public under the Apache License 2.0. local m1, s1 -local ena, mcf, lci, lsv, rlh, rpv, vld, nvd, eds, prt, tlm -local ctl, dlk, dom, dty, lfq, wfq, exa, dp6, d64, pfx, qry, qrs +local ena, mcf, lci, lsv +local rlh, rpv, vld, nvd, eds, prt, tlm +local ctl, dlk, dom, dty, lfq, wfq, exa +local dp6, d64, pfx, qry, qrs local pro, tgr, rsc, rsn, ag2, stt +local rpn, din, dfw local ucl = luci.model.uci.cursor() local valman = ucl:get_first("unbound", "unbound", "manual_conf") @@ -19,10 +22,10 @@ s1.anonymous = true --LuCI, Unbound, or Not s1:tab("basic", translate("Basic"), translatef("

Unbound Basic Settings

\n" - .. "Unbound" + .. "Unbound (link)" .. " is a validating, recursive, and caching DNS resolver. " - .. "UCI help can be found on " - .. "github.", + .. "UCI documentation can be found on " + .. "github (link).", "https://www.unbound.net/", "https://github.com/openwrt/packages/blob/master/net/unbound/files/README.md")) @@ -34,8 +37,8 @@ mcf = s1:taboption("basic", Flag, "manual_conf", translate("Manual Conf:"), translate("Skip UCI and use /etc/unbound/unbound.conf")) mcf.rmempty = false -lci = s1:taboption("basic", Flag, "extended_luci", translate("Advanced LuCI:"), - translate("See detailed tabs for debug and advanced manual configuration")) +lci = s1:taboption("basic", Flag, "extended_luci", translate("Extended Tabs:"), + translate("See detailed tabs for statistics, debug, and manual configuration")) lci.rmempty = false @@ -61,29 +64,23 @@ if valman ~= "1" then -- Not in manual configuration mode; show UCI s1:tab("advanced", translate("Advanced"), translatef("

Unbound Advanced Settings

\n" - .. "Advanced setttings and plugin modules for " - .. "Unbound" + .. "Link DHCP-DNS, Manipulate DNS, or protect your local domain in " + .. "Unbound " .. " DNS resolver.", "https://www.unbound.net/")) + s1:tab("resource", translate("Resource"), translatef("

Unbound Resource Settings

\n" .. "Memory and protocol setttings for " - .. "Unbound" + .. "Unbound " .. " DNS resolver.", "https://www.unbound.net/")) + --Basic Tab lsv = s1:taboption("basic", Flag, "localservice", translate("Local Service:"), translate("Accept queries only from local subnets")) lsv.rmempty = false - rlh = s1:taboption("basic", Flag, "rebind_localhost", translate("Block Localhost Rebind:"), - translate("Prevent upstream response of 127.0.0.0/8")) - rlh.rmempty = false - - rpv = s1:taboption("basic", Flag, "rebind_protection", translate("Block Private Rebind:"), - translate("Prevent upstream response of RFC1918 ranges")) - rpv.rmempty = false - vld = s1:taboption("basic", Flag, "validator", translate("Enable DNSSEC:"), translate("Enable the DNSSEC validator module")) vld.rmempty = false @@ -93,31 +90,37 @@ if valman ~= "1" then nvd.rmempty = false nvd:depends({ validator = true }) - eds = s1:taboption("basic", Value, "edns_size", translate("EDNS Size:"), - translate("Limit extended DNS packet size")) - eds.datatype = "and(uinteger,min(512),max(4096))" - eds.rmempty = false + din = s1:taboption("basic", DynamicList, "domain_insecure", + translate("Domain Insecure:"), + translate("List domains to bypass checks of DNSSEC")) + din:depends({ validator = true }) + + d64 = s1:taboption("basic", Flag, "dns64", translate("Enable DNS64:"), + translate("Enable the DNS64 module")) + d64.rmempty = false + + pfx = s1:taboption("basic", Value, "dns64_prefix", translate("DNS64 Prefix:"), + translate("Prefix for generated DNS64 addresses")) + pfx.datatype = "ip6addr" + pfx.placeholder = "64:ff9b::/96" + pfx.optional = true + pfx:depends({ dns64 = true }) + + qry = s1:taboption("basic", Flag, "query_minimize", translate("Query Minimize:"), + translate("Break down query components for limited added privacy")) + qry.rmempty = false + + qrs = s1:taboption("basic", Flag, "query_min_strict", translate("Strict Minimize:"), + translate("Strict version of 'query minimize' but it can break DNS")) + qrs.rmempty = false + qrs:depends({ query_minimize = true }) prt = s1:taboption("basic", Value, "listen_port", translate("Listening Port:"), translate("Choose Unbounds listening port")) prt.datatype = "port" prt.rmempty = false - tlm = s1:taboption("basic", Value, "ttl_min", translate("TTL Minimum:"), - translate("Prevent excessively short cache periods")) - tlm.datatype = "and(uinteger,min(0),max(600))" - tlm.rmempty = false - - --Advanced Tab - ctl = s1:taboption("advanced", ListValue, "unbound_control", translate("Unbound Control App:"), - translate("Enable access for unbound-control")) - ctl.rmempty = false - ctl:value("0", translate("No Remote Control")) - ctl:value("1", translate("Local Host, No Encryption")) - ctl:value("2", translate("Local Host, Encrypted")) - ctl:value("3", translate("Local Subnet, Encrypted")) - ctl:value("4", translate("Local Subnet, Static Encryption")) - + --Avanced Tab dlk = s1:taboption("advanced", ListValue, "dhcp_link", translate("DHCP Link:"), translate("Link to supported programs to load DHCP into DNS")) dlk:value("none", translate("No Link")) @@ -125,6 +128,11 @@ if valman ~= "1" then dlk:value("odhcpd", "odhcpd") dlk.rmempty = false + dp6 = s1:taboption("advanced", Flag, "dhcp4_slaac6", translate("DHCPv4 to SLAAC:"), + translate("Use DHCPv4 MAC to discover IP6 hosts SLAAC (EUI64)")) + dp6.rmempty = false + dp6:depends({ dhcp_link = "odhcpd" }) + dom = s1:taboption("advanced", Value, "domain", translate("Local Domain:"), translate("Domain suffix for this router and DHCP clients")) dom.placeholder = "lan" @@ -142,7 +150,7 @@ if valman ~= "1" then lfq = s1:taboption("advanced", ListValue, "add_local_fqdn", translate("LAN DNS:"), translate("How to enter the LAN or local network router in DNS")) - lfq:value("0", translate("No DNS")) + lfq:value("0", translate("No Entry")) lfq:value("1", translate("Hostname, Primary Address")) lfq:value("2", translate("Hostname, All Addresses")) lfq:value("3", translate("Host FQDN, All Addresses")) @@ -152,7 +160,7 @@ if valman ~= "1" then wfq = s1:taboption("advanced", ListValue, "add_wan_fqdn", translate("WAN DNS:"), translate("Override the WAN side router entry in DNS")) - wfq:value("0", translate("Upstream")) + wfq:value("0", translate("Use Upstream")) wfq:value("1", translate("Hostname, Primary Address")) wfq:value("2", translate("Hostname, All Addresses")) wfq:value("3", translate("Host FQDN, All Addresses")) @@ -169,33 +177,41 @@ if valman ~= "1" then exa:depends({ dhcp_link = "none" }) exa:depends({ dhcp_link = "odhcpd" }) - dp6 = s1:taboption("advanced", Flag, "dhcp4_slaac6", translate("DHCPv4 to SLAAC:"), - translate("Use DHCPv4 MAC to discover IP6 hosts SLAAC (EUI64)")) - dp6.rmempty = false + dfw = s1:taboption("advanced", DynamicList, "domain_forward", + translate("Domain Forward:"), + translate("List domains to simply forward to stub resolvers in /tmp/resolve.auto")) - d64 = s1:taboption("advanced", Flag, "dns64", translate("Enable DNS64:"), - translate("Enable the DNS64 module")) - d64.rmempty = false + rlh = s1:taboption("advanced", Flag, "rebind_localhost", translate("Filter Localhost Rebind:"), + translate("Protect against upstream response of 127.0.0.0/8")) + rlh.rmempty = false - pfx = s1:taboption("advanced", Value, "dns64_prefix", translate("DNS64 Prefix:"), - translate("Prefix for generated DNS64 addresses")) - pfx.datatype = "ip6addr" - pfx.placeholder = "64:ff9b::/96" - pfx.optional = true - pfx:depends({ dns64 = true }) + rpv = s1:taboption("advanced", ListValue, "rebind_protection", translate("Filter Private Rebind:"), + translate("Protect against upstream responses within local subnets")) + rpv:value("0", translate("No Filter")) + rpv:value("1", translate("Filter RFC1918/4193")) + rpv:value("2", translate("Filter Entire Subnet")) + rpv.rmempty = false - qry = s1:taboption("advanced", Flag, "query_minimize", translate("Query Minimize:"), - translate("Break down query components for limited added privacy")) - qry.rmempty = false - - qrs = s1:taboption("advanced", Flag, "query_min_strict", translate("Strict Minimize:"), - translate("Strict version of 'query minimize' but it can break DNS")) - qrs.rmempty = false - qrs:depends({ query_minimize = true }) + rpn = s1:taboption("advanced", Value, "rebind_interface", translate("Rebind Network Filter:"), + translate("Network subnets to filter from upstream responses")) + rpn.template = "cbi/network_netlist" + rpn.widget = "checkbox" + rpn.cast = "string" + rpn:depends({ rebind_protection = 2 }) + rpn:depends({ rebind_protection = 3 }) --TODO: dnsmasq needs to not reference resolve-file and get off port 53. --Resource Tuning Tab + ctl = s1:taboption("resource", ListValue, "unbound_control", translate("Unbound Control App:"), + translate("Enable access for unbound-control")) + ctl.rmempty = false + ctl:value("0", translate("No Remote Control")) + ctl:value("1", translate("Local Host, No Encryption")) + ctl:value("2", translate("Local Host, Encrypted")) + ctl:value("3", translate("Local Subnet, Encrypted")) + ctl:value("4", translate("Local Subnet, Static Encryption")) + pro = s1:taboption("resource", ListValue, "protocol", translate("Recursion Protocol:"), translate("Chose the protocol recursion queries leave on")) pro:value("mixed", translate("IP4 and IP6")) @@ -220,7 +236,7 @@ if valman ~= "1" then rsc.rmempty = false ag2 = s1:taboption("resource", Value, "root_age", translate("Root DSKEY Age:"), - translate("Limit days between RFC5011 to reduce flash writes")) + translate("Limit days between RFC 5011 copies to reduce flash writes")) ag2.datatype = "and(uinteger,min(1),max(99))" ag2:value("3", "3") ag2:value("9", "9 ("..translate("default")..")") @@ -228,11 +244,21 @@ if valman ~= "1" then ag2:value("24", "24") ag2:value("99", "99 ("..translate("never")..")") + eds = s1:taboption("resource", Value, "edns_size", translate("EDNS Size:"), + translate("Limit extended DNS packet size")) + eds.datatype = "and(uinteger,min(512),max(4096))" + eds.rmempty = false + + tlm = s1:taboption("resource", Value, "ttl_min", translate("TTL Minimum:"), + translate("Prevent excessively short cache periods")) + tlm.datatype = "and(uinteger,min(0),max(600))" + tlm.rmempty = false + stt = s1:taboption("resource", Flag, "extended_stats", translate("Extended Statistics:"), translate("Extended statistics are printed from unbound-control")) stt.rmempty = false - tgr = s1:taboption("resource", Value, "trigger", translate("Trigger Networks:"), + tgr = s1:taboption("resource", Value, "trigger_interface", translate("Trigger Networks:"), translate("Networks that may trigger Unbound to reload (avoid wan6)")) tgr.template = "cbi/network_netlist" tgr.widget = "checkbox" diff --git a/applications/luci-app-upnp/luasrc/controller/upnp.lua b/applications/luci-app-upnp/luasrc/controller/upnp.lua index e485708f0..95a0ef486 100644 --- a/applications/luci-app-upnp/luasrc/controller/upnp.lua +++ b/applications/luci-app-upnp/luasrc/controller/upnp.lua @@ -21,7 +21,7 @@ end function act_status() local uci = luci.model.uci.cursor() local lease_file = uci:get("upnpd", "config", "upnp_lease_file") - + local ipt = io.popen("iptables --line-numbers -t nat -xnvL MINIUPNPD 2>/dev/null") if ipt then local upnpf = lease_file and io.open(lease_file, "r") @@ -39,7 +39,7 @@ function act_status() num = tonumber(num) extport = tonumber(extport) intport = tonumber(intport) - + if upnpf then local uln = upnpf:read("*l") if uln then descr = uln:match(string.format("^%s:%d:%s:%d:%%d*:(.*)$", proto:upper(), extport, intaddr, intport)) end @@ -76,7 +76,7 @@ function act_delete(num) local lease_file = uci:get("upnpd", "config", "upnp_lease_file") if lease_file and nixio.fs.access(lease_file) then - luci.sys.call("sed -i -e '%dd' %q" %{ idx, lease_file }) + luci.sys.call("sed -i -e '%dd' %s" %{ idx, luci.util.shellquote(lease_file) }) end luci.http.status(200, "OK") diff --git a/applications/luci-app-upnp/po/zh-cn/upnp.po b/applications/luci-app-upnp/po/zh-cn/upnp.po index 6620d93c0..894de1c26 100644 --- a/applications/luci-app-upnp/po/zh-cn/upnp.po +++ b/applications/luci-app-upnp/po/zh-cn/upnp.po @@ -16,31 +16,31 @@ msgstr "" msgid "" "ACLs specify which external ports may be redirected to which internal " "addresses and ports" -msgstr "指定外部端口的ACL可能会被重定向至某些内部地址及端口" +msgstr "ACL 指定哪些外部端口可以被重定向至哪些内部地址及端口" msgid "Action" msgstr "动作" msgid "Active UPnP Redirects" -msgstr "活动的UPnP重定向" +msgstr "活动的 UPnP 重定向" msgid "Advanced Settings" msgstr "高级设置" msgid "Allow adding forwards only to requesting ip addresses" -msgstr "允许添加只转发给请求的IP地址(当启用时,UPnP的客户可以只转发到其IP)" +msgstr "允许只向请求的 IP 地址添加转发" msgid "Announced model number" -msgstr "公布的型号" +msgstr "通告的型号" msgid "Announced serial number" -msgstr "公布的序列号" +msgstr "通告的序列号" msgid "Clean rules interval" -msgstr "定时自动清除无效规则" +msgstr "定时清除规则" msgid "Clean rules threshold" -msgstr "启动时清除端口转发" +msgstr "清除规则阈值" msgid "Client Address" msgstr "客户端地址" @@ -49,31 +49,31 @@ msgid "Client Port" msgstr "客户端端口" msgid "Collecting data..." -msgstr "正在收集数据" +msgstr "正在收集数据..." msgid "Comment" msgstr "备注" msgid "Delete" -msgstr "" +msgstr "删除" msgid "Description" -msgstr "" +msgstr "描述" msgid "Device UUID" -msgstr "设备UUID" +msgstr "设备 UUID" msgid "Downlink" msgstr "下行速率" msgid "Enable NAT-PMP functionality" -msgstr "启用NAT-PMP功能" +msgstr "启用 NAT-PMP 功能" msgid "Enable UPnP functionality" -msgstr "启用UPnP功能" +msgstr "启用 UPnP 功能" msgid "Enable additional logging" -msgstr "启用额外的日志记录" +msgstr "启用额外的日志" msgid "Enable secure mode" msgstr "启用安全模式" @@ -94,19 +94,19 @@ msgid "Internal ports" msgstr "内部端口" msgid "MiniUPnP ACLs" -msgstr "MiniUPnP的ACL" +msgstr "MiniUPnP 的 ACL" msgid "MiniUPnP settings" -msgstr "MiniUPnP设置" +msgstr "MiniUPnP 设置" msgid "Notify interval" -msgstr "警报间隔" +msgstr "通知间隔" msgid "Port" msgstr "端口" msgid "Presentation URL" -msgstr "显示URL" +msgstr "显示 URL" msgid "Protocol" msgstr "协议" @@ -118,10 +118,10 @@ msgid "Report system instead of daemon uptime" msgstr "用系统运行时间代替进程运行时间" msgid "Start UPnP and NAT-PMP service" -msgstr "启动UPnP与NAT-PMP服务" +msgstr "启动 UPnP 与 NAT-PMP 服务" msgid "There are no active redirects." -msgstr "没有活动的重定向" +msgstr "没有活动的重定向。" msgid "UPnP" msgstr "UPnP" @@ -129,19 +129,19 @@ msgstr "UPnP" msgid "" "UPnP allows clients in the local network to automatically configure the " "router." -msgstr "UPnP允许局域网内客户端自动设置路由上的端口转发。" +msgstr "UPnP 允许局域网内客户端自动设置路由器上的端口转发。" msgid "UPnP lease file" -msgstr "UPnP租约文件" +msgstr "UPnP 租约文件" msgid "Universal Plug & Play" -msgstr "通用即插即用(UPnP)" +msgstr "通用即插即用(UPnP)" msgid "Uplink" msgstr "上行速率" msgid "Value in KByte/s, informational only" -msgstr "值为KByte/s,仅供参考" +msgstr "值为 KByte/s,仅供参考" #~ msgid "Delete Redirect" #~ msgstr "删除转发规则" diff --git a/applications/luci-app-vnstat/luasrc/view/vnstat.htm b/applications/luci-app-vnstat/luasrc/view/vnstat.htm index 2b8d9ff9c..42d7d2404 100644 --- a/applications/luci-app-vnstat/luasrc/view/vnstat.htm +++ b/applications/luci-app-vnstat/luasrc/view/vnstat.htm @@ -21,12 +21,13 @@ style = (style and #style > 0) and style or "s" -- render image -- if iface then - style = style:gsub("[^%w]", "") - iface = iface:gsub("[^%w%.%-%_]", "") - luci.http.prepare_content("image/png") - local png = io.popen("vnstati -i '%s' '-%s' -o -" % { iface, style }) + local png = io.popen("vnstati -i %s -%s -o -" %{ + utl.shellquote(iface), + utl.shellquote(style) + }) + luci.http.write(png:read("*a")) png:close() @@ -89,7 +90,7 @@ dbdir = dbdir or "/var/lib/vnstat" <% end end - end + end %> <% if empty then %> diff --git a/applications/luci-app-vpnbypass/Makefile b/applications/luci-app-vpnbypass/Makefile index 838840e6b..f426acc53 100644 --- a/applications/luci-app-vpnbypass/Makefile +++ b/applications/luci-app-vpnbypass/Makefile @@ -10,7 +10,7 @@ LUCI_TITLE:=VPN Bypass Web UI LUCI_DESCRIPTION:=Provides Web UI for VPNBypass service. LUCI_DEPENDS:=+luci +vpnbypass LUCI_PKGARCH:=all -PKG_RELEASE:=3 +PKG_RELEASE:=4 include ../../luci.mk diff --git a/applications/luci-app-vpnbypass/luasrc/model/cbi/vpnbypass.lua b/applications/luci-app-vpnbypass/luasrc/model/cbi/vpnbypass.lua index 9d2f5f425..6545154c2 100644 --- a/applications/luci-app-vpnbypass/luasrc/model/cbi/vpnbypass.lua +++ b/applications/luci-app-vpnbypass/luasrc/model/cbi/vpnbypass.lua @@ -30,7 +30,7 @@ p2.optional = false -- Local Subnets r1 = s:option(DynamicList, "localsubnet", translate("Local IP Addresses to Bypass"), translate("Local IP addresses or subnets with direct internet access (outside of the VPN tunnel)")) r1.datatype = "ip4addr" --- r1.placeholder = luci.ip.new(uci.cursor():get("network", "lan", "ipaddr") .. "/" .. uci.cursor():get("network", "lan", "netmask")) +-- r1.placeholder = luci.ip.new(m.uci:get("network", "lan", "ipaddr"), m.uci:get("network", "lan", "netmask")) r1.addremove = false r1.optional = false diff --git a/applications/luci-app-vpnbypass/po/ru/vpnbypass.po b/applications/luci-app-vpnbypass/po/ru/vpnbypass.po index 05e21935a..d41cfac0c 100644 --- a/applications/luci-app-vpnbypass/po/ru/vpnbypass.po +++ b/applications/luci-app-vpnbypass/po/ru/vpnbypass.po @@ -28,14 +28,14 @@ msgid "" "Local IP addresses or subnets with direct internet access (outside of the " "VPN tunnel)" msgstr "" -"Локальные IP-адреса или подсети с прямым доступом в Интернет (вне VPN-" +"Локальные IP-адреса или подсети с прямым доступом в интернет (вне VPN-" "туннеля)." msgid "Local Ports to Bypass" -msgstr "Локальные порты
для обхода VPN" +msgstr "Локальные порты для запуска обхода VPN" msgid "Local ports to trigger VPN Bypass" -msgstr "Локальные порты для запуска обхода VPN." +msgstr "Локальные порты
для обхода VPN" msgid "README" msgstr "Описание" @@ -54,10 +54,10 @@ msgid "Remote Ports to Bypass" msgstr "Удаленные порты
для обхода VPN" msgid "Remote ports to trigger VPN Bypass" -msgstr "Удаленные порты для запуска обхода VPN." +msgstr "Удаленные порты для запуска обхода VPN" msgid "Start VPNBypass service" -msgstr "Запуск сервиса VPNBypass" +msgstr "" msgid "VPN Bypass" msgstr "Обход VPN" @@ -66,4 +66,7 @@ msgid "VPN Bypass Settings" msgstr "Настройка обхода VPN" msgid "for syntax" -msgstr "для синтаксиса." +msgstr "для синтаксиса" + +#~ msgid "Enable/start service" +#~ msgstr "Включение / Запуск сервиса" diff --git a/applications/luci-app-wireguard/Makefile b/applications/luci-app-wireguard/Makefile index 92cdcf270..ae315bdfe 100644 --- a/applications/luci-app-wireguard/Makefile +++ b/applications/luci-app-wireguard/Makefile @@ -7,7 +7,7 @@ include $(TOPDIR)/rules.mk LUCI_TITLE:=WireGuard Status -LUCI_DEPENDS:=+wireguard-tools +kmod-wireguard +LUCI_DEPENDS:=+wireguard-tools +kmod-wireguard +luci-proto-wireguard LUCI_PKGARCH:=all PKG_MAINTAINER:=Dan Luedtke diff --git a/applications/luci-app-wol/luasrc/controller/wol.lua b/applications/luci-app-wol/luasrc/controller/wol.lua index dbbfdde12..43ab84ab2 100644 --- a/applications/luci-app-wol/luasrc/controller/wol.lua +++ b/applications/luci-app-wol/luasrc/controller/wol.lua @@ -1,6 +1,6 @@ module("luci.controller.wol", package.seeall) function index() - entry({"admin", "services", "wol"}, cbi("wol"), _("Wake on LAN"), 90) - entry({"mini", "services", "wol"}, cbi("wol"), _("Wake on LAN"), 90) + entry({"admin", "services", "wol"}, form("wol"), _("Wake on LAN"), 90) + entry({"mini", "services", "wol"}, form("wol"), _("Wake on LAN"), 90) end diff --git a/applications/luci-app-wol/luasrc/model/cbi/wol.lua b/applications/luci-app-wol/luasrc/model/cbi/wol.lua index d40dde017..43b87dda9 100644 --- a/applications/luci-app-wol/luasrc/model/cbi/wol.lua +++ b/applications/luci-app-wol/luasrc/model/cbi/wol.lua @@ -1,6 +1,7 @@ -- Copyright 2010 Jo-Philipp Wich -- Licensed to the public under the Apache License 2.0. +local utl = require "luci.util" local sys = require "luci.sys" local ipc = require "luci.ip" local fs = require "nixio.fs" @@ -69,8 +70,8 @@ function host.write(self, s, val) if util == "/usr/bin/etherwake" then local iface = luci.http.formvalue("cbid.wol.1.iface") local broadcast = luci.http.formvalue("cbid.wol.1.broadcast") - cmd = "%s -D%s %s %q" %{ - util, (iface ~= "" and " -i %q" % iface or ""), + cmd = "%s -D%s %s %q 2>&1" %{ + util, (iface ~= "" and " -i %s" % utl.shellquote(iface) or ""), (broadcast == "1" and " -b" or ""), mac } else @@ -78,7 +79,7 @@ function host.write(self, s, val) end local msg = "

%s

%s

" %{ - translate("Starting WoL utility:"), cmd + translate("Starting WoL utility:"), utl.pcdata(cmd) } local p = io.popen(cmd .. " 2>&1") diff --git a/build/check-controllers.sh b/build/check-controllers.sh new file mode 100755 index 000000000..573e6f864 --- /dev/null +++ b/build/check-controllers.sh @@ -0,0 +1,30 @@ +#!/usr/bin/env bash + +[ -d build ] || { + echo "Execute as ./build/check-controllers.sh" >&2 + exit 1 +} + +find . -type f -name '*.lua' -path '*/controller/*' | while read controller; do + controller="${controller#./}" + base="${controller%%/controller/*}" + + sed -rne 's#^.*\b(cbi|form)\([[:space:]]*("([^"]*)"|\047([^\047]*)\047)[[:space:]]*[,)].*$#\1 \3\4#gp' "$controller" | while read type map; do + model="$base/model/cbi/$map.lua" + package="${controller##*/controller/}"; package="${package%.lua}"; package="luci.controller.${package//\//.}" + + if ! grep -sqE '\bmodule[[:space:]]*\(?[[:space:]]*("|\047|\[=*\[)'"$package" "$controller"; then + echo "'$controller' does not containt the expected\n\t'module(\"$package\", ...)' line.\n" + fi + + grep -sqE '\b(Form|SimpleForm)[[:space:]]*\(' "$model" && ! grep -sqE '\bMap[[:space:]]*\(' "$model" && is_form=1 || is_form=0 + + if [ ! -f "$model" ]; then + echo -e "'$controller' references $type('$map')\n\tbut expected file '$model' does not exist.\n" + elif [ $type = "cbi" -a $is_form = 1 ]; then + echo -e "'$controller' references $type('$map')\n\tbut '$model' looks like a Form or SimpleForm.\n" + elif [ $type = "form" -a $is_form = 0 ]; then + echo -e "'$controller' references $type('$map')\n\tbut '$model' does not look like a Form or SimpleForm.\n" + fi + done +done diff --git a/contrib/package/community-profiles/files/etc/config/profile_berlin b/contrib/package/community-profiles/files/etc/config/profile_berlin index 1bfc8ed7d..e1e4eda91 100644 --- a/contrib/package/community-profiles/files/etc/config/profile_berlin +++ b/contrib/package/community-profiles/files/etc/config/profile_berlin @@ -33,7 +33,7 @@ config 'defaults' 'ssidscheme' config 'defaults' 'interface' option 'netmask' '255.255.255.255' - option 'dns' '85.214.20.141 213.73.91.35 194.150.168.168 2001:4ce8::53 2001:910:800::12' + option 'dns' '85.214.20.141 194.150.168.168 2001:4ce8::53 2001:910:800::12' config 'dhcp' 'dhcp' option leasetime '5m' diff --git a/contrib/package/community-profiles/files/etc/config/profile_cottbus b/contrib/package/community-profiles/files/etc/config/profile_cottbus index 6f395a133..9b08acc25 100644 --- a/contrib/package/community-profiles/files/etc/config/profile_cottbus +++ b/contrib/package/community-profiles/files/etc/config/profile_cottbus @@ -31,7 +31,7 @@ config 'defaults' 'ssidscheme' config 'defaults' 'interface' option 'netmask' '255.255.255.255' - option 'dns' '85.214.20.141 213.73.91.35 194.150.168.168 2001:4ce8::53 2001:910:800::12' + option 'dns' '85.214.20.141 194.150.168.168 2001:4ce8::53 2001:910:800::12' config 'dhcp' 'dhcp' option 'leasetime' '5m' diff --git a/contrib/package/community-profiles/files/etc/config/profile_potsdam b/contrib/package/community-profiles/files/etc/config/profile_potsdam index 6a8f1f14b..84bbdfe52 100644 --- a/contrib/package/community-profiles/files/etc/config/profile_potsdam +++ b/contrib/package/community-profiles/files/etc/config/profile_potsdam @@ -11,7 +11,7 @@ config 'community' 'profile' config 'defaults' 'interface' option 'netmask' '255.255.0.0' - option 'dns' '85.214.20.141 213.73.91.35 194.150.168.168' + option 'dns' '85.214.20.141 194.150.168.168' option 'delegate' '0' config 'defaults' 'wifi_device' diff --git a/contrib/package/community-profiles/files/etc/config/profile_tulumlibre b/contrib/package/community-profiles/files/etc/config/profile_tulumlibre index ecc6f9bc4..c028a6661 100644 --- a/contrib/package/community-profiles/files/etc/config/profile_tulumlibre +++ b/contrib/package/community-profiles/files/etc/config/profile_tulumlibre @@ -7,4 +7,4 @@ config 'community' 'profile' option 'splash_prefix' '28' config 'defaults' 'interface' - option 'dns' '213.73.91.35 216.87.84.211' + option 'dns' '216.87.84.211' diff --git a/contrib/package/freifunk-common/Makefile b/contrib/package/freifunk-common/Makefile index 2b9336fb0..f7128b641 100644 --- a/contrib/package/freifunk-common/Makefile +++ b/contrib/package/freifunk-common/Makefile @@ -15,6 +15,7 @@ define Package/freifunk-common CATEGORY:=LuCI SUBMENU:=9. Freifunk TITLE:=Freifunk common files + DEPENDS:=+libuci-lua endef define Package/freifunk-common/description diff --git a/contrib/package/lucihttp/Makefile b/contrib/package/lucihttp/Makefile new file mode 100644 index 000000000..f1926a8e3 --- /dev/null +++ b/contrib/package/lucihttp/Makefile @@ -0,0 +1,54 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=lucihttp +PKG_RELEASE:=1 + +PKG_SOURCE_PROTO:=git +PKG_SOURCE_URL=https://github.com/jow-/lucihttp.git +PKG_SOURCE_DATE:=2018-04-22 +PKG_SOURCE_VERSION:=ccc685e5c366490fc9f50a2e211ec79b7cf5962e +PKG_MIRROR_HASH:=48608971cdfe20a6ad476fbf461527e4bf4786afeb8316fd6c38412bfeed4a3c +CMAKE_INSTALL:=1 + +PKG_LICENSE:=ISC +PKG_LICENSE_FILES:=LICENSE + +PKG_MAINTAINER:=Jo-Philipp Wich +PKG_CONFIG_DEPENDS:=CONFIG_PACKAGE_liblucihttp-lua + +include $(INCLUDE_DIR)/package.mk +include $(INCLUDE_DIR)/cmake.mk + +define Package/liblucihttp + SECTION:=libs + CATEGORY:=Libraries + ABI_VERSION:=$(PKG_VERSION) + TITLE:=LuCI HTTP utility library +endef + +define Package/liblucihttp-lua + SECTION:=libs + CATEGORY:=Libraries + DEPENDS:=+liblucihttp +liblua + TITLE:=Lua binding for the LuCI HTTP utility library +endef + +TARGET_CFLAGS += -I$(STAGING_DIR)/usr/include + +CMAKE_OPTIONS = \ + -DLUAPATH=/usr/lib/lua \ + -DBUILD_LUA=$(if $(CONFIG_PACKAGE_liblucihttp-lua),ON,OFF) \ + -DBUILD_TESTS=OFF + +define Package/liblucihttp/install + $(INSTALL_DIR) $(1)/usr/lib + $(CP) $(PKG_INSTALL_DIR)/usr/lib/liblucihttp.so $(1)/usr/lib/ +endef + +define Package/liblucihttp-lua/install + $(INSTALL_DIR) $(1)/usr/lib/lua + $(CP) $(PKG_INSTALL_DIR)/usr/lib/lua/lucihttp.so $(1)/usr/lib/lua/ +endef + +$(eval $(call BuildPackage,liblucihttp)) +$(eval $(call BuildPackage,liblucihttp-lua)) diff --git a/documentation/api/index.html b/documentation/api/index.html index c762b9b0e..5e3f3c211 100644 --- a/documentation/api/index.html +++ b/documentation/api/index.html @@ -43,19 +43,15 @@

  • - luci.http.protocol + luci.http.conditionals
  • - luci.http.protocol.conditionals + luci.http.date
  • - luci.http.protocol.date -
  • - -
  • - luci.http.protocol.mime + luci.http.mime
  • @@ -214,22 +210,17 @@ - luci.http.protocol - - - - - luci.http.protocol.conditionals + luci.http.conditionals - luci.http.protocol.date + luci.http.date - luci.http.protocol.mime + luci.http.mime diff --git a/documentation/api/modules/luci.dispatcher.html b/documentation/api/modules/luci.dispatcher.html index 4ae88fe61..e4b12e676 100644 --- a/documentation/api/modules/luci.dispatcher.html +++ b/documentation/api/modules/luci.dispatcher.html @@ -41,19 +41,15 @@
  • - luci.http.protocol + luci.http.conditionals
  • - luci.http.protocol.conditionals + luci.http.date
  • - luci.http.protocol.date -
  • - -
  • - luci.http.protocol.mime + luci.http.mime
  • @@ -321,7 +317,6 @@ Create a CBI form model dispatching target. Fetch or create a dispatching node without setting the target module or - enabling the node. @@ -333,6 +328,13 @@ Dispatch an HTTP request. + lookup (...) + + +Lookup node in dispatching tree. + + + modifier (func, order) @@ -857,8 +859,8 @@ Create a CBI form model dispatching target. Fetch or create a dispatching node without setting the target module or - -enabling the node. +enabling the node. +

    Parameters

    @@ -914,6 +916,38 @@ Dispatch an HTTP request. +
    lookup (...)
    +
    + + +Lookup node in dispatching tree. + + + +

    Parameters

    +
      + +
    • + ...: Virtual path +
    • + +
    + + + + + + +

    Return value:

    +Node object, canonical url or nil if the path was not found. + + + +
    + + + +
    modifier (func, order)
    diff --git a/documentation/api/modules/luci.http.html b/documentation/api/modules/luci.http.html index ea04fc236..d75863fa6 100644 --- a/documentation/api/modules/luci.http.html +++ b/documentation/api/modules/luci.http.html @@ -41,19 +41,15 @@
  • luci.http
  • - luci.http.protocol + luci.http.conditionals
  • - luci.http.protocol.conditionals + luci.http.date
  • - luci.http.protocol.date -
  • - -
  • - luci.http.protocol.mime + luci.http.mime
  • @@ -256,7 +252,6 @@ Get the value of a certain HTTP-Cookie. Get the value of a certain HTTP environment variable - or the environment table itself. @@ -268,6 +263,20 @@ Send a HTTP-Header. + mimedecode_message_body (src, msg, filecb) + + +Decode a mime encoded http message body with multipart/form-data Content-Type. + + + + parse_message_body (src, msg, filecb) + + +Try to extract and decode a http message body from the given ltn12 source. + + + prepare_content (mime) @@ -311,6 +320,44 @@ Set the HTTP status code and status message. + urldecode (str, no_plus) + + +Return the URL-decoded equivalent of a string. + + + + urldecode_message_body (src, msg) + + +Decode an urlencoded http message body with application/x-www-urlencoded +Content-Type. + + + + urldecode_params (url, tbl) + + +Extract and split urlencoded data pairs, separated bei either "&" or ";" +from given url or string. + + + + urlencode (str) + + +Return the URL-encoded equivalent of a string. + + + + urlencode_params (tbl) + + +Encode each key-value-pair in given table to x-www-urlencoded format, +separated by "&". + + + write (content, src_err) @@ -377,7 +424,6 @@ Encoded HTTP query string Close the HTTP-Connection. - @@ -527,8 +573,8 @@ String containing cookie data Get the value of a certain HTTP environment variable - -or the environment table itself. +or the environment table itself. +

    Parameters

    @@ -588,6 +634,135 @@ Send a HTTP-Header. +
    mimedecode_message_body (src, msg, filecb)
    +
    + + +Decode a mime encoded http message body with multipart/form-data Content-Type. + +Stores all extracted data associated with its parameter name +in the params table within the given message object. Multiple parameter +values are stored as tables, ordinary ones as strings. + +If an optional file callback function is given then it is feeded with the +file contents chunk by chunk and only the extracted file name is stored +within the params table. The callback function will be called subsequently +with three arguments: + o Table containing decoded (name, file) and raw (headers) mime header data + o String value containing a chunk of the file data + o Boolean which indicates wheather the current chunk is the last one (eof) + + + +

    Parameters

    +
      + +
    • + src: Ltn12 source function +
    • + +
    • + msg: HTTP message object +
    • + +
    • + filecb: File callback function (optional) +
    • + +
    + + + + + + +

    Return values:

    +
      + +
    1. Value indicating successful operation (not nil means "ok") + +
    2. String containing the error if unsuccessful + +
    + + + +

    See also:

    + + +
    + + + + +
    parse_message_body (src, msg, filecb)
    +
    + + +Try to extract and decode a http message body from the given ltn12 source. +This function will examine the Content-Type within the given message object +to select the appropriate content decoder. + +Currently the application/x-www-urlencoded and application/form-data +mime types are supported. If the encountered content encoding can't be +handled then the whole message body will be stored unaltered as "content" +property within the given message object. + + + +

    Parameters

    +
      + +
    • + src: Ltn12 source function +
    • + +
    • + msg: HTTP message object +
    • + +
    • + filecb: File data callback (optional, see mimedecode_message_body()) +
    • + +
    + + + + + + +

    Return values:

    +
      + +
    1. Value indicating successful operation (not nil means "ok") + +
    2. String containing the error if unsuccessful + +
    + + + +

    See also:

    + + +
    + + + +
    prepare_content (mime)
    @@ -764,6 +939,243 @@ Set the HTTP status code and status message. +
    urldecode (str, no_plus)
    +
    + + +Return the URL-decoded equivalent of a string. + + + +

    Parameters

    +
      + +
    • + str: URL-encoded string +
    • + +
    • + no_plus: Don't decode + to " " +
    • + +
    + + + + + + +

    Return value:

    +URL-decoded string + + + +

    See also:

    + + +
    + + + + +
    urldecode_message_body (src, msg)
    +
    + + +Decode an urlencoded http message body with application/x-www-urlencoded +Content-Type. + +Stores all extracted data associated with its parameter name in the params +table within the given message object. Multiple parameter values are stored +as tables, ordinary ones as strings. + + + +

    Parameters

    +
      + +
    • + src: Ltn12 source function +
    • + +
    • + msg: HTTP message object +
    • + +
    + + + + + + +

    Return values:

    +
      + +
    1. Value indicating successful operation (not nil means "ok") + +
    2. String containing the error if unsuccessful + +
    + + + +

    See also:

    + + +
    + + + + +
    urldecode_params (url, tbl)
    +
    + + +Extract and split urlencoded data pairs, separated bei either "&" or ";" +from given url or string. Returns a table with urldecoded values. + +Simple parameters are stored as string values associated with the parameter +name within the table. Parameters with multiple values are stored as array +containing the corresponding values. + + + +

    Parameters

    +
      + +
    • + url: The url or string which contains x-www-urlencoded form data +
    • + +
    • + tbl: Use the given table for storing values (optional) +
    • + +
    + + + + + + +

    Return value:

    +Table containing the urldecoded parameters + + + +

    See also:

    + + +
    + + + + +
    urlencode (str)
    +
    + + +Return the URL-encoded equivalent of a string. + + + +

    Parameters

    +
      + +
    • + str: Source string +
    • + +
    + + + + + + +

    Return value:

    +URL-encoded string + + + +

    See also:

    + + +
    + + + + +
    urlencode_params (tbl)
    +
    + + +Encode each key-value-pair in given table to x-www-urlencoded format, +separated by "&". + +Tables are encoded as parameters with multiple values by repeating the +parameter name with each value. + + + +

    Parameters

    +
      + +
    • + tbl: Table with the values +
    • + +
    + + + + + + +

    Return value:

    +String containing encoded values + + + +

    See also:

    + + +
    + + + +
    write (content, src_err)
    @@ -771,7 +1183,8 @@ Set the HTTP status code and status message. Send a chunk of content data to the client. This function is as a valid LTN12 sink. -If the content chunk is nil this function will automatically invoke close. +If the content chunk is nil this function will automatically invoke close. +

    Parameters

    diff --git a/documentation/api/modules/luci.i18n.html b/documentation/api/modules/luci.i18n.html index 0111cb200..3f0738bf1 100644 --- a/documentation/api/modules/luci.i18n.html +++ b/documentation/api/modules/luci.i18n.html @@ -43,19 +43,15 @@
  • - luci.http.protocol + luci.http.conditionals
  • - luci.http.protocol.conditionals + luci.http.date
  • - luci.http.protocol.date -
  • - -
  • - luci.http.protocol.mime + luci.http.mime
  • luci.i18n
  • diff --git a/documentation/api/modules/luci.ip.cidr.html b/documentation/api/modules/luci.ip.cidr.html index 5a2b06ec6..50633a773 100644 --- a/documentation/api/modules/luci.ip.cidr.html +++ b/documentation/api/modules/luci.ip.cidr.html @@ -43,19 +43,15 @@
  • - luci.http.protocol + luci.http.conditionals
  • - luci.http.protocol.conditionals + luci.http.date
  • - luci.http.protocol.date -
  • - -
  • - luci.http.protocol.mime + luci.http.mime
  • diff --git a/documentation/api/modules/luci.ip.html b/documentation/api/modules/luci.ip.html index 1f89626fa..fc13e31e5 100644 --- a/documentation/api/modules/luci.ip.html +++ b/documentation/api/modules/luci.ip.html @@ -43,19 +43,15 @@
  • - luci.http.protocol + luci.http.conditionals
  • - luci.http.protocol.conditionals + luci.http.date
  • - luci.http.protocol.date -
  • - -
  • - luci.http.protocol.mime + luci.http.mime
  • diff --git a/documentation/api/modules/luci.json.html b/documentation/api/modules/luci.json.html index 761bd6e7e..db2d1da3f 100644 --- a/documentation/api/modules/luci.json.html +++ b/documentation/api/modules/luci.json.html @@ -43,19 +43,15 @@
  • - luci.http.protocol + luci.http.conditionals
  • - luci.http.protocol.conditionals + luci.http.date
  • - luci.http.protocol.date -
  • - -
  • - luci.http.protocol.mime + luci.http.mime
  • diff --git a/documentation/api/modules/luci.jsonc.html b/documentation/api/modules/luci.jsonc.html index f82eb406c..79deb933d 100644 --- a/documentation/api/modules/luci.jsonc.html +++ b/documentation/api/modules/luci.jsonc.html @@ -43,19 +43,15 @@
  • - luci.http.protocol + luci.http.conditionals
  • - luci.http.protocol.conditionals + luci.http.date
  • - luci.http.protocol.date -
  • - -
  • - luci.http.protocol.mime + luci.http.mime
  • diff --git a/documentation/api/modules/luci.jsonc.parser.html b/documentation/api/modules/luci.jsonc.parser.html index e8e145f43..709cb9afc 100644 --- a/documentation/api/modules/luci.jsonc.parser.html +++ b/documentation/api/modules/luci.jsonc.parser.html @@ -43,19 +43,15 @@
  • - luci.http.protocol + luci.http.conditionals
  • - luci.http.protocol.conditionals + luci.http.date
  • - luci.http.protocol.date -
  • - -
  • - luci.http.protocol.mime + luci.http.mime
  • diff --git a/documentation/api/modules/luci.model.ipkg.html b/documentation/api/modules/luci.model.ipkg.html index 921153c98..a0af3187b 100644 --- a/documentation/api/modules/luci.model.ipkg.html +++ b/documentation/api/modules/luci.model.ipkg.html @@ -43,19 +43,15 @@
  • - luci.http.protocol + luci.http.conditionals
  • - luci.http.protocol.conditionals + luci.http.date
  • - luci.http.protocol.date -
  • - -
  • - luci.http.protocol.mime + luci.http.mime
  • diff --git a/documentation/api/modules/luci.model.uci.html b/documentation/api/modules/luci.model.uci.html index c84d1eb0e..77a81fd46 100644 --- a/documentation/api/modules/luci.model.uci.html +++ b/documentation/api/modules/luci.model.uci.html @@ -43,19 +43,15 @@
  • - luci.http.protocol + luci.http.conditionals
  • - luci.http.protocol.conditionals + luci.http.date
  • - luci.http.protocol.date -
  • - -
  • - luci.http.protocol.mime + luci.http.mime
  • @@ -310,6 +306,13 @@ Get the directory for uncomitted changes. + Cursor:get_session_id () + + +Get the effective session ID. + + + Cursor:load (config) @@ -366,6 +369,13 @@ Set the directory for uncommited changes. + Cursor:set_session_id (id) + + +Set the effective session ID. + + + Cursor:substate () @@ -631,8 +641,8 @@ Delete all sections of a given type that match certain criteria.
  • - comparator: Function that will be called for each section and -returns a boolean whether to delete the current section (optional) + comparator: Function that will be called for each section and returns + a boolean whether to delete the current section (optional)
  • @@ -903,8 +913,8 @@ Get an option or list and return values as table.

    Return value:

    -table. If the option was not found, you will simply get - an empty table. +table. If the option was not found, you will simply get an empty + table. @@ -936,6 +946,29 @@ Save directory +
    Cursor:get_session_id ()
    +
    + + +Get the effective session ID. + + + + + + + + +

    Return value:

    +String containing the session ID + + + +
    + + + +
    Cursor:load (config)
    @@ -1222,7 +1255,8 @@ has the same effect as deleting the option.
  • - value: value or table. Raw values will become a single item table. + value: Value or table. Non-table values will be set as single + item UCI list.
  • @@ -1274,14 +1308,47 @@ Boolean whether operation succeeded +
    Cursor:set_session_id (id)
    +
    + + +Set the effective session ID. + + + +

    Parameters

    +
      + +
    • + id: String containing the session ID to set +
    • + +
    + + + + + + +

    Return value:

    +Boolean whether operation succeeded + + + +
    + + + +
    Cursor:substate ()
    -Create a sub-state of this cursor. The sub-state is tied to the parent +Create a sub-state of this cursor. -curser, means it the parent unloads or loads configs, the sub state will -do so as well. +The sub-state is tied to the parent curser, means it the parent unloads or +loads configs, the sub state will do so as well. + diff --git a/documentation/api/modules/luci.rpcc.html b/documentation/api/modules/luci.rpcc.html index f7cb02048..18065788b 100644 --- a/documentation/api/modules/luci.rpcc.html +++ b/documentation/api/modules/luci.rpcc.html @@ -43,19 +43,15 @@
  • - luci.http.protocol + luci.http.conditionals
  • - luci.http.protocol.conditionals + luci.http.date
  • - luci.http.protocol.date -
  • - -
  • - luci.http.protocol.mime + luci.http.mime
  • diff --git a/documentation/api/modules/luci.rpcc.ruci.html b/documentation/api/modules/luci.rpcc.ruci.html index 203779ce7..7348f1932 100644 --- a/documentation/api/modules/luci.rpcc.ruci.html +++ b/documentation/api/modules/luci.rpcc.ruci.html @@ -43,19 +43,15 @@
  • - luci.http.protocol + luci.http.conditionals
  • - luci.http.protocol.conditionals + luci.http.date
  • - luci.http.protocol.date -
  • - -
  • - luci.http.protocol.mime + luci.http.mime
  • diff --git a/documentation/api/modules/luci.sys.html b/documentation/api/modules/luci.sys.html index 860c5fba2..6342a51d5 100644 --- a/documentation/api/modules/luci.sys.html +++ b/documentation/api/modules/luci.sys.html @@ -43,19 +43,15 @@
  • - luci.http.protocol + luci.http.conditionals
  • - luci.http.protocol.conditionals + luci.http.date
  • - luci.http.protocol.date -
  • - -
  • - luci.http.protocol.mime + luci.http.mime
  • diff --git a/documentation/api/modules/luci.sys.init.html b/documentation/api/modules/luci.sys.init.html index 596fb7cd1..e2c51f953 100644 --- a/documentation/api/modules/luci.sys.init.html +++ b/documentation/api/modules/luci.sys.init.html @@ -43,19 +43,15 @@
  • - luci.http.protocol + luci.http.conditionals
  • - luci.http.protocol.conditionals + luci.http.date
  • - luci.http.protocol.date -
  • - -
  • - luci.http.protocol.mime + luci.http.mime
  • diff --git a/documentation/api/modules/luci.sys.iptparser.html b/documentation/api/modules/luci.sys.iptparser.html index 122afcc2a..5928281cf 100644 --- a/documentation/api/modules/luci.sys.iptparser.html +++ b/documentation/api/modules/luci.sys.iptparser.html @@ -43,19 +43,15 @@
  • - luci.http.protocol + luci.http.conditionals
  • - luci.http.protocol.conditionals + luci.http.date
  • - luci.http.protocol.date -
  • - -
  • - luci.http.protocol.mime + luci.http.mime
  • diff --git a/documentation/api/modules/luci.sys.net.html b/documentation/api/modules/luci.sys.net.html index 09cef175f..e7802bb24 100644 --- a/documentation/api/modules/luci.sys.net.html +++ b/documentation/api/modules/luci.sys.net.html @@ -43,19 +43,15 @@
  • - luci.http.protocol + luci.http.conditionals
  • - luci.http.protocol.conditionals + luci.http.date
  • - luci.http.protocol.date -
  • - -
  • - luci.http.protocol.mime + luci.http.mime
  • diff --git a/documentation/api/modules/luci.sys.process.html b/documentation/api/modules/luci.sys.process.html index 9c4f0a540..ffe09bdc2 100644 --- a/documentation/api/modules/luci.sys.process.html +++ b/documentation/api/modules/luci.sys.process.html @@ -43,19 +43,15 @@
  • - luci.http.protocol + luci.http.conditionals
  • - luci.http.protocol.conditionals + luci.http.date
  • - luci.http.protocol.date -
  • - -
  • - luci.http.protocol.mime + luci.http.mime
  • diff --git a/documentation/api/modules/luci.sys.user.html b/documentation/api/modules/luci.sys.user.html index 37126dd92..04f8bf02b 100644 --- a/documentation/api/modules/luci.sys.user.html +++ b/documentation/api/modules/luci.sys.user.html @@ -43,19 +43,15 @@
  • - luci.http.protocol + luci.http.conditionals
  • - luci.http.protocol.conditionals + luci.http.date
  • - luci.http.protocol.date -
  • - -
  • - luci.http.protocol.mime + luci.http.mime
  • diff --git a/documentation/api/modules/luci.sys.wifi.html b/documentation/api/modules/luci.sys.wifi.html index eb1f6b31d..6c893244c 100644 --- a/documentation/api/modules/luci.sys.wifi.html +++ b/documentation/api/modules/luci.sys.wifi.html @@ -43,19 +43,15 @@
  • - luci.http.protocol + luci.http.conditionals
  • - luci.http.protocol.conditionals + luci.http.date
  • - luci.http.protocol.date -
  • - -
  • - luci.http.protocol.mime + luci.http.mime
  • diff --git a/documentation/api/modules/luci.util.html b/documentation/api/modules/luci.util.html index 70d27d331..d3d45a180 100644 --- a/documentation/api/modules/luci.util.html +++ b/documentation/api/modules/luci.util.html @@ -43,19 +43,15 @@
  • - luci.http.protocol + luci.http.conditionals
  • - luci.http.protocol.conditionals + luci.http.date
  • - luci.http.protocol.date -
  • - -
  • - luci.http.protocol.mime + luci.http.mime
  • @@ -275,13 +271,6 @@ This is a coroutine-safe drop-in replacement for Lua's "xpcall"-function - dtable () - - -Create a dynamic table which automatically creates subtables. - - - dumptable (t, maxdepth) @@ -349,7 +338,6 @@ Returns the absolute path to LuCI base directory. Parse certain units from the given string and return the canonical integer - value or 0 if the unit is unknown. @@ -379,7 +367,6 @@ Restore data previously serialized with serialize_data(). Recursively serialize given data to lua code, suitable for restoring - with loadstring(). @@ -392,11 +379,17 @@ Convert data structure to JSON + shellquote (value) + + +Safely quote value for use in shell commands. + + + spairs (t, f) Return a key, value iterator which returns the values sorted according to - the provided callback function. @@ -405,7 +398,6 @@ the provided callback function. Splits given string on a defined separator sequence and return a table - containing the resulting substrings. @@ -428,7 +420,6 @@ Strip HTML tags from given string. Create a new or get an already existing thread local store associated with - the current active coroutine. @@ -454,6 +445,20 @@ Update values in given table with the values from the second given table. + urldecode (str, decode_plus) + + +Decode an URL-encoded string - optionally decoding the "+" sign to space. + + + + urlencode (str) + + +URL-encode given string. + + + vspairs (t) @@ -549,7 +554,8 @@ Classes can inherit member functions and values from a base class. Class can be instantiated by calling them. All parameters will be passed to the __init__ function of this class - if such a function exists. The __init__ function must be used to set any object parameters that are not shared -with other objects of this class. Any return values will be ignored. +with other objects of this class. Any return values will be ignored. +

    Parameters

    @@ -728,8 +734,8 @@ Checks whether the given table contains the given value.

    Return value:

    -number indicating the first index at which the given value occurs - within table or false. +Number indicating the first index at which the given value occurs + within table or false. @@ -766,7 +772,7 @@ This is a coroutine-safe drop-in replacement for Lua's "pcall"-function

    Return value:

    A boolean whether the function call succeeded and the returns - values of the function or the error object + values of the function or the error object @@ -807,30 +813,7 @@ This is a coroutine-safe drop-in replacement for Lua's "xpcall"-function

    Return value:

    A boolean whether the function call succeeded and the return - values of either the function or the error handler - - - -
  • - - - - -
    dtable ()
    -
    - - -Create a dynamic table which automatically creates subtables. - - - - - - - - -

    Return value:

    -Dynamic Table + values of either the function or the error handler @@ -944,8 +927,8 @@ Iterator Return the current runtime bytecode of the given data. The byte code - -will be stripped before it is returned. +will be stripped before it is returned. +

    Parameters

    @@ -976,11 +959,12 @@ String value containing the bytecode of the given data
    -Return a matching iterator for the given value. The iterator will return +Return a matching iterator for the given value. -one token per invocation, the tokens are separated by whitespace. If the -input value is a table, it is transformed into a string first. A nil value -will result in a valid interator which aborts with the first invocation. +The iterator will return one token per invocation, the tokens are separated by +whitespace. If the input value is a table, it is transformed into a string first. +A nil value will result in a valid interator which aborts with the first invocation. +

    Parameters

    @@ -1094,7 +1078,8 @@ Sorted table containing the keys Return a key, value iterator for the given table. -The table pairs are sorted by key. +The table pairs are sorted by key. +

    Parameters

    @@ -1149,9 +1134,11 @@ String containing the directory path Parse certain units from the given string and return the canonical integer +value or 0 if the unit is unknown. -value or 0 if the unit is unknown. Upper- or lower case is irrelevant. +Upper- or lower case is irrelevant. Recognized units are: + o "y" - one year (60*60*24*366) o "m" - one month (60*60*24*31) o "w" - one week (60*60*24*7) @@ -1163,7 +1150,8 @@ Recognized units are: o "gb" - one gigabyte (1024*1024*1024) o "kib" - one si kilobyte (1000) o "mib" - one si megabyte (1000*1000) - o "gib" - one si gigabyte (1000*1000*1000) + o "gib" - one si gigabyte (1000*1000*1000) +

    Parameters

    @@ -1304,8 +1292,8 @@ Value containing the restored data structure Recursively serialize given data to lua code, suitable for restoring - -with loadstring(). +with loadstring(). +

    Parameters

    @@ -1381,13 +1369,45 @@ String containing the JSON if called without write callback +
    shellquote (value)
    +
    + + +Safely quote value for use in shell commands. + + + +

    Parameters

    +
      + +
    • + value: String containing the value to quote +
    • + +
    + + + + + + +

    Return value:

    +Single-quote enclosed string with embedded quotes escaped + + + +
    + + + +
    spairs (t, f)
    Return a key, value iterator which returns the values sorted according to - -the provided callback function. +the provided callback function. +

    Parameters

    @@ -1423,11 +1443,13 @@ Function value containing the corresponding iterator Splits given string on a defined separator sequence and return a table +containing the resulting substrings. -containing the resulting substrings. The optional max parameter specifies -the number of bytes to process, regardless of the actual length of the given -string. The optional last parameter, regex, specifies whether the separator -sequence is interpreted as regular expression. +The optional max parameter specifies the number of bytes to process, +regardless of the actual length of the given string. The optional last +parameter, regex, specifies whether the separator sequence is +nterpreted as regular expression. +

    Parameters

    @@ -1471,10 +1493,11 @@ Table containing the resulting substrings
    -Strips unnescessary lua bytecode from given string. Information like line +Strips unnescessary lua bytecode from given string. -numbers and debugging numbers will be discarded. Original version by -Peter Cawley (http://lua-users.org/lists/lua-l/2008-02/msg01158.html) +Information like line numbers and debugging numbers will be discarded. +Original version by Peter Cawley (http://lua-users.org/lists/lua-l/2008-02/msg01158.html) +

    Parameters

    @@ -1538,9 +1561,11 @@ String with HTML tags stripped of Create a new or get an already existing thread local store associated with +the current active coroutine. -the current active coroutine. A thread local store is private a table object -whose values can't be accessed from outside of the running coroutine. +A thread local store is private a table object +whose values can't be accessed from outside of the running coroutine. + @@ -1636,7 +1661,8 @@ Table containin the ubus result Update values in given table with the values from the second given table. -Both table are - in fact - merged together. +Both table are - in fact - merged together. +

    Parameters

    @@ -1667,13 +1693,100 @@ Always nil +
    urldecode (str, decode_plus)
    +
    + + +Decode an URL-encoded string - optionally decoding the "+" sign to space. + + + +

    Parameters

    +
      + +
    • + str: Input string in x-www-urlencoded format +
    • + +
    • + decode_plus: Decode "+" signs to spaces if true (optional) +
    • + +
    + + + + + + +

    Return value:

    +The decoded string + + + +

    See also:

    + + +
    + + + + +
    urlencode (str)
    +
    + + +URL-encode given string. + + + +

    Parameters

    +
      + +
    • + str: String to encode +
    • + +
    + + + + + + +

    Return value:

    +String containing the encoded data + + + +

    See also:

    + + +
    + + + +
    vspairs (t)
    Return a key, value iterator for the given table. -The table pairs are sorted by value. +The table pairs are sorted by value. +

    Parameters

    diff --git a/documentation/api/modules/nixio.CHANGELOG.html b/documentation/api/modules/nixio.CHANGELOG.html index 48bedc80a..7d98747c2 100644 --- a/documentation/api/modules/nixio.CHANGELOG.html +++ b/documentation/api/modules/nixio.CHANGELOG.html @@ -43,19 +43,15 @@
  • - luci.http.protocol + luci.http.conditionals
  • - luci.http.protocol.conditionals + luci.http.date
  • - luci.http.protocol.date -
  • - -
  • - luci.http.protocol.mime + luci.http.mime
  • diff --git a/documentation/api/modules/nixio.CryptoHash.html b/documentation/api/modules/nixio.CryptoHash.html index 6158a77b6..7d2f48b1e 100644 --- a/documentation/api/modules/nixio.CryptoHash.html +++ b/documentation/api/modules/nixio.CryptoHash.html @@ -43,19 +43,15 @@
  • - luci.http.protocol + luci.http.conditionals
  • - luci.http.protocol.conditionals + luci.http.date
  • - luci.http.protocol.date -
  • - -
  • - luci.http.protocol.mime + luci.http.mime
  • diff --git a/documentation/api/modules/nixio.File.html b/documentation/api/modules/nixio.File.html index d9e67ea5b..7a7500a77 100644 --- a/documentation/api/modules/nixio.File.html +++ b/documentation/api/modules/nixio.File.html @@ -43,19 +43,15 @@
  • - luci.http.protocol + luci.http.conditionals
  • - luci.http.protocol.conditionals + luci.http.date
  • - luci.http.protocol.date -
  • - -
  • - luci.http.protocol.mime + luci.http.mime
  • diff --git a/documentation/api/modules/nixio.README.html b/documentation/api/modules/nixio.README.html index 99e036b82..22dd79349 100644 --- a/documentation/api/modules/nixio.README.html +++ b/documentation/api/modules/nixio.README.html @@ -43,19 +43,15 @@
  • - luci.http.protocol + luci.http.conditionals
  • - luci.http.protocol.conditionals + luci.http.date
  • - luci.http.protocol.date -
  • - -
  • - luci.http.protocol.mime + luci.http.mime
  • diff --git a/documentation/api/modules/nixio.Socket.html b/documentation/api/modules/nixio.Socket.html index 7d258fc19..185099125 100644 --- a/documentation/api/modules/nixio.Socket.html +++ b/documentation/api/modules/nixio.Socket.html @@ -43,19 +43,15 @@
  • - luci.http.protocol + luci.http.conditionals
  • - luci.http.protocol.conditionals + luci.http.date
  • - luci.http.protocol.date -
  • - -
  • - luci.http.protocol.mime + luci.http.mime
  • diff --git a/documentation/api/modules/nixio.TLSContext.html b/documentation/api/modules/nixio.TLSContext.html index a91b1eec4..c84d31895 100644 --- a/documentation/api/modules/nixio.TLSContext.html +++ b/documentation/api/modules/nixio.TLSContext.html @@ -43,19 +43,15 @@
  • - luci.http.protocol + luci.http.conditionals
  • - luci.http.protocol.conditionals + luci.http.date
  • - luci.http.protocol.date -
  • - -
  • - luci.http.protocol.mime + luci.http.mime
  • diff --git a/documentation/api/modules/nixio.TLSSocket.html b/documentation/api/modules/nixio.TLSSocket.html index 3d99a6482..5d6098a9f 100644 --- a/documentation/api/modules/nixio.TLSSocket.html +++ b/documentation/api/modules/nixio.TLSSocket.html @@ -43,19 +43,15 @@
  • - luci.http.protocol + luci.http.conditionals
  • - luci.http.protocol.conditionals + luci.http.date
  • - luci.http.protocol.date -
  • - -
  • - luci.http.protocol.mime + luci.http.mime
  • diff --git a/documentation/api/modules/nixio.UnifiedIO.html b/documentation/api/modules/nixio.UnifiedIO.html index 700485dbe..6410ffb42 100644 --- a/documentation/api/modules/nixio.UnifiedIO.html +++ b/documentation/api/modules/nixio.UnifiedIO.html @@ -43,19 +43,15 @@
  • - luci.http.protocol + luci.http.conditionals
  • - luci.http.protocol.conditionals + luci.http.date
  • - luci.http.protocol.date -
  • - -
  • - luci.http.protocol.mime + luci.http.mime
  • diff --git a/documentation/api/modules/nixio.bin.html b/documentation/api/modules/nixio.bin.html index fd8287912..48e6fcd8b 100644 --- a/documentation/api/modules/nixio.bin.html +++ b/documentation/api/modules/nixio.bin.html @@ -43,19 +43,15 @@
  • - luci.http.protocol + luci.http.conditionals
  • - luci.http.protocol.conditionals + luci.http.date
  • - luci.http.protocol.date -
  • - -
  • - luci.http.protocol.mime + luci.http.mime
  • diff --git a/documentation/api/modules/nixio.bit.html b/documentation/api/modules/nixio.bit.html index b29c29d33..419736363 100644 --- a/documentation/api/modules/nixio.bit.html +++ b/documentation/api/modules/nixio.bit.html @@ -43,19 +43,15 @@
  • - luci.http.protocol + luci.http.conditionals
  • - luci.http.protocol.conditionals + luci.http.date
  • - luci.http.protocol.date -
  • - -
  • - luci.http.protocol.mime + luci.http.mime
  • diff --git a/documentation/api/modules/nixio.crypto.html b/documentation/api/modules/nixio.crypto.html index 79a74584d..b91fe28c1 100644 --- a/documentation/api/modules/nixio.crypto.html +++ b/documentation/api/modules/nixio.crypto.html @@ -43,19 +43,15 @@
  • - luci.http.protocol + luci.http.conditionals
  • - luci.http.protocol.conditionals + luci.http.date
  • - luci.http.protocol.date -
  • - -
  • - luci.http.protocol.mime + luci.http.mime
  • diff --git a/documentation/api/modules/nixio.fs.html b/documentation/api/modules/nixio.fs.html index 476e7fd31..c9d34591c 100644 --- a/documentation/api/modules/nixio.fs.html +++ b/documentation/api/modules/nixio.fs.html @@ -43,19 +43,15 @@
  • - luci.http.protocol + luci.http.conditionals
  • - luci.http.protocol.conditionals + luci.http.date
  • - luci.http.protocol.date -
  • - -
  • - luci.http.protocol.mime + luci.http.mime
  • diff --git a/documentation/api/modules/nixio.html b/documentation/api/modules/nixio.html index 8ee0f62dc..65294a658 100644 --- a/documentation/api/modules/nixio.html +++ b/documentation/api/modules/nixio.html @@ -43,19 +43,15 @@
  • - luci.http.protocol + luci.http.conditionals
  • - luci.http.protocol.conditionals + luci.http.date
  • - luci.http.protocol.date -
  • - -
  • - luci.http.protocol.mime + luci.http.mime
  • diff --git a/libs/luci-lib-httpclient/Makefile b/libs/luci-lib-httpclient/Makefile index 1e7fd1bc8..b8bd428b2 100644 --- a/libs/luci-lib-httpclient/Makefile +++ b/libs/luci-lib-httpclient/Makefile @@ -7,7 +7,7 @@ include $(TOPDIR)/rules.mk LUCI_TITLE:=HTTP(S) client library -LUCI_DEPENDS:=+luci-base +luci-lib-nixio +LUCI_DEPENDS:=+luci-base +luci-lib-nixio +luci-lib-httpprotoutils include ../../luci.mk diff --git a/libs/luci-lib-httpclient/luasrc/httpclient.lua b/libs/luci-lib-httpclient/luasrc/httpclient.lua index c76cc542e..3e8d7277d 100644 --- a/libs/luci-lib-httpclient/luasrc/httpclient.lua +++ b/libs/luci-lib-httpclient/luasrc/httpclient.lua @@ -7,8 +7,8 @@ local nixio = require "nixio" local ltn12 = require "luci.ltn12" local util = require "luci.util" local table = require "table" -local http = require "luci.http.protocol" -local date = require "luci.http.protocol.date" +local http = require "luci.http" +local date = require "luci.http.date" local type, pairs, ipairs, tonumber = type, pairs, ipairs, tonumber local unpack = unpack diff --git a/libs/luci-lib-httpprotoutils/Makefile b/libs/luci-lib-httpprotoutils/Makefile new file mode 100644 index 000000000..851a362eb --- /dev/null +++ b/libs/luci-lib-httpprotoutils/Makefile @@ -0,0 +1,14 @@ +# +# Copyright (C) 2018 The LuCI Team +# +# This is free software, licensed under the Apache License, Version 2.0 . +# + +include $(TOPDIR)/rules.mk + +LUCI_TITLE:=HTTP protocol utility functions +LUCI_DEPENDS:=+luci-base + +include ../../luci.mk + +# call BuildPackage - OpenWrt buildroot signature diff --git a/libs/luci-lib-httpprotoutils/luasrc/http/conditionals.lua b/libs/luci-lib-httpprotoutils/luasrc/http/conditionals.lua new file mode 100644 index 000000000..86b4db29c --- /dev/null +++ b/libs/luci-lib-httpprotoutils/luasrc/http/conditionals.lua @@ -0,0 +1,110 @@ +-- Copyright 2008 Freifunk Leipzig / Jo-Philipp Wich +-- Licensed to the public under the Apache License 2.0. + +-- This class provides basic ETag handling and implements most of the +-- conditional HTTP/1.1 headers specified in RFC2616 Sct. 14.24 - 14.28 . +module("luci.http.conditionals", package.seeall) + +local date = require("luci.http.date") + + +function mk_etag( stat ) + if stat ~= nil then + return string.format( '"%x-%x-%x"', stat.ino, stat.size, stat.mtime ) + end +end + +-- Test whether the given message object contains an "If-Match" header and +-- compare it against the given stat object. +function if_match( req, stat ) + local h = req.headers + local etag = mk_etag( stat ) + + -- Check for matching resource + if type(h['If-Match']) == "string" then + for ent in h['If-Match']:gmatch("([^, ]+)") do + if ( ent == '*' or ent == etag ) and stat ~= nil then + return true + end + end + + return false, 412 + end + + return true +end + +-- Test whether the given message object contains an "If-Modified-Since" header +-- and compare it against the given stat object. +function if_modified_since( req, stat ) + local h = req.headers + + -- Compare mtimes + if type(h['If-Modified-Since']) == "string" then + local since = date.to_unix( h['If-Modified-Since'] ) + + if stat == nil or since < stat.mtime then + return true + end + + return false, 304, { + ["ETag"] = mk_etag( stat ); + ["Date"] = date.to_http( os.time() ); + ["Last-Modified"] = date.to_http( stat.mtime ) + } + end + + return true +end + +-- Test whether the given message object contains an "If-None-Match" header and +-- compare it against the given stat object. +function if_none_match( req, stat ) + local h = req.headers + local etag = mk_etag( stat ) + local method = req.env and req.env.REQUEST_METHOD or "GET" + + -- Check for matching resource + if type(h['If-None-Match']) == "string" then + for ent in h['If-None-Match']:gmatch("([^, ]+)") do + if ( ent == '*' or ent == etag ) and stat ~= nil then + if method == "GET" or method == "HEAD" then + return false, 304, { + ["ETag"] = etag; + ["Date"] = date.to_http( os.time() ); + ["Last-Modified"] = date.to_http( stat.mtime ) + } + else + return false, 412 + end + end + end + end + + return true +end + +-- The If-Range header is currently not implemented due to the lack of general +-- byte range stuff in luci.http.protocol . This function will always return +-- false, 412 to indicate a failed precondition. +function if_range( req, stat ) + -- Sorry, no subranges (yet) + return false, 412 +end + +-- Test whether the given message object contains an "If-Unmodified-Since" +-- header and compare it against the given stat object. +function if_unmodified_since( req, stat ) + local h = req.headers + + -- Compare mtimes + if type(h['If-Unmodified-Since']) == "string" then + local since = date.to_unix( h['If-Unmodified-Since'] ) + + if stat ~= nil and since <= stat.mtime then + return false, 412 + end + end + + return true +end diff --git a/libs/luci-lib-httpprotoutils/luasrc/http/conditionals.luadoc b/libs/luci-lib-httpprotoutils/luasrc/http/conditionals.luadoc new file mode 100644 index 000000000..7ce0b5ebe --- /dev/null +++ b/libs/luci-lib-httpprotoutils/luasrc/http/conditionals.luadoc @@ -0,0 +1,85 @@ +---[[ +LuCI http protocol implementation - HTTP/1.1 bits. + +This class provides basic ETag handling and implements most of the +conditional HTTP/1.1 headers specified in RFC2616 Sct. 14.24 - 14.28 . +]] +module "luci.http.conditionals" + +---[[ +Implement 14.19 / ETag. + +@class function +@name mk_etag +@param stat A file.stat structure +@return String containing the generated tag suitable for ETag headers +]] + +---[[ +14.24 / If-Match + +Test whether the given message object contains an "If-Match" header and +compare it against the given stat object. +@class function +@name if_match +@param req HTTP request message object +@param stat A file.stat object +@return Boolean indicating whether the precondition is ok +@return Alternative status code if the precondition failed +]] + +---[[ +14.25 / If-Modified-Since + +Test whether the given message object contains an "If-Modified-Since" header +and compare it against the given stat object. +@class function +@name if_modified_since +@param req HTTP request message object +@param stat A file.stat object +@return Boolean indicating whether the precondition is ok +@return Alternative status code if the precondition failed +@return Table containing extra HTTP headers if the precondition failed +]] + +---[[ +14.26 / If-None-Match + +Test whether the given message object contains an "If-None-Match" header and +compare it against the given stat object. +@class function +@name if_none_match +@param req HTTP request message object +@param stat A file.stat object +@return Boolean indicating whether the precondition is ok +@return Alternative status code if the precondition failed +@return Table containing extra HTTP headers if the precondition failed +]] + +---[[ +14.27 / If-Range + +The If-Range header is currently not implemented due to the lack of general +byte range stuff in luci.http.protocol . This function will always return +false, 412 to indicate a failed precondition. +@class function +@name if_range +@param req HTTP request message object +@param stat A file.stat object +@return Boolean indicating whether the precondition is ok +@return Alternative status code if the precondition failed +]] + +---[[ +14.28 / If-Unmodified-Since + +Test whether the given message object contains an "If-Unmodified-Since" +header and compare it against the given stat object. +@class function +@name if_unmodified_since +@param req HTTP request message object +@param stat A file.stat object +@return Boolean indicating whether the precondition is ok +@return Alternative status code if the precondition failed +]] + diff --git a/libs/luci-lib-httpprotoutils/luasrc/http/date.lua b/libs/luci-lib-httpprotoutils/luasrc/http/date.lua new file mode 100644 index 000000000..72f1bdb57 --- /dev/null +++ b/libs/luci-lib-httpprotoutils/luasrc/http/date.lua @@ -0,0 +1,87 @@ +-- Copyright 2008 Freifunk Leipzig / Jo-Philipp Wich +-- Licensed to the public under the Apache License 2.0. + +-- This class contains functions to parse, compare and format http dates. +module("luci.http.date", package.seeall) + +require("luci.sys.zoneinfo") + + +MONTHS = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", + "Sep", "Oct", "Nov", "Dec" +} + +function tz_offset(tz) + + if type(tz) == "string" then + + -- check for a numeric identifier + local s, v = tz:match("([%+%-])([0-9]+)") + if s == '+' then s = 1 else s = -1 end + if v then v = tonumber(v) end + + if s and v then + return s * 60 * ( math.floor( v / 100 ) * 60 + ( v % 100 ) ) + + -- lookup symbolic tz + elseif luci.sys.zoneinfo.OFFSET[tz:lower()] then + return luci.sys.zoneinfo.OFFSET[tz:lower()] + end + + end + + -- bad luck + return 0 +end + +function to_unix(date) + + local wd, day, mon, yr, hr, min, sec, tz = date:match( + "([A-Z][a-z][a-z]), ([0-9]+) " .. + "([A-Z][a-z][a-z]) ([0-9]+) " .. + "([0-9]+):([0-9]+):([0-9]+) " .. + "([A-Z0-9%+%-]+)" + ) + + if day and mon and yr and hr and min and sec then + -- find month + local month = 1 + for i = 1, 12 do + if MONTHS[i] == mon then + month = i + break + end + end + + -- convert to epoch time + return tz_offset(tz) + os.time( { + year = yr, + month = month, + day = day, + hour = hr, + min = min, + sec = sec + } ) + end + + return 0 +end + +function to_http(time) + return os.date( "%a, %d %b %Y %H:%M:%S GMT", time ) +end + +function compare(d1, d2) + + if d1:match("[^0-9]") then d1 = to_unix(d1) end + if d2:match("[^0-9]") then d2 = to_unix(d2) end + + if d1 == d2 then + return 0 + elseif d1 < d2 then + return -1 + else + return 1 + end +end diff --git a/libs/luci-lib-httpprotoutils/luasrc/http/date.luadoc b/libs/luci-lib-httpprotoutils/luasrc/http/date.luadoc new file mode 100644 index 000000000..6028fb483 --- /dev/null +++ b/libs/luci-lib-httpprotoutils/luasrc/http/date.luadoc @@ -0,0 +1,46 @@ +---[[ +LuCI http protocol implementation - date helper class. + +This class contains functions to parse, compare and format http dates. +]] +module "luci.http.date" + +---[[ +Return the time offset in seconds between the UTC and given time zone. + +@class function +@name tz_offset +@param tz Symbolic or numeric timezone specifier +@return Time offset to UTC in seconds +]] + +---[[ +Parse given HTTP date string and convert it to unix epoch time. + +@class function +@name to_unix +@param data String containing the date +@return Unix epoch time +]] + +---[[ +Convert the given unix epoch time to valid HTTP date string. + +@class function +@name to_http +@param time Unix epoch time +@return String containing the formatted date +]] + +---[[ +Compare two dates which can either be unix epoch times or HTTP date strings. + +@class function +@name compare +@param d1 The first date or epoch time to compare +@param d2 The first date or epoch time to compare +@return -1 - if d1 is lower then d2 +@return 0 - if both dates are equal +@return 1 - if d1 is higher then d2 +]] + diff --git a/libs/luci-lib-httpprotoutils/luasrc/http/mime.lua b/libs/luci-lib-httpprotoutils/luasrc/http/mime.lua new file mode 100644 index 000000000..0bcff8a36 --- /dev/null +++ b/libs/luci-lib-httpprotoutils/luasrc/http/mime.lua @@ -0,0 +1,78 @@ +-- Copyright 2008 Freifunk Leipzig / Jo-Philipp Wich +-- Licensed to the public under the Apache License 2.0. + +-- This class provides functions to guess mime types from file extensions and +-- vice versa. +module("luci.http.mime", package.seeall) + +require("luci.util") + +MIME_TYPES = { + ["txt"] = "text/plain"; + ["js"] = "text/javascript"; + ["css"] = "text/css"; + ["htm"] = "text/html"; + ["html"] = "text/html"; + ["patch"] = "text/x-patch"; + ["c"] = "text/x-csrc"; + ["h"] = "text/x-chdr"; + ["o"] = "text/x-object"; + ["ko"] = "text/x-object"; + + ["bmp"] = "image/bmp"; + ["gif"] = "image/gif"; + ["png"] = "image/png"; + ["jpg"] = "image/jpeg"; + ["jpeg"] = "image/jpeg"; + ["svg"] = "image/svg+xml"; + + ["zip"] = "application/zip"; + ["pdf"] = "application/pdf"; + ["xml"] = "application/xml"; + ["xsl"] = "application/xml"; + ["doc"] = "application/msword"; + ["ppt"] = "application/vnd.ms-powerpoint"; + ["xls"] = "application/vnd.ms-excel"; + ["odt"] = "application/vnd.oasis.opendocument.text"; + ["odp"] = "application/vnd.oasis.opendocument.presentation"; + ["pl"] = "application/x-perl"; + ["sh"] = "application/x-shellscript"; + ["php"] = "application/x-php"; + ["deb"] = "application/x-deb"; + ["iso"] = "application/x-cd-image"; + ["tgz"] = "application/x-compressed-tar"; + + ["mp3"] = "audio/mpeg"; + ["ogg"] = "audio/x-vorbis+ogg"; + ["wav"] = "audio/x-wav"; + + ["mpg"] = "video/mpeg"; + ["mpeg"] = "video/mpeg"; + ["avi"] = "video/x-msvideo"; +} + +-- "application/octet-stream" if the extension is unknown. +function to_mime(filename) + if type(filename) == "string" then + local ext = filename:match("[^%.]+$") + + if ext and MIME_TYPES[ext:lower()] then + return MIME_TYPES[ext:lower()] + end + end + + return "application/octet-stream" +end + +-- given mime-type is unknown. +function to_ext(mimetype) + if type(mimetype) == "string" then + for ext, type in luci.util.kspairs( MIME_TYPES ) do + if type == mimetype then + return ext + end + end + end + + return nil +end diff --git a/libs/luci-lib-httpprotoutils/luasrc/http/mime.luadoc b/libs/luci-lib-httpprotoutils/luasrc/http/mime.luadoc new file mode 100644 index 000000000..7751e2baf --- /dev/null +++ b/libs/luci-lib-httpprotoutils/luasrc/http/mime.luadoc @@ -0,0 +1,34 @@ +---[[ +LuCI http protocol implementation - mime helper class. + +This class provides functions to guess mime types from file extensions and +vice versa. +]] +module "luci.http.mime" + +---[[ +MIME mapping table containg extension - mimetype relations. + +@class table +]] + +---[[ +Extract extension from a filename and return corresponding mime-type or + +"application/octet-stream" if the extension is unknown. +@class function +@name to_mime +@param filename The filename for which the mime type is guessed +@return String containign the determined mime type +]] + +---[[ +Return corresponding extension for a given mime type or nil if the + +given mime-type is unknown. +@class function +@name to_ext +@param mimetype The mimetype to retrieve the extension from +@return String with the extension or nil for unknown type +]] + diff --git a/modules/luci-base/Makefile b/modules/luci-base/Makefile index d3039ef41..7f7d7e772 100644 --- a/modules/luci-base/Makefile +++ b/modules/luci-base/Makefile @@ -12,8 +12,7 @@ LUCI_TYPE:=mod LUCI_BASENAME:=base LUCI_TITLE:=LuCI core libraries -LUCI_DEPENDS:=+lua +libuci-lua +luci-lib-nixio +luci-lib-ip +rpcd +libubus-lua +luci-lib-jsonc -LUCI_EXTRA_DEPENDS:=libuci-lua (>= 2018-01-01) +LUCI_DEPENDS:=+lua +luci-lib-nixio +luci-lib-ip +rpcd +libubus-lua +luci-lib-jsonc +liblucihttp-lua PKG_SOURCE:=LuaSrcDiet-0.12.1.tar.bz2 PKG_SOURCE_URL:=https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/luasrcdiet diff --git a/modules/luci-base/htdocs/luci-static/resources/cbi.js b/modules/luci-base/htdocs/luci-static/resources/cbi.js index d40ec34bc..6c35372cd 100644 --- a/modules/luci-base/htdocs/luci-static/resources/cbi.js +++ b/modules/luci-base/htdocs/luci-static/resources/cbi.js @@ -218,12 +218,13 @@ var cbi_validators = { ((ipv4only == 1) && cbi_validators.ip4addr.apply(this)); }, - 'hostname': function() + 'hostname': function(strict) { if (this.length <= 253) - return (this.match(/^[a-zA-Z0-9]+$/) != null || + return (this.match(/^[a-zA-Z0-9_]+$/) != null || (this.match(/^[a-zA-Z0-9_][a-zA-Z0-9_\-.]*[a-zA-Z0-9]$/) && - this.match(/[^0-9.]/))); + this.match(/[^0-9.]/))) && + (!strict || !this.match(/^_/)); return false; }, diff --git a/modules/luci-base/htdocs/luci-static/resources/xhr.js b/modules/luci-base/htdocs/luci-static/resources/xhr.js index 3385f8f23..91dcf3fef 100644 --- a/modules/luci-base/htdocs/luci-static/resources/xhr.js +++ b/modules/luci-base/htdocs/luci-static/resources/xhr.js @@ -39,7 +39,7 @@ XHR = function() this._xmlHttp.abort(); } - this.get = function(url,data,callback) + this.get = function(url,data,callback,timeout) { this.reinit(); @@ -54,6 +54,9 @@ XHR = function() else url += '?' + code; + if (!isNaN(timeout)) + xhr.timeout = timeout; + xhr.open('GET', url, true); xhr.onreadystatechange = function() @@ -76,7 +79,7 @@ XHR = function() xhr.send(null); } - this.post = function(url,data,callback) + this.post = function(url,data,callback,timeout) { this.reinit(); @@ -89,6 +92,9 @@ XHR = function() callback(xhr); } + if (!isNaN(timeout)) + xhr.timeout = timeout; + xhr.open('POST', url, true); xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); xhr.send(code); @@ -168,7 +174,7 @@ XHR.get = function(url, data, callback) (new XHR()).get(url, data, callback); } -XHR.poll = function(interval, url, data, callback) +XHR.poll = function(interval, url, data, callback, post) { if (isNaN(interval) || interval < 1) interval = 5; @@ -181,22 +187,38 @@ XHR.poll = function(interval, url, data, callback) for (var i = 0, e = XHR._q[0]; i < XHR._q.length; e = XHR._q[++i]) { if (!(XHR._t % e.interval) && !e.xhr.busy()) - e.xhr.get(e.url, e.data, e.callback); + e.xhr[post ? 'post' : 'get'](e.url, e.data, e.callback, e.interval * 1000 - 5); } XHR._t++; }; } - XHR._q.push({ + var e = { interval: interval, callback: callback, url: url, data: data, xhr: new XHR() - }); + }; + XHR._q.push(e); XHR.run(); + + return e; +} + +XHR.stop = function(e) +{ + for (var i = 0; XHR._q && XHR._q[i]; i++) { + if (XHR._q[i] === e) { + e.xhr.cancel(); + XHR._q.splice(i, 1); + return true; + } + } + + return false; } XHR.halt = function() diff --git a/modules/luci-base/luasrc/cbi/datatypes.lua b/modules/luci-base/luasrc/cbi/datatypes.lua index 55cdf8a74..99113e0b7 100644 --- a/modules/luci-base/luasrc/cbi/datatypes.lua +++ b/modules/luci-base/luasrc/cbi/datatypes.lua @@ -199,13 +199,13 @@ function macaddr(val) return ip.checkmac(val) and true or false end -function hostname(val) +function hostname(val, strict) if val and (#val < 254) and ( val:match("^[a-zA-Z_]+$") or (val:match("^[a-zA-Z0-9_][a-zA-Z0-9_%-%.]*[a-zA-Z0-9]$") and val:match("[^0-9%.]")) ) then - return true + return (not strict or not val:match("^_")) end return false end diff --git a/modules/luci-base/luasrc/dispatcher.lua b/modules/luci-base/luasrc/dispatcher.lua index 16b32548e..1984fc4ad 100644 --- a/modules/luci-base/luasrc/dispatcher.lua +++ b/modules/luci-base/luasrc/dispatcher.lua @@ -75,11 +75,16 @@ function error404(message) http.status(404, "Not Found") message = message or "Not Found" - require("luci.template") - if not util.copcall(luci.template.render, "error404") then + local function render() + local template = require "luci.template" + template.render("error404") + end + + if not util.copcall(render) then http.prepare_content("text/plain") http.write(message) end + return false end @@ -113,7 +118,8 @@ function httpdispatch(request, prefix) end end - for node in pathinfo:gmatch("[^/]+") do + local node + for node in pathinfo:gmatch("[^/%z]+") do r[#r+1] = node end @@ -136,8 +142,7 @@ local function require_post_security(target) if (type(required_val) == "string" and request_val ~= required_val) or - (required_val == true and - (request_val == nil or request_val == "")) + (required_val == true and request_val == nil) then return false end @@ -346,15 +351,23 @@ function dispatch(request) ifattr = function(...) return _ifattr(...) end; attr = function(...) return _ifattr(true, ...) end; url = build_url; - }, {__index=function(table, key) + }, {__index=function(tbl, key) if key == "controller" then return build_url() elseif key == "REQUEST_URI" then return build_url(unpack(ctx.requestpath)) + elseif key == "FULL_REQUEST_URI" then + local url = { http.getenv("SCRIPT_NAME"), http.getenv("PATH_INFO") } + local query = http.getenv("QUERY_STRING") + if query and #query > 0 then + url[#url+1] = "?" + url[#url+1] = query + end + return table.concat(url, "") elseif key == "token" then return ctx.authtoken else - return rawget(table, key) or _G[key] + return rawget(tbl, key) or _G[key] end end}) end @@ -429,6 +442,13 @@ function dispatch(request) ctx.authuser = sdat.username end + if track.cors and http.getenv("REQUEST_METHOD") == "OPTIONS" then + luci.http.status(200, "OK") + luci.http.header("Access-Control-Allow-Origin", http.getenv("HTTP_ORIGIN") or "*") + luci.http.header("Access-Control-Allow-Methods", "GET, POST, OPTIONS") + return + end + if c and require_post_security(c.target) then if not test_post_security(c) then return @@ -650,6 +670,23 @@ function node(...) return c end +function lookup(...) + local i, path = nil, {} + for i = 1, select('#', ...) do + local name, arg = nil, tostring(select(i, ...)) + for name in arg:gmatch("[^/]+") do + path[#path+1] = name + end + end + + for i = #path, 1, -1 do + local node = context.treecache[table.concat(path, ".", 1, i)] + if node and (i == #path or node.leaf) then + return node, build_url(unpack(path)) + end + end +end + function _create_node(path) if #path == 0 then return context.tree @@ -791,7 +828,16 @@ local function _cbi(self, ...) local state = nil + local i, res for i, res in ipairs(maps) do + if util.instanceof(res, cbi.SimpleForm) then + io.stderr:write("Model %s returns SimpleForm but is dispatched via cbi(),\n" + % self.model) + + io.stderr:write("please change %s to use the form() action instead.\n" + % table.concat(context.request, "/")) + end + res.flow = config local cstate = res:parse() if cstate and (not state or cstate < state) then @@ -884,7 +930,7 @@ end function cbi(model, config) return { type = "cbi", - post = { ["cbi.submit"] = "1" }, + post = { ["cbi.submit"] = true }, config = config, model = model, target = _cbi @@ -912,6 +958,7 @@ local function _form(self, ...) local maps = luci.cbi.load(self.model, ...) local state = nil + local i, res for i, res in ipairs(maps) do local cstate = res:parse() if cstate and (not state or cstate < state) then @@ -930,7 +977,7 @@ end function form(model) return { type = "cbi", - post = { ["cbi.submit"] = "1" }, + post = { ["cbi.submit"] = true }, model = model, target = _form } diff --git a/modules/luci-base/luasrc/dispatcher.luadoc b/modules/luci-base/luasrc/dispatcher.luadoc index 743463c74..ddf534b3e 100644 --- a/modules/luci-base/luasrc/dispatcher.luadoc +++ b/modules/luci-base/luasrc/dispatcher.luadoc @@ -116,8 +116,8 @@ Create a new dispatching node and define common parameters. ---[[ Fetch or create a dispatching node without setting the target module or - enabling the node. + @class function @name get @param ... Virtual path @@ -134,6 +134,15 @@ Fetch or create a new dispatching node. ]] ---[[ +Lookup node in dispatching tree. + +@class function +@name lookup +@param ... Virtual path +@return Node object, canonical url or nil if the path was not found. +]] + +---[[ Alias the first (lowest order) page automatically diff --git a/modules/luci-base/luasrc/http.lua b/modules/luci-base/luasrc/http.lua index 9cc985786..16fb04c54 100644 --- a/modules/luci-base/luasrc/http.lua +++ b/modules/luci-base/luasrc/http.lua @@ -1,18 +1,21 @@ -- Copyright 2008 Steven Barth +-- Copyright 2010-2018 Jo-Philipp Wich -- Licensed to the public under the Apache License 2.0. -local ltn12 = require "luci.ltn12" -local protocol = require "luci.http.protocol" local util = require "luci.util" -local string = require "string" local coroutine = require "coroutine" local table = require "table" +local lhttp = require "lucihttp" +local nixio = require "nixio" +local ltn12 = require "luci.ltn12" -local ipairs, pairs, next, type, tostring, error = - ipairs, pairs, next, type, tostring, error +local table, ipairs, pairs, type, tostring, tonumber, error = + table, ipairs, pairs, type, tostring, tonumber, error module "luci.http" +HTTP_MAX_CONTENT = 1024*8 -- 8 kB maximum content size + context = util.threadlocal() Request = util.class() @@ -28,7 +31,7 @@ function Request.__init__(self, env, sourcein, sinkerr) self.message = { env = env, headers = {}, - params = protocol.urldecode_params(env.QUERY_STRING or ""), + params = urldecode_params(env.QUERY_STRING or ""), } self.parsed_input = false @@ -73,10 +76,7 @@ function Request.content(self) end function Request.getcookie(self, name) - local c = string.gsub(";" .. (self:getenv("HTTP_COOKIE") or "") .. ";", "%s*;%s*", ";") - local p = ";" .. name .. "=(.-);" - local i, j, value = c:find(p) - return value and urldecode(value) + return lhttp.header_attribute("cookie; " .. (self:getenv("HTTP_COOKIE") or ""), name) end function Request.getenv(self, name) @@ -90,40 +90,34 @@ end function Request.setfilehandler(self, callback) self.filehandler = callback - -- If input has already been parsed then any files are either in temporary files - -- or are in self.message.params[key] - if self.parsed_input then - for param, value in pairs(self.message.params) do - repeat - -- We're only interested in files - if (not value["file"]) then break end - -- If we were able to write to temporary file - if (value["fd"]) then - fd = value["fd"] - local eof = false - repeat - filedata = fd:read(1024) - if (filedata:len() < 1024) then - eof = true - end - callback({ name=value["name"], file=value["file"] }, filedata, eof) - until (eof) - fd:close() - value["fd"] = nil - -- We had to read into memory - else - -- There should only be one numbered value in table - the data - for k, v in ipairs(value) do - callback({ name=value["name"], file=value["file"] }, v, true) + if not self.parsed_input then + return + end + + -- If input has already been parsed then uploads are stored as unlinked + -- temporary files pointed to by open file handles in the parameter + -- value table. Loop all params, and invoke the file callback for any + -- param with an open file handle. + local name, value + for name, value in pairs(self.message.params) do + if type(value) == "table" then + while value.fd do + local data = value.fd:read(1024) + local eof = (not data or data == "") + + callback(value, data, eof) + + if eof then + value.fd:close() + value.fd = nil end end - until true end end end function Request._parse_input(self) - protocol.parse_message_body( + parse_message_body( self.input, self.message, self.filehandler @@ -254,23 +248,307 @@ function redirect(url) end function build_querystring(q) - local s = { "?" } + local s, n, k, v = {}, 1, nil, nil for k, v in pairs(q) do - if #s > 1 then s[#s+1] = "&" end - - s[#s+1] = urldecode(k) - s[#s+1] = "=" - s[#s+1] = urldecode(v) + s[n+0] = (n == 1) and "?" or "&" + s[n+1] = util.urlencode(k) + s[n+2] = "=" + s[n+3] = util.urlencode(v) + n = n + 4 end return table.concat(s, "") end -urldecode = protocol.urldecode +urldecode = util.urldecode -urlencode = protocol.urlencode +urlencode = util.urlencode function write_json(x) util.serialize_json(x, write) end + +-- from given url or string. Returns a table with urldecoded values. +-- Simple parameters are stored as string values associated with the parameter +-- name within the table. Parameters with multiple values are stored as array +-- containing the corresponding values. +function urldecode_params(url, tbl) + local parser, name + local params = tbl or { } + + parser = lhttp.urlencoded_parser(function (what, buffer, length) + if what == parser.TUPLE then + name, value = nil, nil + elseif what == parser.NAME then + name = lhttp.urldecode(buffer) + elseif what == parser.VALUE and name then + params[name] = lhttp.urldecode(buffer) or "" + end + + return true + end) + + if parser then + parser:parse((url or ""):match("[^?]*$")) + parser:parse(nil) + end + + return params +end + +-- separated by "&". Tables are encoded as parameters with multiple values by +-- repeating the parameter name with each value. +function urlencode_params(tbl) + local k, v + local n, enc = 1, {} + for k, v in pairs(tbl) do + if type(v) == "table" then + local i, v2 + for i, v2 in ipairs(v) do + if enc[1] then + enc[n] = "&" + n = n + 1 + end + + enc[n+0] = lhttp.urlencode(k) + enc[n+1] = "=" + enc[n+2] = lhttp.urlencode(v2) + n = n + 3 + end + else + if enc[1] then + enc[n] = "&" + n = n + 1 + end + + enc[n+0] = lhttp.urlencode(k) + enc[n+1] = "=" + enc[n+2] = lhttp.urlencode(v) + n = n + 3 + end + end + + return table.concat(enc, "") +end + +-- Content-Type. Stores all extracted data associated with its parameter name +-- in the params table within the given message object. Multiple parameter +-- values are stored as tables, ordinary ones as strings. +-- If an optional file callback function is given then it is feeded with the +-- file contents chunk by chunk and only the extracted file name is stored +-- within the params table. The callback function will be called subsequently +-- with three arguments: +-- o Table containing decoded (name, file) and raw (headers) mime header data +-- o String value containing a chunk of the file data +-- o Boolean which indicates wheather the current chunk is the last one (eof) +function mimedecode_message_body(src, msg, file_cb) + local parser, header, field + local len, maxlen = 0, tonumber(msg.env.CONTENT_LENGTH or nil) + + parser, err = lhttp.multipart_parser(msg.env.CONTENT_TYPE, function (what, buffer, length) + if what == parser.PART_INIT then + field = { } + + elseif what == parser.HEADER_NAME then + header = buffer:lower() + + elseif what == parser.HEADER_VALUE and header then + if header:lower() == "content-disposition" and + lhttp.header_attribute(buffer, nil) == "form-data" + then + field.name = lhttp.header_attribute(buffer, "name") + field.file = lhttp.header_attribute(buffer, "filename") + field[1] = field.file + end + + if field.headers then + field.headers[header] = buffer + else + field.headers = { [header] = buffer } + end + + elseif what == parser.PART_BEGIN then + return not field.file + + elseif what == parser.PART_DATA and field.name and length > 0 then + if field.file then + if file_cb then + file_cb(field, buffer, false) + msg.params[field.name] = msg.params[field.name] or field + else + if not field.fd then + field.fd = nixio.mkstemp(field.name) + end + + if field.fd then + field.fd:write(buffer) + msg.params[field.name] = msg.params[field.name] or field + end + end + else + field.value = buffer + end + + elseif what == parser.PART_END and field.name then + if field.file and msg.params[field.name] then + if file_cb then + file_cb(field, "", true) + elseif field.fd then + field.fd:seek(0, "set") + end + else + local val = msg.params[field.name] + + if type(val) == "table" then + val[#val+1] = field.value or "" + elseif val ~= nil then + msg.params[field.name] = { val, field.value or "" } + else + msg.params[field.name] = field.value or "" + end + end + + field = nil + + elseif what == parser.ERROR then + err = buffer + end + + return true + end) + + return ltn12.pump.all(src, function (chunk) + len = len + (chunk and #chunk or 0) + + if maxlen and len > maxlen + 2 then + return nil, "Message body size exceeds Content-Length" + end + + if not parser or not parser:parse(chunk) then + return nil, err + end + + return true + end) +end + +-- Content-Type. Stores all extracted data associated with its parameter name +-- in the params table within the given message object. Multiple parameter +-- values are stored as tables, ordinary ones as strings. +function urldecode_message_body(src, msg) + local err, name, value, parser + local len, maxlen = 0, tonumber(msg.env.CONTENT_LENGTH or nil) + + parser = lhttp.urlencoded_parser(function (what, buffer, length) + if what == parser.TUPLE then + name, value = nil, nil + elseif what == parser.NAME then + name = lhttp.urldecode(buffer, lhttp.DECODE_PLUS) + elseif what == parser.VALUE and name then + local val = msg.params[name] + + if type(val) == "table" then + val[#val+1] = lhttp.urldecode(buffer, lhttp.DECODE_PLUS) or "" + elseif val ~= nil then + msg.params[name] = { val, lhttp.urldecode(buffer, lhttp.DECODE_PLUS) or "" } + else + msg.params[name] = lhttp.urldecode(buffer, lhttp.DECODE_PLUS) or "" + end + elseif what == parser.ERROR then + err = buffer + end + + return true + end) + + return ltn12.pump.all(src, function (chunk) + len = len + (chunk and #chunk or 0) + + if maxlen and len > maxlen + 2 then + return nil, "Message body size exceeds Content-Length" + elseif len > HTTP_MAX_CONTENT then + return nil, "Message body size exceeds maximum allowed length" + end + + if not parser or not parser:parse(chunk) then + return nil, err + end + + return true + end) +end + +-- This function will examine the Content-Type within the given message object +-- to select the appropriate content decoder. +-- Currently the application/x-www-urlencoded and application/form-data +-- mime types are supported. If the encountered content encoding can't be +-- handled then the whole message body will be stored unaltered as "content" +-- property within the given message object. +function parse_message_body(src, msg, filecb) + if msg.env.CONTENT_LENGTH or msg.env.REQUEST_METHOD == "POST" then + local ctype = lhttp.header_attribute(msg.env.CONTENT_TYPE, nil) + + -- Is it multipart/mime ? + if ctype == "multipart/form-data" then + return mimedecode_message_body(src, msg, filecb) + + -- Is it application/x-www-form-urlencoded ? + elseif ctype == "application/x-www-form-urlencoded" then + return urldecode_message_body(src, msg) + + end + + -- Unhandled encoding + -- If a file callback is given then feed it chunk by chunk, else + -- store whole buffer in message.content + local sink + + -- If we have a file callback then feed it + if type(filecb) == "function" then + local meta = { + name = "raw", + encoding = msg.env.CONTENT_TYPE + } + sink = function( chunk ) + if chunk then + return filecb(meta, chunk, false) + else + return filecb(meta, nil, true) + end + end + -- ... else append to .content + else + msg.content = "" + msg.content_length = 0 + + sink = function( chunk ) + if chunk then + if ( msg.content_length + #chunk ) <= HTTP_MAX_CONTENT then + msg.content = msg.content .. chunk + msg.content_length = msg.content_length + #chunk + return true + else + return nil, "POST data exceeds maximum allowed length" + end + end + return true + end + end + + -- Pump data... + while true do + local ok, err = ltn12.pump.step( src, sink ) + + if not ok and err then + return nil, err + elseif not ok then -- eof + return true + end + end + + return true + end + + return false +end diff --git a/modules/luci-base/luasrc/http.luadoc b/modules/luci-base/luasrc/http.luadoc index 8a325db21..f8121230b 100644 --- a/modules/luci-base/luasrc/http.luadoc +++ b/modules/luci-base/luasrc/http.luadoc @@ -6,25 +6,24 @@ module "luci.http" ---[[ Close the HTTP-Connection. - -@class function -@name close +@class function +@name close ]] ---[[ Return the request content if the request was of unknown type. -@class function -@name content -@return HTTP request body -@return HTTP request body length +@class function +@name content +@return HTTP request body +@return HTTP request body length ]] ---[[ Get a certain HTTP input value or a table of all input values. -@class function -@name formvalue +@class function +@name formvalue @param name Name of the GET or POST variable to fetch @param noparse Don't parse POST data before getting the value @return HTTP input value or table of all input value @@ -33,8 +32,8 @@ Get a certain HTTP input value or a table of all input values. ---[[ Get a table of all HTTP input values with a certain prefix. -@class function -@name formvaluetable +@class function +@name formvaluetable @param prefix Prefix @return Table of all HTTP input values with given prefix ]] @@ -42,18 +41,18 @@ Get a table of all HTTP input values with a certain prefix. ---[[ Get the value of a certain HTTP-Cookie. -@class function -@name getcookie +@class function +@name getcookie @param name Cookie Name @return String containing cookie data ]] ---[[ Get the value of a certain HTTP environment variable - or the environment table itself. -@class function -@name getenv + +@class function +@name getenv @param name Environment variable @return HTTP environment value or environment table ]] @@ -61,41 +60,41 @@ or the environment table itself. ---[[ Set a handler function for incoming user file uploads. -@class function -@name setfilehandler +@class function +@name setfilehandler @param callback Handler function ]] ---[[ Send a HTTP-Header. -@class function -@name header -@param key Header key -@param value Header value +@class function +@name header +@param key Header key +@param value Header value ]] ---[[ Set the mime type of following content data. -@class function -@name prepare_content -@param mime Mimetype of following content +@class function +@name prepare_content +@param mime Mimetype of following content ]] ---[[ Get the RAW HTTP input source -@class function -@name source -@return HTTP LTN12 source +@class function +@name source +@return HTTP LTN12 source ]] ---[[ Set the HTTP status code and status message. -@class function -@name status +@class function +@name status @param code Status code @param message Status message ]] @@ -105,8 +104,9 @@ Send a chunk of content data to the client. This function is as a valid LTN12 sink. If the content chunk is nil this function will automatically invoke close. -@class function -@name write + +@class function +@name write @param content Content chunk @param src_err Error object from source (optional) @see close @@ -115,51 +115,146 @@ If the content chunk is nil this function will automatically invoke close. ---[[ Splice data from a filedescriptor to the client. -@class function -@name splice -@param fp File descriptor -@param size Bytes to splice (optional) +@class function +@name splice +@param fp File descriptor +@param size Bytes to splice (optional) ]] ---[[ Redirects the client to a new URL and closes the connection. -@class function -@name redirect -@param url Target URL +@class function +@name redirect +@param url Target URL ]] ---[[ Create a querystring out of a table of key - value pairs. -@class function -@name build_querystring -@param table Query string source table +@class function +@name build_querystring +@param table Query string source table @return Encoded HTTP query string ]] ---[[ Return the URL-decoded equivalent of a string. +@class function +@name urldecode @param str URL-encoded string @param no_plus Don't decode + to " " @return URL-decoded string -@see urlencode +@see urlencode ]] ---[[ Return the URL-encoded equivalent of a string. +@class function +@name urlencode @param str Source string @return URL-encoded string -@see urldecode +@see urldecode ]] ---[[ Send the given data as JSON encoded string. -@class function -@name write_json +@class function +@name write_json @param data Data to send ]] +---[[ +Extract and split urlencoded data pairs, separated bei either "&" or ";" +from given url or string. Returns a table with urldecoded values. + +Simple parameters are stored as string values associated with the parameter +name within the table. Parameters with multiple values are stored as array +containing the corresponding values. + +@class function +@name urldecode_params +@param url The url or string which contains x-www-urlencoded form data +@param tbl Use the given table for storing values (optional) +@return Table containing the urldecoded parameters +@see urlencode_params +]] + +---[[ +Encode each key-value-pair in given table to x-www-urlencoded format, +separated by "&". + +Tables are encoded as parameters with multiple values by repeating the +parameter name with each value. + +@class function +@name urlencode_params +@param tbl Table with the values +@return String containing encoded values +@see urldecode_params +]] + +---[[ +Decode a mime encoded http message body with multipart/form-data Content-Type. + +Stores all extracted data associated with its parameter name +in the params table within the given message object. Multiple parameter +values are stored as tables, ordinary ones as strings. + +If an optional file callback function is given then it is feeded with the +file contents chunk by chunk and only the extracted file name is stored +within the params table. The callback function will be called subsequently +with three arguments: + o Table containing decoded (name, file) and raw (headers) mime header data + o String value containing a chunk of the file data + o Boolean which indicates wheather the current chunk is the last one (eof) + +@class function +@name mimedecode_message_body +@param src Ltn12 source function +@param msg HTTP message object +@param filecb File callback function (optional) +@return Value indicating successful operation (not nil means "ok") +@return String containing the error if unsuccessful +@see parse_message_header +]] + +---[[ +Decode an urlencoded http message body with application/x-www-urlencoded +Content-Type. + +Stores all extracted data associated with its parameter name in the params +table within the given message object. Multiple parameter values are stored +as tables, ordinary ones as strings. + +@class function +@name urldecode_message_body +@param src Ltn12 source function +@param msg HTTP message object +@return Value indicating successful operation (not nil means "ok") +@return String containing the error if unsuccessful +@see parse_message_header +]] + +---[[ +Try to extract and decode a http message body from the given ltn12 source. +This function will examine the Content-Type within the given message object +to select the appropriate content decoder. + +Currently the application/x-www-urlencoded and application/form-data +mime types are supported. If the encountered content encoding can't be +handled then the whole message body will be stored unaltered as "content" +property within the given message object. + +@class function +@name parse_message_body +@param src Ltn12 source function +@param msg HTTP message object +@param filecb File data callback (optional, see mimedecode_message_body()) +@return Value indicating successful operation (not nil means "ok") +@return String containing the error if unsuccessful +@see parse_message_header +]] diff --git a/modules/luci-base/luasrc/http/protocol.lua b/modules/luci-base/luasrc/http/protocol.lua deleted file mode 100644 index 0a8b2fbab..000000000 --- a/modules/luci-base/luasrc/http/protocol.lua +++ /dev/null @@ -1,649 +0,0 @@ --- Copyright 2008 Freifunk Leipzig / Jo-Philipp Wich --- Licensed to the public under the Apache License 2.0. - --- This class contains several functions useful for http message- and content --- decoding and to retrive form data from raw http messages. -module("luci.http.protocol", package.seeall) - -local ltn12 = require("luci.ltn12") - -HTTP_MAX_CONTENT = 1024*8 -- 8 kB maximum content size - --- the "+" sign to " " - and return the decoded string. -function urldecode( str, no_plus ) - - local function __chrdec( hex ) - return string.char( tonumber( hex, 16 ) ) - end - - if type(str) == "string" then - if not no_plus then - str = str:gsub( "+", " " ) - end - - str = str:gsub( "%%([a-fA-F0-9][a-fA-F0-9])", __chrdec ) - end - - return str -end - --- from given url or string. Returns a table with urldecoded values. --- Simple parameters are stored as string values associated with the parameter --- name within the table. Parameters with multiple values are stored as array --- containing the corresponding values. -function urldecode_params( url, tbl ) - - local params = tbl or { } - - if url:find("?") then - url = url:gsub( "^.+%?([^?]+)", "%1" ) - end - - for pair in url:gmatch( "[^&;]+" ) do - - -- find key and value - local key = urldecode( pair:match("^([^=]+)") ) - local val = urldecode( pair:match("^[^=]+=(.+)$") ) - - -- store - if type(key) == "string" and key:len() > 0 then - if type(val) ~= "string" then val = "" end - - if not params[key] then - params[key] = val - elseif type(params[key]) ~= "table" then - params[key] = { params[key], val } - else - table.insert( params[key], val ) - end - end - end - - return params -end - -function urlencode( str ) - - local function __chrenc( chr ) - return string.format( - "%%%02x", string.byte( chr ) - ) - end - - if type(str) == "string" then - str = str:gsub( - "([^a-zA-Z0-9$_%-%.%~])", - __chrenc - ) - end - - return str -end - --- separated by "&". Tables are encoded as parameters with multiple values by --- repeating the parameter name with each value. -function urlencode_params( tbl ) - local enc = "" - - for k, v in pairs(tbl) do - if type(v) == "table" then - for i, v2 in ipairs(v) do - enc = enc .. ( #enc > 0 and "&" or "" ) .. - urlencode(k) .. "=" .. urlencode(v2) - end - else - enc = enc .. ( #enc > 0 and "&" or "" ) .. - urlencode(k) .. "=" .. urlencode(v) - end - end - - return enc -end - --- (Internal function) --- Initialize given parameter and coerce string into table when the parameter --- already exists. -local function __initval( tbl, key ) - if tbl[key] == nil then - tbl[key] = "" - elseif type(tbl[key]) == "string" then - tbl[key] = { tbl[key], "" } - else - table.insert( tbl[key], "" ) - end -end - --- (Internal function) --- Initialize given file parameter. -local function __initfileval( tbl, key, filename, fd ) - if tbl[key] == nil then - tbl[key] = { file=filename, fd=fd, name=key, "" } - else - table.insert( tbl[key], "" ) - end -end - --- (Internal function) --- Append given data to given parameter, either by extending the string value --- or by appending it to the last string in the parameter's value table. -local function __appendval( tbl, key, chunk ) - if type(tbl[key]) == "table" then - tbl[key][#tbl[key]] = tbl[key][#tbl[key]] .. chunk - else - tbl[key] = tbl[key] .. chunk - end -end - --- (Internal function) --- Finish the value of given parameter, either by transforming the string value --- or - in the case of multi value parameters - the last element in the --- associated values table. -local function __finishval( tbl, key, handler ) - if handler then - if type(tbl[key]) == "table" then - tbl[key][#tbl[key]] = handler( tbl[key][#tbl[key]] ) - else - tbl[key] = handler( tbl[key] ) - end - end -end - - --- Table of our process states -local process_states = { } - --- Extract "magic", the first line of a http message. --- Extracts the message type ("get", "post" or "response"), the requested uri --- or the status code if the line descripes a http response. -process_states['magic'] = function( msg, chunk, err ) - - if chunk ~= nil then - -- ignore empty lines before request - if #chunk == 0 then - return true, nil - end - - -- Is it a request? - local method, uri, http_ver = chunk:match("^([A-Z]+) ([^ ]+) HTTP/([01]%.[019])$") - - -- Yup, it is - if method then - - msg.type = "request" - msg.request_method = method:lower() - msg.request_uri = uri - msg.http_version = tonumber( http_ver ) - msg.headers = { } - - -- We're done, next state is header parsing - return true, function( chunk ) - return process_states['headers']( msg, chunk ) - end - - -- Is it a response? - else - - local http_ver, code, message = chunk:match("^HTTP/([01]%.[019]) ([0-9]+) ([^\r\n]+)$") - - -- Is a response - if code then - - msg.type = "response" - msg.status_code = code - msg.status_message = message - msg.http_version = tonumber( http_ver ) - msg.headers = { } - - -- We're done, next state is header parsing - return true, function( chunk ) - return process_states['headers']( msg, chunk ) - end - end - end - end - - -- Can't handle it - return nil, "Invalid HTTP message magic" -end - - --- Extract headers from given string. -process_states['headers'] = function( msg, chunk ) - - if chunk ~= nil then - - -- Look for a valid header format - local hdr, val = chunk:match( "^([A-Za-z][A-Za-z0-9%-_]+): +(.+)$" ) - - if type(hdr) == "string" and hdr:len() > 0 and - type(val) == "string" and val:len() > 0 - then - msg.headers[hdr] = val - - -- Valid header line, proceed - return true, nil - - elseif #chunk == 0 then - -- Empty line, we won't accept data anymore - return false, nil - else - -- Junk data - return nil, "Invalid HTTP header received" - end - else - return nil, "Unexpected EOF" - end -end - - --- data line by line with the trailing \r\n stripped of. -function header_source( sock ) - return ltn12.source.simplify( function() - - local chunk, err, part = sock:receive("*l") - - -- Line too long - if chunk == nil then - if err ~= "timeout" then - return nil, part - and "Line exceeds maximum allowed length" - or "Unexpected EOF" - else - return nil, err - end - - -- Line ok - elseif chunk ~= nil then - - -- Strip trailing CR - chunk = chunk:gsub("\r$","") - - return chunk, nil - end - end ) -end - --- Content-Type. Stores all extracted data associated with its parameter name --- in the params table within the given message object. Multiple parameter --- values are stored as tables, ordinary ones as strings. --- If an optional file callback function is given then it is feeded with the --- file contents chunk by chunk and only the extracted file name is stored --- within the params table. The callback function will be called subsequently --- with three arguments: --- o Table containing decoded (name, file) and raw (headers) mime header data --- o String value containing a chunk of the file data --- o Boolean which indicates wheather the current chunk is the last one (eof) -function mimedecode_message_body( src, msg, filecb ) - - if msg and msg.env.CONTENT_TYPE then - msg.mime_boundary = msg.env.CONTENT_TYPE:match("^multipart/form%-data; boundary=(.+)$") - end - - if not msg.mime_boundary then - return nil, "Invalid Content-Type found" - end - - - local tlen = 0 - local inhdr = false - local field = nil - local store = nil - local lchunk = nil - - local function parse_headers( chunk, field ) - - local stat - repeat - chunk, stat = chunk:gsub( - "^([A-Z][A-Za-z0-9%-_]+): +([^\r\n]+)\r\n", - function(k,v) - field.headers[k] = v - return "" - end - ) - until stat == 0 - - chunk, stat = chunk:gsub("^\r\n","") - - -- End of headers - if stat > 0 then - if field.headers["Content-Disposition"] then - if field.headers["Content-Disposition"]:match("^form%-data; ") then - field.name = field.headers["Content-Disposition"]:match('name="(.-)"') - field.file = field.headers["Content-Disposition"]:match('filename="(.+)"$') - end - end - - if not field.headers["Content-Type"] then - field.headers["Content-Type"] = "text/plain" - end - - if field.name and field.file and filecb then - __initval( msg.params, field.name ) - __appendval( msg.params, field.name, field.file ) - - store = filecb - elseif field.name and field.file then - local nxf = require "nixio" - local fd = nxf.mkstemp(field.name) - __initfileval ( msg.params, field.name, field.file, fd ) - if fd then - store = function(hdr, buf, eof) - fd:write(buf) - if (eof) then - fd:seek(0, "set") - end - end - else - store = function( hdr, buf, eof ) - __appendval( msg.params, field.name, buf ) - end - end - elseif field.name then - __initval( msg.params, field.name ) - - store = function( hdr, buf, eof ) - __appendval( msg.params, field.name, buf ) - end - else - store = nil - end - - return chunk, true - end - - return chunk, false - end - - local function snk( chunk ) - - tlen = tlen + ( chunk and #chunk or 0 ) - - if msg.env.CONTENT_LENGTH and tlen > tonumber(msg.env.CONTENT_LENGTH) + 2 then - return nil, "Message body size exceeds Content-Length" - end - - if chunk and not lchunk then - lchunk = "\r\n" .. chunk - - elseif lchunk then - local data = lchunk .. ( chunk or "" ) - local spos, epos, found - - repeat - spos, epos = data:find( "\r\n--" .. msg.mime_boundary .. "\r\n", 1, true ) - - if not spos then - spos, epos = data:find( "\r\n--" .. msg.mime_boundary .. "--\r\n", 1, true ) - end - - - if spos then - local predata = data:sub( 1, spos - 1 ) - - if inhdr then - predata, eof = parse_headers( predata, field ) - - if not eof then - return nil, "Invalid MIME section header" - elseif not field.name then - return nil, "Invalid Content-Disposition header" - end - end - - if store then - store( field, predata, true ) - end - - - field = { headers = { } } - found = found or true - - data, eof = parse_headers( data:sub( epos + 1, #data ), field ) - inhdr = not eof - end - until not spos - - if found then - -- We found at least some boundary. Save - -- the unparsed remaining data for the - -- next chunk. - lchunk, data = data, nil - else - -- There was a complete chunk without a boundary. Parse it as headers or - -- append it as data, depending on our current state. - if inhdr then - lchunk, eof = parse_headers( data, field ) - inhdr = not eof - else - -- We're inside data, so append the data. Note that we only append - -- lchunk, not all of data, since there is a chance that chunk - -- contains half a boundary. Assuming that each chunk is at least the - -- boundary in size, this should prevent problems - store( field, lchunk, false ) - lchunk, chunk = chunk, nil - end - end - end - - return true - end - - return ltn12.pump.all( src, snk ) -end - --- Content-Type. Stores all extracted data associated with its parameter name --- in the params table within the given message object. Multiple parameter --- values are stored as tables, ordinary ones as strings. -function urldecode_message_body( src, msg ) - - local tlen = 0 - local lchunk = nil - - local function snk( chunk ) - - tlen = tlen + ( chunk and #chunk or 0 ) - - if msg.env.CONTENT_LENGTH and tlen > tonumber(msg.env.CONTENT_LENGTH) + 2 then - return nil, "Message body size exceeds Content-Length" - elseif tlen > HTTP_MAX_CONTENT then - return nil, "Message body size exceeds maximum allowed length" - end - - if not lchunk and chunk then - lchunk = chunk - - elseif lchunk then - local data = lchunk .. ( chunk or "&" ) - local spos, epos - - repeat - spos, epos = data:find("^.-[;&]") - - if spos then - local pair = data:sub( spos, epos - 1 ) - local key = pair:match("^(.-)=") - local val = pair:match("=([^%s]*)%s*$") - - if key and #key > 0 then - __initval( msg.params, key ) - __appendval( msg.params, key, val ) - __finishval( msg.params, key, urldecode ) - end - - data = data:sub( epos + 1, #data ) - end - until not spos - - lchunk = data - end - - return true - end - - return ltn12.pump.all( src, snk ) -end - --- version, message headers and resulting CGI environment variables from the --- given ltn12 source. -function parse_message_header( src ) - - local ok = true - local msg = { } - - local sink = ltn12.sink.simplify( - function( chunk ) - return process_states['magic']( msg, chunk ) - end - ) - - -- Pump input data... - while ok do - - -- get data - ok, err = ltn12.pump.step( src, sink ) - - -- error - if not ok and err then - return nil, err - - -- eof - elseif not ok then - - -- Process get parameters - if ( msg.request_method == "get" or msg.request_method == "post" ) and - msg.request_uri:match("?") - then - msg.params = urldecode_params( msg.request_uri ) - else - msg.params = { } - end - - -- Populate common environment variables - msg.env = { - CONTENT_LENGTH = msg.headers['Content-Length']; - CONTENT_TYPE = msg.headers['Content-Type'] or msg.headers['Content-type']; - REQUEST_METHOD = msg.request_method:upper(); - REQUEST_URI = msg.request_uri; - SCRIPT_NAME = msg.request_uri:gsub("?.+$",""); - SCRIPT_FILENAME = ""; -- XXX implement me - SERVER_PROTOCOL = "HTTP/" .. string.format("%.1f", msg.http_version); - QUERY_STRING = msg.request_uri:match("?") - and msg.request_uri:gsub("^.+?","") or "" - } - - -- Populate HTTP_* environment variables - for i, hdr in ipairs( { - 'Accept', - 'Accept-Charset', - 'Accept-Encoding', - 'Accept-Language', - 'Connection', - 'Cookie', - 'Host', - 'Referer', - 'User-Agent', - } ) do - local var = 'HTTP_' .. hdr:upper():gsub("%-","_") - local val = msg.headers[hdr] - - msg.env[var] = val - end - end - end - - return msg -end - --- This function will examine the Content-Type within the given message object --- to select the appropriate content decoder. --- Currently the application/x-www-urlencoded and application/form-data --- mime types are supported. If the encountered content encoding can't be --- handled then the whole message body will be stored unaltered as "content" --- property within the given message object. -function parse_message_body( src, msg, filecb ) - -- Is it multipart/mime ? - if msg.env.REQUEST_METHOD == "POST" and msg.env.CONTENT_TYPE and - msg.env.CONTENT_TYPE:match("^multipart/form%-data") - then - - return mimedecode_message_body( src, msg, filecb ) - - -- Is it application/x-www-form-urlencoded ? - elseif msg.env.REQUEST_METHOD == "POST" and msg.env.CONTENT_TYPE and - msg.env.CONTENT_TYPE:match("^application/x%-www%-form%-urlencoded") - then - return urldecode_message_body( src, msg, filecb ) - - - -- Unhandled encoding - -- If a file callback is given then feed it chunk by chunk, else - -- store whole buffer in message.content - else - - local sink - - -- If we have a file callback then feed it - if type(filecb) == "function" then - local meta = { - name = "raw", - encoding = msg.env.CONTENT_TYPE - } - sink = function( chunk ) - if chunk then - return filecb(meta, chunk, false) - else - return filecb(meta, nil, true) - end - end - -- ... else append to .content - else - msg.content = "" - msg.content_length = 0 - - sink = function( chunk ) - if chunk then - if ( msg.content_length + #chunk ) <= HTTP_MAX_CONTENT then - msg.content = msg.content .. chunk - msg.content_length = msg.content_length + #chunk - return true - else - return nil, "POST data exceeds maximum allowed length" - end - end - return true - end - end - - -- Pump data... - while true do - local ok, err = ltn12.pump.step( src, sink ) - - if not ok and err then - return nil, err - elseif not ok then -- eof - return true - end - end - - return true - end -end - -statusmsg = { - [200] = "OK", - [206] = "Partial Content", - [301] = "Moved Permanently", - [302] = "Found", - [304] = "Not Modified", - [400] = "Bad Request", - [403] = "Forbidden", - [404] = "Not Found", - [405] = "Method Not Allowed", - [408] = "Request Time-out", - [411] = "Length Required", - [412] = "Precondition Failed", - [416] = "Requested range not satisfiable", - [500] = "Internal Server Error", - [503] = "Server Unavailable", -} diff --git a/modules/luci-base/luasrc/http/protocol.luadoc b/modules/luci-base/luasrc/http/protocol.luadoc deleted file mode 100644 index 19a0a3419..000000000 --- a/modules/luci-base/luasrc/http/protocol.luadoc +++ /dev/null @@ -1,142 +0,0 @@ ----[[ -LuCI http protocol class. - -This class contains several functions useful for http message- and content -decoding and to retrive form data from raw http messages. -]] -module "luci.http.protocol" - ----[[ -Decode an urlencoded string - optionally without decoding - -the "+" sign to " " - and return the decoded string. -@class function -@name urldecode -@param str Input string in x-www-urlencoded format -@param no_plus Don't decode "+" signs to spaces -@return The decoded string -@see urlencode -]] - ----[[ -Extract and split urlencoded data pairs, separated bei either "&" or ";" - -from given url or string. Returns a table with urldecoded values. -Simple parameters are stored as string values associated with the parameter -name within the table. Parameters with multiple values are stored as array -containing the corresponding values. -@class function -@name urldecode_params -@param url The url or string which contains x-www-urlencoded form data -@param tbl Use the given table for storing values (optional) -@return Table containing the urldecoded parameters -@see urlencode_params -]] - ----[[ -Encode given string to x-www-urlencoded format. - -@class function -@name urlencode -@param str String to encode -@return String containing the encoded data -@see urldecode -]] - ----[[ -Encode each key-value-pair in given table to x-www-urlencoded format, - -separated by "&". Tables are encoded as parameters with multiple values by -repeating the parameter name with each value. -@class function -@name urlencode_params -@param tbl Table with the values -@return String containing encoded values -@see urldecode_params -]] - ----[[ -Creates a ltn12 source from the given socket. The source will return it's - -data line by line with the trailing \r\n stripped of. -@class function -@name header_source -@param sock Readable network socket -@return Ltn12 source function -]] - ----[[ -Decode a mime encoded http message body with multipart/form-data - -Content-Type. Stores all extracted data associated with its parameter name -in the params table within the given message object. Multiple parameter -values are stored as tables, ordinary ones as strings. -If an optional file callback function is given then it is feeded with the -file contents chunk by chunk and only the extracted file name is stored -within the params table. The callback function will be called subsequently -with three arguments: - o Table containing decoded (name, file) and raw (headers) mime header data - o String value containing a chunk of the file data - o Boolean which indicates wheather the current chunk is the last one (eof) -@class function -@name mimedecode_message_body -@param src Ltn12 source function -@param msg HTTP message object -@param filecb File callback function (optional) -@return Value indicating successful operation (not nil means "ok") -@return String containing the error if unsuccessful -@see parse_message_header -]] - ----[[ -Decode an urlencoded http message body with application/x-www-urlencoded - -Content-Type. Stores all extracted data associated with its parameter name -in the params table within the given message object. Multiple parameter -values are stored as tables, ordinary ones as strings. -@class function -@name urldecode_message_body -@param src Ltn12 source function -@param msg HTTP message object -@return Value indicating successful operation (not nil means "ok") -@return String containing the error if unsuccessful -@see parse_message_header -]] - ----[[ -Try to extract an http message header including information like protocol - -version, message headers and resulting CGI environment variables from the -given ltn12 source. -@class function -@name parse_message_header -@param src Ltn12 source function -@return HTTP message object -@see parse_message_body -]] - ----[[ -Try to extract and decode a http message body from the given ltn12 source. - -This function will examine the Content-Type within the given message object -to select the appropriate content decoder. -Currently the application/x-www-urlencoded and application/form-data -mime types are supported. If the encountered content encoding can't be -handled then the whole message body will be stored unaltered as "content" -property within the given message object. -@class function -@name parse_message_body -@param src Ltn12 source function -@param msg HTTP message object -@param filecb File data callback (optional, see mimedecode_message_body()) -@return Value indicating successful operation (not nil means "ok") -@return String containing the error if unsuccessful -@see parse_message_header -]] - ----[[ -Table containing human readable messages for several http status codes. - -@class table -]] - diff --git a/modules/luci-base/luasrc/http/protocol/conditionals.lua b/modules/luci-base/luasrc/http/protocol/conditionals.lua deleted file mode 100644 index d31a4e38a..000000000 --- a/modules/luci-base/luasrc/http/protocol/conditionals.lua +++ /dev/null @@ -1,110 +0,0 @@ --- Copyright 2008 Freifunk Leipzig / Jo-Philipp Wich --- Licensed to the public under the Apache License 2.0. - --- This class provides basic ETag handling and implements most of the --- conditional HTTP/1.1 headers specified in RFC2616 Sct. 14.24 - 14.28 . -module("luci.http.protocol.conditionals", package.seeall) - -local date = require("luci.http.protocol.date") - - -function mk_etag( stat ) - if stat ~= nil then - return string.format( '"%x-%x-%x"', stat.ino, stat.size, stat.mtime ) - end -end - --- Test whether the given message object contains an "If-Match" header and --- compare it against the given stat object. -function if_match( req, stat ) - local h = req.headers - local etag = mk_etag( stat ) - - -- Check for matching resource - if type(h['If-Match']) == "string" then - for ent in h['If-Match']:gmatch("([^, ]+)") do - if ( ent == '*' or ent == etag ) and stat ~= nil then - return true - end - end - - return false, 412 - end - - return true -end - --- Test whether the given message object contains an "If-Modified-Since" header --- and compare it against the given stat object. -function if_modified_since( req, stat ) - local h = req.headers - - -- Compare mtimes - if type(h['If-Modified-Since']) == "string" then - local since = date.to_unix( h['If-Modified-Since'] ) - - if stat == nil or since < stat.mtime then - return true - end - - return false, 304, { - ["ETag"] = mk_etag( stat ); - ["Date"] = date.to_http( os.time() ); - ["Last-Modified"] = date.to_http( stat.mtime ) - } - end - - return true -end - --- Test whether the given message object contains an "If-None-Match" header and --- compare it against the given stat object. -function if_none_match( req, stat ) - local h = req.headers - local etag = mk_etag( stat ) - local method = req.env and req.env.REQUEST_METHOD or "GET" - - -- Check for matching resource - if type(h['If-None-Match']) == "string" then - for ent in h['If-None-Match']:gmatch("([^, ]+)") do - if ( ent == '*' or ent == etag ) and stat ~= nil then - if method == "GET" or method == "HEAD" then - return false, 304, { - ["ETag"] = etag; - ["Date"] = date.to_http( os.time() ); - ["Last-Modified"] = date.to_http( stat.mtime ) - } - else - return false, 412 - end - end - end - end - - return true -end - --- The If-Range header is currently not implemented due to the lack of general --- byte range stuff in luci.http.protocol . This function will always return --- false, 412 to indicate a failed precondition. -function if_range( req, stat ) - -- Sorry, no subranges (yet) - return false, 412 -end - --- Test whether the given message object contains an "If-Unmodified-Since" --- header and compare it against the given stat object. -function if_unmodified_since( req, stat ) - local h = req.headers - - -- Compare mtimes - if type(h['If-Unmodified-Since']) == "string" then - local since = date.to_unix( h['If-Unmodified-Since'] ) - - if stat ~= nil and since <= stat.mtime then - return false, 412 - end - end - - return true -end diff --git a/modules/luci-base/luasrc/http/protocol/conditionals.luadoc b/modules/luci-base/luasrc/http/protocol/conditionals.luadoc deleted file mode 100644 index 9cfe02dd5..000000000 --- a/modules/luci-base/luasrc/http/protocol/conditionals.luadoc +++ /dev/null @@ -1,85 +0,0 @@ ----[[ -LuCI http protocol implementation - HTTP/1.1 bits. - -This class provides basic ETag handling and implements most of the -conditional HTTP/1.1 headers specified in RFC2616 Sct. 14.24 - 14.28 . -]] -module "luci.http.protocol.conditionals" - ----[[ -Implement 14.19 / ETag. - -@class function -@name mk_etag -@param stat A file.stat structure -@return String containing the generated tag suitable for ETag headers -]] - ----[[ -14.24 / If-Match - -Test whether the given message object contains an "If-Match" header and -compare it against the given stat object. -@class function -@name if_match -@param req HTTP request message object -@param stat A file.stat object -@return Boolean indicating whether the precondition is ok -@return Alternative status code if the precondition failed -]] - ----[[ -14.25 / If-Modified-Since - -Test whether the given message object contains an "If-Modified-Since" header -and compare it against the given stat object. -@class function -@name if_modified_since -@param req HTTP request message object -@param stat A file.stat object -@return Boolean indicating whether the precondition is ok -@return Alternative status code if the precondition failed -@return Table containing extra HTTP headers if the precondition failed -]] - ----[[ -14.26 / If-None-Match - -Test whether the given message object contains an "If-None-Match" header and -compare it against the given stat object. -@class function -@name if_none_match -@param req HTTP request message object -@param stat A file.stat object -@return Boolean indicating whether the precondition is ok -@return Alternative status code if the precondition failed -@return Table containing extra HTTP headers if the precondition failed -]] - ----[[ -14.27 / If-Range - -The If-Range header is currently not implemented due to the lack of general -byte range stuff in luci.http.protocol . This function will always return -false, 412 to indicate a failed precondition. -@class function -@name if_range -@param req HTTP request message object -@param stat A file.stat object -@return Boolean indicating whether the precondition is ok -@return Alternative status code if the precondition failed -]] - ----[[ -14.28 / If-Unmodified-Since - -Test whether the given message object contains an "If-Unmodified-Since" -header and compare it against the given stat object. -@class function -@name if_unmodified_since -@param req HTTP request message object -@param stat A file.stat object -@return Boolean indicating whether the precondition is ok -@return Alternative status code if the precondition failed -]] - diff --git a/modules/luci-base/luasrc/http/protocol/date.lua b/modules/luci-base/luasrc/http/protocol/date.lua deleted file mode 100644 index e440219a9..000000000 --- a/modules/luci-base/luasrc/http/protocol/date.lua +++ /dev/null @@ -1,87 +0,0 @@ --- Copyright 2008 Freifunk Leipzig / Jo-Philipp Wich --- Licensed to the public under the Apache License 2.0. - --- This class contains functions to parse, compare and format http dates. -module("luci.http.protocol.date", package.seeall) - -require("luci.sys.zoneinfo") - - -MONTHS = { - "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", - "Sep", "Oct", "Nov", "Dec" -} - -function tz_offset(tz) - - if type(tz) == "string" then - - -- check for a numeric identifier - local s, v = tz:match("([%+%-])([0-9]+)") - if s == '+' then s = 1 else s = -1 end - if v then v = tonumber(v) end - - if s and v then - return s * 60 * ( math.floor( v / 100 ) * 60 + ( v % 100 ) ) - - -- lookup symbolic tz - elseif luci.sys.zoneinfo.OFFSET[tz:lower()] then - return luci.sys.zoneinfo.OFFSET[tz:lower()] - end - - end - - -- bad luck - return 0 -end - -function to_unix(date) - - local wd, day, mon, yr, hr, min, sec, tz = date:match( - "([A-Z][a-z][a-z]), ([0-9]+) " .. - "([A-Z][a-z][a-z]) ([0-9]+) " .. - "([0-9]+):([0-9]+):([0-9]+) " .. - "([A-Z0-9%+%-]+)" - ) - - if day and mon and yr and hr and min and sec then - -- find month - local month = 1 - for i = 1, 12 do - if MONTHS[i] == mon then - month = i - break - end - end - - -- convert to epoch time - return tz_offset(tz) + os.time( { - year = yr, - month = month, - day = day, - hour = hr, - min = min, - sec = sec - } ) - end - - return 0 -end - -function to_http(time) - return os.date( "%a, %d %b %Y %H:%M:%S GMT", time ) -end - -function compare(d1, d2) - - if d1:match("[^0-9]") then d1 = to_unix(d1) end - if d2:match("[^0-9]") then d2 = to_unix(d2) end - - if d1 == d2 then - return 0 - elseif d1 < d2 then - return -1 - else - return 1 - end -end diff --git a/modules/luci-base/luasrc/http/protocol/date.luadoc b/modules/luci-base/luasrc/http/protocol/date.luadoc deleted file mode 100644 index d6f1c8d65..000000000 --- a/modules/luci-base/luasrc/http/protocol/date.luadoc +++ /dev/null @@ -1,46 +0,0 @@ ----[[ -LuCI http protocol implementation - date helper class. - -This class contains functions to parse, compare and format http dates. -]] -module "luci.http.protocol.date" - ----[[ -Return the time offset in seconds between the UTC and given time zone. - -@class function -@name tz_offset -@param tz Symbolic or numeric timezone specifier -@return Time offset to UTC in seconds -]] - ----[[ -Parse given HTTP date string and convert it to unix epoch time. - -@class function -@name to_unix -@param data String containing the date -@return Unix epoch time -]] - ----[[ -Convert the given unix epoch time to valid HTTP date string. - -@class function -@name to_http -@param time Unix epoch time -@return String containing the formatted date -]] - ----[[ -Compare two dates which can either be unix epoch times or HTTP date strings. - -@class function -@name compare -@param d1 The first date or epoch time to compare -@param d2 The first date or epoch time to compare -@return -1 - if d1 is lower then d2 -@return 0 - if both dates are equal -@return 1 - if d1 is higher then d2 -]] - diff --git a/modules/luci-base/luasrc/http/protocol/mime.lua b/modules/luci-base/luasrc/http/protocol/mime.lua deleted file mode 100644 index 2b99d8e74..000000000 --- a/modules/luci-base/luasrc/http/protocol/mime.lua +++ /dev/null @@ -1,78 +0,0 @@ --- Copyright 2008 Freifunk Leipzig / Jo-Philipp Wich --- Licensed to the public under the Apache License 2.0. - --- This class provides functions to guess mime types from file extensions and --- vice versa. -module("luci.http.protocol.mime", package.seeall) - -require("luci.util") - -MIME_TYPES = { - ["txt"] = "text/plain"; - ["js"] = "text/javascript"; - ["css"] = "text/css"; - ["htm"] = "text/html"; - ["html"] = "text/html"; - ["patch"] = "text/x-patch"; - ["c"] = "text/x-csrc"; - ["h"] = "text/x-chdr"; - ["o"] = "text/x-object"; - ["ko"] = "text/x-object"; - - ["bmp"] = "image/bmp"; - ["gif"] = "image/gif"; - ["png"] = "image/png"; - ["jpg"] = "image/jpeg"; - ["jpeg"] = "image/jpeg"; - ["svg"] = "image/svg+xml"; - - ["zip"] = "application/zip"; - ["pdf"] = "application/pdf"; - ["xml"] = "application/xml"; - ["xsl"] = "application/xml"; - ["doc"] = "application/msword"; - ["ppt"] = "application/vnd.ms-powerpoint"; - ["xls"] = "application/vnd.ms-excel"; - ["odt"] = "application/vnd.oasis.opendocument.text"; - ["odp"] = "application/vnd.oasis.opendocument.presentation"; - ["pl"] = "application/x-perl"; - ["sh"] = "application/x-shellscript"; - ["php"] = "application/x-php"; - ["deb"] = "application/x-deb"; - ["iso"] = "application/x-cd-image"; - ["tgz"] = "application/x-compressed-tar"; - - ["mp3"] = "audio/mpeg"; - ["ogg"] = "audio/x-vorbis+ogg"; - ["wav"] = "audio/x-wav"; - - ["mpg"] = "video/mpeg"; - ["mpeg"] = "video/mpeg"; - ["avi"] = "video/x-msvideo"; -} - --- "application/octet-stream" if the extension is unknown. -function to_mime(filename) - if type(filename) == "string" then - local ext = filename:match("[^%.]+$") - - if ext and MIME_TYPES[ext:lower()] then - return MIME_TYPES[ext:lower()] - end - end - - return "application/octet-stream" -end - --- given mime-type is unknown. -function to_ext(mimetype) - if type(mimetype) == "string" then - for ext, type in luci.util.kspairs( MIME_TYPES ) do - if type == mimetype then - return ext - end - end - end - - return nil -end diff --git a/modules/luci-base/luasrc/http/protocol/mime.luadoc b/modules/luci-base/luasrc/http/protocol/mime.luadoc deleted file mode 100644 index 195b5fcc8..000000000 --- a/modules/luci-base/luasrc/http/protocol/mime.luadoc +++ /dev/null @@ -1,34 +0,0 @@ ----[[ -LuCI http protocol implementation - mime helper class. - -This class provides functions to guess mime types from file extensions and -vice versa. -]] -module "luci.http.protocol.mime" - ----[[ -MIME mapping table containg extension - mimetype relations. - -@class table -]] - ----[[ -Extract extension from a filename and return corresponding mime-type or - -"application/octet-stream" if the extension is unknown. -@class function -@name to_mime -@param filename The filename for which the mime type is guessed -@return String containign the determined mime type -]] - ----[[ -Return corresponding extension for a given mime type or nil if the - -given mime-type is unknown. -@class function -@name to_ext -@param mimetype The mimetype to retrieve the extension from -@return String with the extension or nil for unknown type -]] - diff --git a/modules/luci-base/luasrc/model/ipkg.lua b/modules/luci-base/luasrc/model/ipkg.lua index e653b0346..e27ea5289 100644 --- a/modules/luci-base/luasrc/model/ipkg.lua +++ b/modules/luci-base/luasrc/model/ipkg.lua @@ -20,12 +20,14 @@ module "luci.model.ipkg" -- Internal action function local function _action(cmd, ...) - local pkg = "" + local cmdline = { ipkg, cmd } + + local k, v for k, v in pairs({...}) do - pkg = pkg .. " '" .. v:gsub("'", "") .. "'" + cmdline[#cmdline+1] = util.shellquote(v) end - local c = "%s %s %s >/tmp/opkg.stdout 2>/tmp/opkg.stderr" %{ ipkg, cmd, pkg } + local c = "%s >/tmp/opkg.stdout 2>/tmp/opkg.stderr" % table.concat(cmdline, " ") local r = os.execute(c) local e = fs.readfile("/tmp/opkg.stderr") local o = fs.readfile("/tmp/opkg.stdout") @@ -74,17 +76,17 @@ local function _parselist(rawdata) end -- Internal lookup function -local function _lookup(act, pkg) - local cmd = ipkg .. " " .. act +local function _lookup(cmd, pkg) + local cmdline = { ipkg, cmd } if pkg then - cmd = cmd .. " '" .. pkg:gsub("'", "") .. "'" + cmdline[#cmdline+1] = util.shellquote(pkg) end -- OPKG sometimes kills the whole machine because it sucks -- Therefore we have to use a sucky approach too and use -- tmpfiles instead of directly reading the output local tmpfile = os.tmpname() - os.execute(cmd .. (" >%s 2>/dev/null" % tmpfile)) + os.execute("%s >%s 2>/dev/null" %{ table.concat(cmdline, " "), tmpfile }) local data = _parselist(io.lines(tmpfile)) os.remove(tmpfile) @@ -123,9 +125,12 @@ end -- List helper local function _list(action, pat, cb) - local fd = io.popen(ipkg .. " " .. action .. - (pat and (" '%s'" % pat:gsub("'", "")) or "")) + local cmdline = { ipkg, action } + if pat then + cmdline[#cmdline+1] = util.shellquote(pat) + end + local fd = io.popen(table.concat(cmdline, " ")) if fd then local name, version, sz, desc while true do diff --git a/modules/luci-base/luasrc/model/network.lua b/modules/luci-base/luasrc/model/network.lua index 056fc67b1..dfe818bcc 100644 --- a/modules/luci-base/luasrc/model/network.lua +++ b/modules/luci-base/luasrc/model/network.lua @@ -629,7 +629,7 @@ function get_interface(self, i) if _interfaces[i] or _wifi_iface(i) then return interface(i) else - local netid = _wifi_netid_by_netname(i) + local netid = _wifi_netid_by_sid(i) return netid and interface(netid) end end diff --git a/modules/luci-base/luasrc/model/uci.lua b/modules/luci-base/luasrc/model/uci.lua index 577c6cde0..fc2a605b3 100644 --- a/modules/luci-base/luasrc/model/uci.lua +++ b/modules/luci-base/luasrc/model/uci.lua @@ -2,13 +2,12 @@ -- Licensed to the public under the Apache License 2.0. local os = require "os" -local uci = require "uci" local util = require "luci.util" local table = require "table" local setmetatable, rawget, rawset = setmetatable, rawget, rawset -local require, getmetatable = require, getmetatable +local require, getmetatable, assert = require, getmetatable, assert local error, pairs, ipairs = error, pairs, ipairs local type, tostring, tonumber, unpack = type, tostring, tonumber, unpack @@ -20,151 +19,436 @@ local type, tostring, tonumber, unpack = type, tostring, tonumber, unpack -- reloaded. module "luci.model.uci" -cursor = uci.cursor +local ERRSTR = { + "Invalid command", + "Invalid argument", + "Method not found", + "Entry not found", + "No data", + "Permission denied", + "Timeout", + "Not supported", + "Unknown error", + "Connection failed" +} + +local session_id = nil + +local function call(cmd, args) + if type(args) == "table" and session_id then + args.ubus_rpc_session = session_id + end + return util.ubus("uci", cmd, args) +end -APIVERSION = uci.APIVERSION + +function cursor() + return _M +end function cursor_state() - return cursor(nil, "/var/state") + return _M end +function substate(self) + return self +end -inst = cursor() -inst_state = cursor_state() -local Cursor = getmetatable(inst) +function get_confdir(self) + return "/etc/config" +end -function Cursor.apply(self, configlist, command) - configlist = self:_affected(configlist) - if command then - return { "/sbin/luci-reload", unpack(configlist) } - else - return os.execute("/sbin/luci-reload %s >/dev/null 2>&1" - % table.concat(configlist, " ")) - end +function get_savedir(self) + return "/tmp/.uci" end +function get_session_id(self) + return session_id +end --- returns a boolean whether to delete the current section (optional) -function Cursor.delete_all(self, config, stype, comparator) - local del = {} +function set_confdir(self, directory) + return false +end - if type(comparator) == "table" then - local tbl = comparator - comparator = function(section) - for k, v in pairs(tbl) do - if section[k] ~= v then - return false +function set_savedir(self, directory) + return false +end + +function set_session_id(self, id) + session_id = id + return true +end + + +function load(self, config) + return true +end + +function save(self, config) + return true +end + +function unload(self, config) + return true +end + + +function changes(self, config) + local rv = call("changes", { config = config }) + local res = {} + + if type(rv) == "table" and type(rv.changes) == "table" then + local package, changes + for package, changes in pairs(rv.changes) do + res[package] = {} + + local _, change + for _, change in ipairs(changes) do + local operation, section, option, value = unpack(change) + if option and value and operation ~= "add" then + res[package][section] = res[package][section] or { } + + if operation == "list-add" then + local v = res[package][section][option] + if type(v) == "table" then + v[#v+1] = value or "" + elseif v ~= nil then + res[package][section][option] = { v, value } + else + res[package][section][option] = { value } + end + else + res[package][section][option] = value or "" + end + else + res[package][section] = res[package][section] or {} + res[package][section][".type"] = option or "" end end - return true end end - local function helper (section) + return res +end + + +function revert(self, config) + local _, err = call("revert", { config = config }) + return (err == nil), ERRSTR[err] +end + +function commit(self, config) + local _, err = call("commit", { config = config }) + return (err == nil), ERRSTR[err] +end + +--[[ +function apply(self, configs, command) + local _, config + + assert(not command, "Apply command not supported anymore") - if not comparator or comparator(section) then - del[#del+1] = section[".name"] + if type(configs) == "table" then + for _, config in ipairs(configs) do + call("service", "event", { + type = "config.change", + data = { package = config } + }) end end +end +]] + + +function foreach(self, config, stype, callback) + if type(callback) == "function" then + local rv, err = call("get", { + config = config, + type = stype + }) + + if type(rv) == "table" and type(rv.values) == "table" then + local sections = { } + local res = false + local index = 1 + + local _, section + for _, section in pairs(rv.values) do + section[".index"] = section[".index"] or index + sections[index] = section + index = index + 1 + end - self:foreach(config, stype, helper) + table.sort(sections, function(a, b) + return a[".index"] < b[".index"] + end) - for i, j in ipairs(del) do - self:delete(config, j) + for _, section in ipairs(sections) do + local continue = callback(section) + res = true + if continue == false then + break + end + end + return res + else + return false, ERRSTR[err] or "No data" + end + else + return false, "Invalid argument" end end -function Cursor.section(self, config, type, name, values) - local stat = true - if name then - stat = self:set(config, name, type) +local function _get(self, operation, config, section, option) + if section == nil then + return nil + elseif type(option) == "string" and option:byte(1) ~= 46 then + local rv, err = call(operation, { + config = config, + section = section, + option = option + }) + + if type(rv) == "table" then + return rv.value or nil + elseif err then + return false, ERRSTR[err] + else + return nil + end + elseif option == nil then + local values = self:get_all(config, section) + if values then + return values[".type"], values[".name"] + else + return nil + end else - name = self:add(config, type) - stat = name and true + return false, "Invalid argument" end +end - if stat and values then - stat = self:tset(config, name, values) - end +function get(self, ...) + return _get(self, "get", ...) +end - return stat and name +function get_state(self, ...) + return _get(self, "state", ...) end -function Cursor.tset(self, config, section, values) - local stat = true - for k, v in pairs(values) do - if k:sub(1, 1) ~= "." then - stat = stat and self:set(config, section, k, v) - end +function get_all(self, config, section) + local rv, err = call("get", { + config = config, + section = section + }) + + if type(rv) == "table" and type(rv.values) == "table" then + return rv.values + elseif err then + return false, ERRSTR[err] + else + return nil end - return stat end -function Cursor.get_bool(self, ...) +function get_bool(self, ...) local val = self:get(...) - return ( val == "1" or val == "true" or val == "yes" or val == "on" ) + return (val == "1" or val == "true" or val == "yes" or val == "on") +end + +function get_first(self, config, stype, option, default) + local rv = default + + self:foreach(config, stype, function(s) + local val = not option and s[".name"] or s[option] + + if type(default) == "number" then + val = tonumber(val) + elseif type(default) == "boolean" then + val = (val == "1" or val == "true" or + val == "yes" or val == "on") + end + + if val ~= nil then + rv = val + return false + end + end) + + return rv end -function Cursor.get_list(self, config, section, option) +function get_list(self, config, section, option) if config and section and option then local val = self:get(config, section, option) - return ( type(val) == "table" and val or { val } ) + return (type(val) == "table" and val or { val }) end - return {} + return { } end -function Cursor.get_first(self, conf, stype, opt, def) - local rv = def - self:foreach(conf, stype, - function(s) - local val = not opt and s['.name'] or s[opt] +function section(self, config, stype, name, values) + local rv, err = call("add", { + config = config, + type = stype, + name = name, + values = values + }) + + if type(rv) == "table" then + return rv.section + elseif err then + return false, ERRSTR[err] + else + return nil + end +end - if type(def) == "number" then - val = tonumber(val) - elseif type(def) == "boolean" then - val = (val == "1" or val == "true" or - val == "yes" or val == "on") + +function add(self, config, stype) + return self:section(config, stype) +end + +function set(self, config, section, option, value) + if value == nil then + local sname, err = self:section(config, option, section) + return (not not sname), err + else + local _, err = call("set", { + config = config, + section = section, + values = { [option] = value } + }) + return (err == nil), ERRSTR[err] + end +end + +function set_list(self, config, section, option, value) + if section == nil or option == nil then + return false + elseif value == nil or (type(value) == "table" and #value == 0) then + return self:delete(config, section, option) + elseif type(value) == "table" then + return self:set(config, section, option, value) + else + return self:set(config, section, option, { value }) + end +end + +function tset(self, config, section, values) + local _, err = call("set", { + config = config, + section = section, + values = values + }) + return (err == nil), ERRSTR[err] +end + +function reorder(self, config, section, index) + local sections + + if type(section) == "string" and type(index) == "number" then + local pos = 0 + + sections = { } + + self:foreach(config, nil, function(s) + if pos == index then + pos = pos + 1 end - if val ~= nil then - rv = val - return false + if s[".name"] ~= section then + pos = pos + 1 + sections[pos] = s[".name"] + else + sections[index + 1] = section end end) + elseif type(section) == "table" then + sections = section + else + return false, "Invalid argument" + end - return rv + local _, err = call("order", { + config = config, + sections = sections + }) + + return (err == nil), ERRSTR[err] end -function Cursor.set_list(self, config, section, option, value) - if config and section and option then - if not value or #value == 0 then - return self:delete(config, section, option) + +function delete(self, config, section, option) + local _, err = call("delete", { + config = config, + section = section, + option = option + }) + return (err == nil), ERRSTR[err] +end + +function delete_all(self, config, stype, comparator) + local _, err + if type(comparator) == "table" then + _, err = call("delete", { + config = config, + type = stype, + match = comparator + }) + elseif type(comparator) == "function" then + local rv = call("get", { + config = config, + type = stype + }) + + if type(rv) == "table" and type(rv.values) == "table" then + local sname, section + for sname, section in pairs(rv.values) do + if comparator(section) then + _, err = call("delete", { + config = config, + section = sname + }) + end + end end - return self:set( - config, section, option, - ( type(value) == "table" and value or { value } ) - ) + elseif comparator == nil then + _, err = call("delete", { + config = config, + type = stype + }) + else + return false, "Invalid argument" end - return false + + return (err == nil), ERRSTR[err] end --- Return a list of initscripts affected by configuration changes. -function Cursor._affected(self, configlist) - configlist = type(configlist) == "table" and configlist or {configlist} - local c = cursor() - c:load("ucitrack") +function apply(self, configlist, command) + configlist = self:_affected(configlist) + if command then + return { "/sbin/luci-reload", unpack(configlist) } + else + return os.execute("/sbin/luci-reload %s >/dev/null 2>&1" + % util.shellquote(table.concat(configlist, " "))) + end +end + +-- Return a list of initscripts affected by configuration changes. +function _affected(self, configlist) + configlist = type(configlist) == "table" and configlist or { configlist } -- Resolve dependencies - local reloadlist = {} + local reloadlist = { } local function _resolve_deps(name) - local reload = {name} - local deps = {} + local reload = { name } + local deps = { } - c:foreach("ucitrack", name, + self:foreach("ucitrack", name, function(section) if section.affects then for i, aff in ipairs(section.affects) do @@ -173,7 +457,9 @@ function Cursor._affected(self, configlist) end end) + local i, dep for i, dep in ipairs(deps) do + local j, add for j, add in ipairs(_resolve_deps(dep)) do reload[#reload+1] = add end @@ -183,7 +469,9 @@ function Cursor._affected(self, configlist) end -- Collect initscripts + local j, config for j, config in ipairs(configlist) do + local i, e for i, e in ipairs(_resolve_deps(config)) do if not util.contains(reloadlist, e) then reloadlist[#reloadlist+1] = e @@ -193,44 +481,3 @@ function Cursor._affected(self, configlist) return reloadlist end - --- curser, means it the parent unloads or loads configs, the sub state will --- do so as well. -function Cursor.substate(self) - Cursor._substates = Cursor._substates or { } - Cursor._substates[self] = Cursor._substates[self] or cursor_state() - return Cursor._substates[self] -end - -local _load = Cursor.load -function Cursor.load(self, ...) - if Cursor._substates and Cursor._substates[self] then - _load(Cursor._substates[self], ...) - end - return _load(self, ...) -end - -local _unload = Cursor.unload -function Cursor.unload(self, ...) - if Cursor._substates and Cursor._substates[self] then - _unload(Cursor._substates[self], ...) - end - return _unload(self, ...) -end - - - - - - - - - - - - - - - - - diff --git a/modules/luci-base/luasrc/model/uci.luadoc b/modules/luci-base/luasrc/model/uci.luadoc index 49093c793..ef89d09b9 100644 --- a/modules/luci-base/luasrc/model/uci.luadoc +++ b/modules/luci-base/luasrc/model/uci.luadoc @@ -14,224 +14,226 @@ module "luci.model.uci" ---[[ Create a new UCI-Cursor. -@class function -@name cursor -@return UCI-Cursor +@class function +@name cursor +@return UCI-Cursor ]] ---[[ Create a new Cursor initialized to the state directory. -@class function -@name cursor_state -@return UCI cursor +@class function +@name cursor_state +@return UCI cursor ]] ---[[ Applies UCI configuration changes -@class function -@name Cursor.apply -@param configlist List of UCI configurations -@param command Don't apply only return the command +@class function +@name Cursor.apply +@param configlist List of UCI configurations +@param command Don't apply only return the command ]] ---[[ Delete all sections of a given type that match certain criteria. -@class function -@name Cursor.delete_all +@class function +@name Cursor.delete_all @param config UCI config @param type UCI section type -@param comparator Function that will be called for each section and -returns a boolean whether to delete the current section (optional) +@param comparator Function that will be called for each section and returns + a boolean whether to delete the current section (optional) ]] ---[[ Create a new section and initialize it with data. -@class function -@name Cursor.section -@param config UCI config -@param type UCI section type -@param name UCI section name (optional) -@param values Table of key - value pairs to initialize the section with -@return Name of created section +@class function +@name Cursor.section +@param config UCI config +@param type UCI section type +@param name UCI section name (optional) +@param values Table of key - value pairs to initialize the section with +@return Name of created section ]] ---[[ Updated the data of a section using data from a table. -@class function -@name Cursor.tset -@param config UCI config -@param section UCI section name (optional) -@param values Table of key - value pairs to update the section with +@class function +@name Cursor.tset +@param config UCI config +@param section UCI section name (optional) +@param values Table of key - value pairs to update the section with ]] ---[[ Get a boolean option and return it's value as true or false. -@class function -@name Cursor.get_bool -@param config UCI config -@param section UCI section name -@param option UCI option -@return Boolean +@class function +@name Cursor.get_bool +@param config UCI config +@param section UCI section name +@param option UCI option +@return Boolean ]] ---[[ Get an option or list and return values as table. -@class function -@name Cursor.get_list -@param config UCI config -@param section UCI section name -@param option UCI option -@return table. If the option was not found, you will simply get --- an empty table. +@class function +@name Cursor.get_list +@param config UCI config +@param section UCI section name +@param option UCI option +@return table. If the option was not found, you will simply get an empty + table. ]] ---[[ Get the given option from the first section with the given type. -@class function -@name Cursor.get_first -@param config UCI config -@param type UCI section type -@param option UCI option (optional) -@param default Default value (optional) -@return UCI value +@class function +@name Cursor.get_first +@param config UCI config +@param type UCI section type +@param option UCI option (optional) +@param default Default value (optional) +@return UCI value ]] ---[[ Set given values as list. Setting a list option to an empty list has the same effect as deleting the option. -@class function -@name Cursor.set_list -@param config UCI config -@param section UCI section name -@param option UCI option -@param value value or table. Raw values will become a single item table. -@return Boolean whether operation succeeded +@class function +@name Cursor.set_list +@param config UCI config +@param section UCI section name +@param option UCI option +@param value Value or table. Non-table values will be set as single + item UCI list. +@return Boolean whether operation succeeded ]] ---[[ -Create a sub-state of this cursor. The sub-state is tied to the parent +Create a sub-state of this cursor. -curser, means it the parent unloads or loads configs, the sub state will -do so as well. -@class function -@name Cursor.substate -@return UCI state cursor tied to the parent cursor +The sub-state is tied to the parent curser, means it the parent unloads or +loads configs, the sub state will do so as well. + +@class function +@name Cursor.substate +@return UCI state cursor tied to the parent cursor ]] ---[[ Add an anonymous section. -@class function -@name Cursor.add -@param config UCI config -@param type UCI section type -@return Name of created section +@class function +@name Cursor.add +@param config UCI config +@param type UCI section type +@return Name of created section ]] ---[[ Get a table of saved but uncommitted changes. -@class function -@name Cursor.changes -@param config UCI config -@return Table of changes -@see Cursor.save +@class function +@name Cursor.changes +@param config UCI config +@return Table of changes +@see Cursor.save ]] ---[[ Commit saved changes. -@class function -@name Cursor.commit -@param config UCI config -@return Boolean whether operation succeeded -@see Cursor.revert -@see Cursor.save +@class function +@name Cursor.commit +@param config UCI config +@return Boolean whether operation succeeded +@see Cursor.revert +@see Cursor.save ]] ---[[ Deletes a section or an option. -@class function -@name Cursor.delete -@param config UCI config -@param section UCI section name -@param option UCI option (optional) -@return Boolean whether operation succeeded +@class function +@name Cursor.delete +@param config UCI config +@param section UCI section name +@param option UCI option (optional) +@return Boolean whether operation succeeded ]] ---[[ Call a function for every section of a certain type. -@class function -@name Cursor.foreach -@param config UCI config -@param type UCI section type -@param callback Function to be called -@return Boolean whether operation succeeded +@class function +@name Cursor.foreach +@param config UCI config +@param type UCI section type +@param callback Function to be called +@return Boolean whether operation succeeded ]] ---[[ Get a section type or an option -@class function -@name Cursor.get -@param config UCI config -@param section UCI section name -@param option UCI option (optional) -@return UCI value +@class function +@name Cursor.get +@param config UCI config +@param section UCI section name +@param option UCI option (optional) +@return UCI value ]] ---[[ Get all sections of a config or all values of a section. -@class function -@name Cursor.get_all -@param config UCI config -@param section UCI section name (optional) -@return Table of UCI sections or table of UCI values +@class function +@name Cursor.get_all +@param config UCI config +@param section UCI section name (optional) +@return Table of UCI sections or table of UCI values ]] ---[[ Manually load a config. -@class function -@name Cursor.load -@param config UCI config -@return Boolean whether operation succeeded -@see Cursor.save -@see Cursor.unload +@class function +@name Cursor.load +@param config UCI config +@return Boolean whether operation succeeded +@see Cursor.save +@see Cursor.unload ]] ---[[ Revert saved but uncommitted changes. -@class function -@name Cursor.revert -@param config UCI config -@return Boolean whether operation succeeded -@see Cursor.commit -@see Cursor.save +@class function +@name Cursor.revert +@param config UCI config +@return Boolean whether operation succeeded +@see Cursor.commit +@see Cursor.save ]] ---[[ Saves changes made to a config to make them committable. -@class function -@name Cursor.save -@param config UCI config -@return Boolean whether operation succeeded -@see Cursor.load -@see Cursor.unload +@class function +@name Cursor.save +@param config UCI config +@return Boolean whether operation succeeded +@see Cursor.load +@see Cursor.unload ]] ---[[ @@ -243,57 +245,74 @@ then a named section of the given type is created. When invoked with four arguments `config`, `sectionname`, `optionname` and `optionvalue` then the value of the specified option is set to the given value. -@class function -@name Cursor.set -@param config UCI config -@param section UCI section name -@param option UCI option or UCI section type +@class function +@name Cursor.set +@param config UCI config +@param section UCI section name +@param option UCI option or UCI section type @param value UCI value or nothing if you want to create a section -@return Boolean whether operation succeeded +@return Boolean whether operation succeeded ]] ---[[ Get the configuration directory. -@class function -@name Cursor.get_confdir -@return Configuration directory +@class function +@name Cursor.get_confdir +@return Configuration directory ]] ---[[ Get the directory for uncomitted changes. -@class function -@name Cursor.get_savedir -@return Save directory +@class function +@name Cursor.get_savedir +@return Save directory +]] + +---[[ +Get the effective session ID. + +@class function +@name Cursor.get_session_id +@return String containing the session ID ]] ---[[ Set the configuration directory. -@class function -@name Cursor.set_confdir +@class function +@name Cursor.set_confdir @param directory UCI configuration directory -@return Boolean whether operation succeeded +@return Boolean whether operation succeeded ]] ---[[ Set the directory for uncommited changes. -@class function -@name Cursor.set_savedir +@class function +@name Cursor.set_savedir @param directory UCI changes directory -@return Boolean whether operation succeeded +@return Boolean whether operation succeeded +]] + +---[[ +Set the effective session ID. + +@class function +@name Cursor.set_session_id +@param id String containing the session ID to set +@return Boolean whether operation succeeded ]] ---[[ Discard changes made to a config. -@class function -@name Cursor.unload -@param config UCI config -@return Boolean whether operation succeeded -@see Cursor.load -@see Cursor.save +@class function +@name Cursor.unload +@param config UCI config +@return Boolean whether operation succeeded +@see Cursor.load +@see Cursor.save ]] diff --git a/modules/luci-base/luasrc/sys.lua b/modules/luci-base/luasrc/sys.lua index 12b20e4c3..823e20770 100644 --- a/modules/luci-base/luasrc/sys.lua +++ b/modules/luci-base/luasrc/sys.lua @@ -87,10 +87,10 @@ end function httpget(url, stream, target) if not target then local source = stream and io.popen or luci.util.exec - return source("wget -qO- '"..url:gsub("'", "").."'") + return source("wget -qO- %s" % luci.util.shellquote(url)) else - return os.execute("wget -qO '%s' '%s'" % - {target:gsub("'", ""), url:gsub("'", "")}) + return os.execute("wget -qO %s %s" % + {luci.util.shellquote(target), luci.util.shellquote(url)}) end end @@ -443,18 +443,11 @@ function user.checkpasswd(username, pass) end function user.setpasswd(username, password) - if password then - password = password:gsub("'", [['"'"']]) - end - - if username then - username = username:gsub("'", [['"'"']]) - end - - return os.execute( - "(echo '" .. password .. "'; sleep 1; echo '" .. password .. "') | " .. - "passwd '" .. username .. "' >/dev/null 2>&1" - ) + return os.execute("(echo %s; sleep 1; echo %s) | passwd %s >/dev/null 2>&1" %{ + luci.util.shellquote(password), + luci.util.shellquote(password), + luci.util.shellquote(username) + }) end diff --git a/modules/luci-base/luasrc/sys/zoneinfo/tzdata.lua b/modules/luci-base/luasrc/sys/zoneinfo/tzdata.lua index 6668dad83..47cb901a5 100644 --- a/modules/luci-base/luasrc/sys/zoneinfo/tzdata.lua +++ b/modules/luci-base/luasrc/sys/zoneinfo/tzdata.lua @@ -202,7 +202,7 @@ TZ = { { 'America/Winnipeg', 'CST6CDT,M3.2.0,M11.1.0' }, { 'America/Yakutat', 'AKST9AKDT,M3.2.0,M11.1.0' }, { 'America/Yellowknife', 'MST7MDT,M3.2.0,M11.1.0' }, - { 'Antarctica/Casey', '<+11>-11' }, + { 'Antarctica/Casey', '<+08>-8' }, { 'Antarctica/Davis', '<+07>-7' }, { 'Antarctica/DumontDUrville', '<+10>-10' }, { 'Antarctica/Macquarie', '<+11>-11' }, @@ -239,8 +239,8 @@ TZ = { { 'Asia/Dubai', '<+04>-4' }, { 'Asia/Dushanbe', '<+05>-5' }, { 'Asia/Famagusta', 'EET-2EEST,M3.5.0/3,M10.5.0/4' }, - { 'Asia/Gaza', 'EET-2EEST,M3.5.6/1,M10.5.6/1' }, - { 'Asia/Hebron', 'EET-2EEST,M3.5.6/1,M10.5.6/1' }, + { 'Asia/Gaza', 'EET-2EEST,M3.4.6/1,M10.5.6/1' }, + { 'Asia/Hebron', 'EET-2EEST,M3.4.6/1,M10.5.6/1' }, { 'Asia/Ho Chi Minh', '<+07>-7' }, { 'Asia/Hong Kong', 'HKT-8' }, { 'Asia/Hovd', '<+07>-7' }, diff --git a/modules/luci-base/luasrc/tools/status.lua b/modules/luci-base/luasrc/tools/status.lua index 501211181..06a9ad415 100644 --- a/modules/luci-base/luasrc/tools/status.lua +++ b/modules/luci-base/luasrc/tools/status.lua @@ -187,7 +187,9 @@ function switch_status(devs) local switches = { } for dev in devs:gmatch("[^%s,]+") do local ports = { } - local swc = io.popen("swconfig dev %q show" % dev, "r") + local swc = io.popen("swconfig dev %s show" + % luci.util.shellquote(dev), "r") + if swc then local l repeat diff --git a/modules/luci-base/luasrc/util.lua b/modules/luci-base/luasrc/util.lua index 0e7334be8..ce42af2fb 100644 --- a/modules/luci-base/luasrc/util.lua +++ b/modules/luci-base/luasrc/util.lua @@ -10,6 +10,7 @@ local string = require "string" local coroutine = require "coroutine" local tparser = require "luci.template.parser" local json = require "luci.jsonc" +local lhttp = require "lucihttp" local _ubus = require "ubus" local _ubus_connection = nil @@ -160,10 +161,33 @@ function pcdata(value) return value and tparser.pcdata(tostring(value)) end +function urlencode(value) + if value ~= nil then + local str = tostring(value) + return lhttp.urlencode(str, lhttp.ENCODE_IF_NEEDED + lhttp.ENCODE_FULL) + or str + end + return nil +end + +function urldecode(value, decode_plus) + if value ~= nil then + local flag = decode_plus and lhttp.DECODE_PLUS or 0 + local str = tostring(value) + return lhttp.urldecode(str, lhttp.DECODE_IF_NEEDED + flag) + or str + end + return nil +end + function striptags(value) return value and tparser.striptags(tostring(value)) end +function shellquote(value) + return string.format("'%s'", string.gsub(value or "", "'", "'\\''")) +end + -- for bash, ash and similar shells single-quoted strings are taken -- literally except for single quotes (which terminate the string) -- (and the exception noted below for dash (-) at the start of a @@ -383,16 +407,6 @@ function clone(object, deep) end -function dtable() - return setmetatable({}, { __index = - function(tbl, key) - return rawget(tbl, key) - or rawget(rawset(tbl, key, dtable()), key) - end - }) -end - - -- Serialize the contents of a table value. function _serialize_table(t, seen) assert(not seen[t], "Recursion detected.") @@ -617,6 +631,20 @@ function execl(command) return data end + +local ubus_codes = { + "INVALID_COMMAND", + "INVALID_ARGUMENT", + "METHOD_NOT_FOUND", + "NOT_FOUND", + "NO_DATA", + "PERMISSION_DENIED", + "TIMEOUT", + "NOT_SUPPORTED", + "UNKNOWN_ERROR", + "CONNECTION_FAILED" +} + function ubus(object, method, data) if not _ubus_connection then _ubus_connection = _ubus.connect() @@ -627,7 +655,8 @@ function ubus(object, method, data) if type(data) ~= "table" then data = { } end - return _ubus_connection:call(object, method, data) + local rv, err = _ubus_connection:call(object, method, data) + return rv, err, ubus_codes[err] elseif object then return _ubus_connection:signatures(object) else @@ -652,10 +681,11 @@ end function checklib(fullpathexe, wantedlib) local fs = require "nixio.fs" local haveldd = fs.access('/usr/bin/ldd') - if not haveldd then + local haveexe = fs.access(fullpathexe) + if not haveldd or not haveexe then return false end - local libs = exec("/usr/bin/ldd " .. fullpathexe) + local libs = exec(string.format("/usr/bin/ldd %s", shellquote(fullpathexe))) if not libs then return false end diff --git a/modules/luci-base/luasrc/util.luadoc b/modules/luci-base/luasrc/util.luadoc index 949aeb21c..c4f28d039 100644 --- a/modules/luci-base/luasrc/util.luadoc +++ b/modules/luci-base/luasrc/util.luadoc @@ -15,126 +15,164 @@ Class can be instantiated by calling them. All parameters will be passed to the __init__ function of this class - if such a function exists. The __init__ function must be used to set any object parameters that are not shared with other objects of this class. Any return values will be ignored. -@class function -@name class -@param base The base class to inherit from (optional) -@return A class object -@see instanceof -@see clone + +@class function +@name class +@param base The base class to inherit from (optional) +@return A class object +@see instanceof +@see clone ]] ---[[ Test whether the given object is an instance of the given class. -@class function -@name instanceof -@param object Object instance +@class function +@name instanceof +@param object Object instance @param class Class object to test against -@return Boolean indicating whether the object is an instance +@return Boolean indicating whether the object is an instance @see class @see clone ]] ---[[ Create a new or get an already existing thread local store associated with +the current active coroutine. -the current active coroutine. A thread local store is private a table object +A thread local store is private a table object whose values can't be accessed from outside of the running coroutine. -@class function -@name threadlocal -@return Table value representing the corresponding thread local store + +@class function +@name threadlocal +@return Table value representing the corresponding thread local store ]] ---[[ Write given object to stderr. -@class function -@name perror -@param obj Value to write to stderr -@return Boolean indicating whether the write operation was successful +@class function +@name perror +@param obj Value to write to stderr +@return Boolean indicating whether the write operation was successful ]] ---[[ Recursively dumps a table to stdout, useful for testing and debugging. -@class function -@name dumptable -@param t Table value to dump -@param maxdepth Maximum depth -@return Always nil +@class function +@name dumptable +@param t Table value to dump +@param maxdepth Maximum depth +@return Always nil ]] ---[[ Create valid XML PCDATA from given string. -@class function -@name pcdata -@param value String value containing the data to escape -@return String value containing the escaped data +@class function +@name pcdata +@param value String value containing the data to escape +@return String value containing the escaped data +]] + +---[[ +Decode an URL-encoded string - optionally decoding the "+" sign to space. + +@class function +@name urldecode +@param str Input string in x-www-urlencoded format +@param decode_plus Decode "+" signs to spaces if true (optional) +@return The decoded string +@see urlencode +]] + +---[[ +URL-encode given string. + +@class function +@name urlencode +@param str String to encode +@return String containing the encoded data +@see urldecode ]] ---[[ Strip HTML tags from given string. -@class function -@name striptags -@param value String containing the HTML text -@return String with HTML tags stripped of +@class function +@name striptags +@param value String containing the HTML text +@return String with HTML tags stripped of ]] ---[[ -Splits given string on a defined separator sequence and return a table +Safely quote value for use in shell commands. + +@class function +@name shellquote +@param value String containing the value to quote +@return Single-quote enclosed string with embedded quotes escaped +]] -containing the resulting substrings. The optional max parameter specifies -the number of bytes to process, regardless of the actual length of the given -string. The optional last parameter, regex, specifies whether the separator -sequence is interpreted as regular expression. -@class function -@name split -@param str String value containing the data to split up -@param pat String with separator pattern (optional, defaults to "\n") -@param max Maximum times to split (optional) -@param regex Boolean indicating whether to interpret the separator +---[[ +Splits given string on a defined separator sequence and return a table +containing the resulting substrings. + +The optional max parameter specifies the number of bytes to process, +regardless of the actual length of the given string. The optional last +parameter, regex, specifies whether the separator sequence is +nterpreted as regular expression. + +@class function +@name split +@param str String value containing the data to split up +@param pat String with separator pattern (optional, defaults to "\n") +@param max Maximum times to split (optional) +@param regex Boolean indicating whether to interpret the separator -- pattern as regular expression (optional, default is false) -@return Table containing the resulting substrings +@return Table containing the resulting substrings ]] ---[[ Remove leading and trailing whitespace from given string value. -@class function -@name trim -@param str String value containing whitespace padded data -@return String value with leading and trailing space removed +@class function +@name trim +@param str String value containing whitespace padded data +@return String value with leading and trailing space removed ]] ---[[ Count the occurrences of given substring in given string. -@class function -@name cmatch -@param str String to search in -@param pattern String containing pattern to find -@return Number of found occurrences +@class function +@name cmatch +@param str String to search in +@param pattern String containing pattern to find +@return Number of found occurrences ]] ---[[ -Return a matching iterator for the given value. The iterator will return +Return a matching iterator for the given value. + +The iterator will return one token per invocation, the tokens are separated by +whitespace. If the input value is a table, it is transformed into a string first. +A nil value will result in a valid interator which aborts with the first invocation. -one token per invocation, the tokens are separated by whitespace. If the -input value is a table, it is transformed into a string first. A nil value -will result in a valid interator which aborts with the first invocation. -@class function -@name imatch -@param val The value to scan (table, string or nil) -@return Iterator which returns one token per call +@class function +@name imatch +@param val The value to scan (table, string or nil) +@return Iterator which returns one token per call ]] ---[[ Parse certain units from the given string and return the canonical integer +value or 0 if the unit is unknown. -value or 0 if the unit is unknown. Upper- or lower case is irrelevant. +Upper- or lower case is irrelevant. Recognized units are: + -- o "y" - one year (60*60*24*366) o "m" - one month (60*60*24*31) o "w" - one week (60*60*24*7) @@ -147,232 +185,229 @@ Recognized units are: o "kib" - one si kilobyte (1000) o "mib" - one si megabyte (1000*1000) o "gib" - one si gigabyte (1000*1000*1000) -@class function -@name parse_units -@param ustr String containing a numerical value with trailing unit -@return Number containing the canonical value + +@class function +@name parse_units +@param ustr String containing a numerical value with trailing unit +@return Number containing the canonical value ]] ---[[ Appends numerically indexed tables or single objects to a given table. -@class function -@name append -@param src Target table -@param ... Objects to insert -@return Target table +@class function +@name append +@param src Target table +@param ... Objects to insert +@return Target table ]] ---[[ Combines two or more numerically indexed tables and single objects into one table. -@class function -@name combine -@param tbl1 Table value to combine -@param tbl2 Table value to combine -@param ... More tables to combine -@return Table value containing all values of given tables +@class function +@name combine +@param tbl1 Table value to combine +@param tbl2 Table value to combine +@param ... More tables to combine +@return Table value containing all values of given tables ]] ---[[ Checks whether the given table contains the given value. -@class function -@name contains -@param table Table value -@param value Value to search within the given table -@return number indicating the first index at which the given value occurs --- within table or false. +@class function +@name contains +@param table Table value +@param value Value to search within the given table +@return Number indicating the first index at which the given value occurs +-- within table or false. ]] ---[[ Update values in given table with the values from the second given table. Both table are - in fact - merged together. -@class function -@name update + +@class function +@name update @param t Table which should be updated -@param updates Table containing the values to update -@return Always nil +@param updates Table containing the values to update +@return Always nil ]] ---[[ Retrieve all keys of given associative table. -@class function -@name keys -@param t Table to extract keys from -@return Sorted table containing the keys +@class function +@name keys +@param t Table to extract keys from +@return Sorted table containing the keys ]] ---[[ Clones the given object and return it's copy. -@class function -@name clone -@param object Table value to clone -@param deep Boolean indicating whether to do recursive cloning -@return Cloned table value -]] - ----[[ -Create a dynamic table which automatically creates subtables. - -@class function -@name dtable -@return Dynamic Table +@class function +@name clone +@param object Table value to clone +@param deep Boolean indicating whether to do recursive cloning +@return Cloned table value ]] ---[[ Recursively serialize given data to lua code, suitable for restoring - with loadstring(). -@class function -@name serialize_data -@param val Value containing the data to serialize -@return String value containing the serialized code -@see restore_data -@see get_bytecode + +@class function +@name serialize_data +@param val Value containing the data to serialize +@return String value containing the serialized code +@see restore_data +@see get_bytecode ]] ---[[ Restore data previously serialized with serialize_data(). -@class function -@name restore_data -@param str String containing the data to restore -@return Value containing the restored data structure -@see serialize_data -@see get_bytecode +@class function +@name restore_data +@param str String containing the data to restore +@return Value containing the restored data structure +@see serialize_data +@see get_bytecode ]] ---[[ Return the current runtime bytecode of the given data. The byte code - will be stripped before it is returned. -@class function -@name get_bytecode -@param val Value to return as bytecode -@return String value containing the bytecode of the given data + +@class function +@name get_bytecode +@param val Value to return as bytecode +@return String value containing the bytecode of the given data ]] ---[[ -Strips unnescessary lua bytecode from given string. Information like line +Strips unnescessary lua bytecode from given string. + +Information like line numbers and debugging numbers will be discarded. +Original version by Peter Cawley (http://lua-users.org/lists/lua-l/2008-02/msg01158.html) -numbers and debugging numbers will be discarded. Original version by -Peter Cawley (http://lua-users.org/lists/lua-l/2008-02/msg01158.html) -@class function -@name strip_bytecode -@param code String value containing the original lua byte code -@return String value containing the stripped lua byte code +@class function +@name strip_bytecode +@param code String value containing the original lua byte code +@return String value containing the stripped lua byte code ]] ---[[ Return a key, value iterator which returns the values sorted according to - the provided callback function. -@class function -@name spairs -@param t The table to iterate -@param f A callback function to decide the order of elements -@return Function value containing the corresponding iterator + +@class function +@name spairs +@param t The table to iterate +@param f A callback function to decide the order of elements +@return Function value containing the corresponding iterator ]] ---[[ Return a key, value iterator for the given table. The table pairs are sorted by key. -@class function -@name kspairs -@param t The table to iterate -@return Function value containing the corresponding iterator + +@class function +@name kspairs +@param t The table to iterate +@return Function value containing the corresponding iterator ]] ---[[ Return a key, value iterator for the given table. The table pairs are sorted by value. -@class function -@name vspairs -@param t The table to iterate -@return Function value containing the corresponding iterator + +@class function +@name vspairs +@param t The table to iterate +@return Function value containing the corresponding iterator ]] ---[[ Test whether the current system is operating in big endian mode. -@class function -@name bigendian -@return Boolean value indicating whether system is big endian +@class function +@name bigendian +@return Boolean value indicating whether system is big endian ]] ---[[ Execute given commandline and gather stdout. -@class function -@name exec -@param command String containing command to execute -@return String containing the command's stdout +@class function +@name exec +@param command String containing command to execute +@return String containing the command's stdout ]] ---[[ Return a line-buffered iterator over the output of given command. -@class function -@name execi -@param command String containing the command to execute -@return Iterator +@class function +@name execi +@param command String containing the command to execute +@return Iterator ]] ---[[ Issue an ubus call. -@class function -@name ubus +@class function +@name ubus @param object String containing the ubus object to call @param method String containing the ubus method to call @param values Table containing the values to pass -@return Table containin the ubus result +@return Table containin the ubus result ]] ---[[ Convert data structure to JSON -@class function -@name serialize_json -@param data The data to serialize -@param writer A function to write a chunk of JSON data (optional) -@return String containing the JSON if called without write callback +@class function +@name serialize_json +@param data The data to serialize +@param writer A function to write a chunk of JSON data (optional) +@return String containing the JSON if called without write callback ]] ---[[ Returns the absolute path to LuCI base directory. -@class function -@name libpath -@return String containing the directory path +@class function +@name libpath +@return String containing the directory path ]] ---[[ This is a coroutine-safe drop-in replacement for Lua's "xpcall"-function -@class function -@name coxpcall -@param f Lua function to be called protected -@param err Custom error handler -@param ... Parameters passed to the function -@return A boolean whether the function call succeeded and the return --- values of either the function or the error handler +@class function +@name coxpcall +@param f Lua function to be called protected +@param err Custom error handler +@param ... Parameters passed to the function +@return A boolean whether the function call succeeded and the return +-- values of either the function or the error handler ]] ---[[ This is a coroutine-safe drop-in replacement for Lua's "pcall"-function -@class function -@name copcall -@param f Lua function to be called protected -@param ... Parameters passed to the function -@return A boolean whether the function call succeeded and the returns --- values of the function or the error object +@class function +@name copcall +@param f Lua function to be called protected +@param ... Parameters passed to the function +@return A boolean whether the function call succeeded and the returns +-- values of the function or the error object ]] diff --git a/modules/luci-base/luasrc/view/cbi/filebrowser.htm b/modules/luci-base/luasrc/view/cbi/filebrowser.htm index a79beebba..806b1b5f4 100644 --- a/modules/luci-base/luasrc/view/cbi/filebrowser.htm +++ b/modules/luci-base/luasrc/view/cbi/filebrowser.htm @@ -22,9 +22,9 @@ <% end %> + + diff --git a/modules/luci-base/luasrc/view/cbi/tblsection.htm b/modules/luci-base/luasrc/view/cbi/tblsection.htm index 26d13f937..3cb87563f 100644 --- a/modules/luci-base/luasrc/view/cbi/tblsection.htm +++ b/modules/luci-base/luasrc/view/cbi/tblsection.htm @@ -35,7 +35,7 @@ end <%- else -%>   <%- end -%> - <%- end -%> + <%- count = count +1; end -%> <%- for i, k in pairs(self.children) do if not k.optional then -%> > <%- if k.titleref then -%><%- end -%> @@ -44,7 +44,7 @@ end <%- count = count + 1; end; end; if self.sortable then -%> <%:Sort%> - <%- end; if self.extedit or self.addremove then -%> + <%- count = count + 1; end; if self.extedit or self.addremove then -%>   <%- count = count + 1; end -%> diff --git a/modules/luci-base/luasrc/view/error404.htm b/modules/luci-base/luasrc/view/error404.htm index bc7422683..a762f6038 100644 --- a/modules/luci-base/luasrc/view/error404.htm +++ b/modules/luci-base/luasrc/view/error404.htm @@ -7,5 +7,5 @@ <%+header%>

    404 <%:Not Found%>

    <%:Sorry, the object you requested was not found.%>

    -<%:Unable to dispatch%>: <%=luci.http.request.env.PATH_INFO%> +<%:Unable to dispatch%>: <%=url(unpack(luci.dispatcher.context.request))%> <%+footer%> diff --git a/modules/luci-base/luasrc/view/sysauth.htm b/modules/luci-base/luasrc/view/sysauth.htm index f6b0f5706..b3ec9b761 100644 --- a/modules/luci-base/luasrc/view/sysauth.htm +++ b/modules/luci-base/luasrc/view/sysauth.htm @@ -6,7 +6,7 @@ <%+header%> -
    "> + <%- if fuser then %>
    <%:Invalid username and/or password! Please try again.%>
    <% end -%> diff --git a/modules/luci-base/po/ca/base.po b/modules/luci-base/po/ca/base.po index a6a8843a7..c413b7172 100644 --- a/modules/luci-base/po/ca/base.po +++ b/modules/luci-base/po/ca/base.po @@ -744,6 +744,11 @@ msgid "Custom feeds" msgstr "" msgid "" +"Custom files (certificates, scripts) may remain on the system. To prevent " +"this, perform a factory-reset first." +msgstr "" + +msgid "" "Customizes the behaviour of the device LEDs if possible." msgstr "" @@ -2154,6 +2159,9 @@ msgstr "Avís" msgid "Nslookup" msgstr "Nslookup" +msgid "Number of cached DNS entries (max is 10000, 0 is no caching)" +msgstr "" + msgid "OK" msgstr "D'acord" @@ -2913,6 +2921,9 @@ msgstr "Mida" msgid "Size (.ipk)" msgstr "Mida (.ipk)" +msgid "Size of DNS query cache" +msgstr "" + msgid "Skip" msgstr "Salta" @@ -3305,7 +3316,7 @@ msgstr "" msgid "" "This is the local endpoint address assigned by the tunnel broker, it usually " -"ends with :2" +"ends with ...:2/64" msgstr "" msgid "" diff --git a/modules/luci-base/po/cs/base.po b/modules/luci-base/po/cs/base.po index c69654f1e..89714cc81 100644 --- a/modules/luci-base/po/cs/base.po +++ b/modules/luci-base/po/cs/base.po @@ -738,6 +738,11 @@ msgid "Custom feeds" msgstr "" msgid "" +"Custom files (certificates, scripts) may remain on the system. To prevent " +"this, perform a factory-reset first." +msgstr "" + +msgid "" "Customizes the behaviour of the device LEDs if possible." msgstr "" @@ -2162,6 +2167,9 @@ msgstr "Oznámení" msgid "Nslookup" msgstr "Nslookup" +msgid "Number of cached DNS entries (max is 10000, 0 is no caching)" +msgstr "" + msgid "OK" msgstr "OK" @@ -2939,6 +2947,9 @@ msgstr "Velikost" msgid "Size (.ipk)" msgstr "" +msgid "Size of DNS query cache" +msgstr "" + msgid "Skip" msgstr "Přeskočit" @@ -3347,7 +3358,7 @@ msgstr "" msgid "" "This is the local endpoint address assigned by the tunnel broker, it usually " -"ends with :2" +"ends with ...:2/64" msgstr "" msgid "" diff --git a/modules/luci-base/po/de/base.po b/modules/luci-base/po/de/base.po index 47472a37c..fd495b950 100644 --- a/modules/luci-base/po/de/base.po +++ b/modules/luci-base/po/de/base.po @@ -764,6 +764,11 @@ msgid "Custom feeds" msgstr "Eigene Repositories" msgid "" +"Custom files (certificates, scripts) may remain on the system. To prevent " +"this, perform a factory-reset first." +msgstr "" + +msgid "" "Customizes the behaviour of the device LEDs if possible." msgstr "Passt das Verhalten der Geräte-LEDs an - wenn dies möglich ist." @@ -2228,6 +2233,9 @@ msgstr "Notiz" msgid "Nslookup" msgstr "DNS-Auflösung" +msgid "Number of cached DNS entries (max is 10000, 0 is no caching)" +msgstr "" + msgid "OK" msgstr "OK" @@ -3039,6 +3047,9 @@ msgstr "Größe" msgid "Size (.ipk)" msgstr "Größe (.ipk)" +msgid "Size of DNS query cache" +msgstr "" + msgid "Skip" msgstr "Überspringen" @@ -3480,10 +3491,10 @@ msgstr "" msgid "" "This is the local endpoint address assigned by the tunnel broker, it usually " -"ends with :2" +"ends with ...:2/64" msgstr "" "Dies ist die lokale, vom Broker zugewiesene IPv6-Adresse, sie endet " -"üblicherweise mit :2" +"üblicherweise mit ...:2/64" msgid "" "This is the only DHCPLEDs if possible." msgstr "" @@ -2170,6 +2175,9 @@ msgstr "Επισήμανση" msgid "Nslookup" msgstr "" +msgid "Number of cached DNS entries (max is 10000, 0 is no caching)" +msgstr "" + msgid "OK" msgstr "Εντάξει" @@ -2931,6 +2939,9 @@ msgstr "Μέγεθος" msgid "Size (.ipk)" msgstr "" +msgid "Size of DNS query cache" +msgstr "" + msgid "Skip" msgstr "Παράκαμψη" @@ -3307,7 +3318,7 @@ msgstr "" msgid "" "This is the local endpoint address assigned by the tunnel broker, it usually " -"ends with :2" +"ends with ...:2/64" msgstr "" msgid "" diff --git a/modules/luci-base/po/en/base.po b/modules/luci-base/po/en/base.po index fbaa03b6f..f62913595 100644 --- a/modules/luci-base/po/en/base.po +++ b/modules/luci-base/po/en/base.po @@ -734,6 +734,11 @@ msgid "Custom feeds" msgstr "" msgid "" +"Custom files (certificates, scripts) may remain on the system. To prevent " +"this, perform a factory-reset first." +msgstr "" + +msgid "" "Customizes the behaviour of the device LEDs if possible." msgstr "" @@ -2137,6 +2142,9 @@ msgstr "" msgid "Nslookup" msgstr "" +msgid "Number of cached DNS entries (max is 10000, 0 is no caching)" +msgstr "" + msgid "OK" msgstr "OK" @@ -2895,6 +2903,9 @@ msgstr "Size" msgid "Size (.ipk)" msgstr "" +msgid "Size of DNS query cache" +msgstr "" + msgid "Skip" msgstr "Skip" @@ -3267,7 +3278,7 @@ msgstr "" msgid "" "This is the local endpoint address assigned by the tunnel broker, it usually " -"ends with :2" +"ends with ...:2/64" msgstr "" msgid "" diff --git a/modules/luci-base/po/es/base.po b/modules/luci-base/po/es/base.po index a92bb43c1..776f7fb15 100644 --- a/modules/luci-base/po/es/base.po +++ b/modules/luci-base/po/es/base.po @@ -743,6 +743,11 @@ msgid "Custom feeds" msgstr "" msgid "" +"Custom files (certificates, scripts) may remain on the system. To prevent " +"this, perform a factory-reset first." +msgstr "" + +msgid "" "Customizes the behaviour of the device LEDs if possible." msgstr "" @@ -2176,6 +2181,9 @@ msgstr "Aviso" msgid "Nslookup" msgstr "NSLookup" +msgid "Number of cached DNS entries (max is 10000, 0 is no caching)" +msgstr "" + msgid "OK" msgstr "Aceptar" @@ -2952,6 +2960,9 @@ msgstr "Tamaño" msgid "Size (.ipk)" msgstr "" +msgid "Size of DNS query cache" +msgstr "" + msgid "Skip" msgstr "Saltar" @@ -3372,10 +3383,10 @@ msgstr "" msgid "" "This is the local endpoint address assigned by the tunnel broker, it usually " -"ends with :2" +"ends with ...:2/64" msgstr "" "Esta es la dirección de punto final asignada por el broker del túnel, suele " -"terminar con :2" +"terminar con ...:2/64" msgid "" "This is the only DHCPLEDs if possible." msgstr "" @@ -2190,6 +2195,9 @@ msgstr "Note" msgid "Nslookup" msgstr "Nslookup" +msgid "Number of cached DNS entries (max is 10000, 0 is no caching)" +msgstr "" + msgid "OK" msgstr "OK" @@ -2966,6 +2974,9 @@ msgstr "Taille" msgid "Size (.ipk)" msgstr "" +msgid "Size of DNS query cache" +msgstr "" + msgid "Skip" msgstr "Passer au suivant" @@ -3387,10 +3398,10 @@ msgstr "" msgid "" "This is the local endpoint address assigned by the tunnel broker, it usually " -"ends with :2" +"ends with ...:2/64" msgstr "" "Il s'agit de l'adresse de l'extrémité locale attribuée par le fournisseur de " -"tunnels, elle se termine habituellement avec :2" +"tunnels, elle se termine habituellement avec ...:2/64" msgid "" "This is the only DHCPLEDs if possible." msgstr "" @@ -2110,6 +2115,9 @@ msgstr "" msgid "Nslookup" msgstr "" +msgid "Number of cached DNS entries (max is 10000, 0 is no caching)" +msgstr "" + msgid "OK" msgstr "" @@ -2862,6 +2870,9 @@ msgstr "" msgid "Size (.ipk)" msgstr "" +msgid "Size of DNS query cache" +msgstr "" + msgid "Skip" msgstr "" @@ -3228,7 +3239,7 @@ msgstr "" msgid "" "This is the local endpoint address assigned by the tunnel broker, it usually " -"ends with :2" +"ends with ...:2/64" msgstr "" msgid "" diff --git a/modules/luci-base/po/hu/base.po b/modules/luci-base/po/hu/base.po index e7b3a79bc..5e2ea2b17 100644 --- a/modules/luci-base/po/hu/base.po +++ b/modules/luci-base/po/hu/base.po @@ -745,6 +745,11 @@ msgid "Custom feeds" msgstr "" msgid "" +"Custom files (certificates, scripts) may remain on the system. To prevent " +"this, perform a factory-reset first." +msgstr "" + +msgid "" "Customizes the behaviour of the device LEDs if possible." msgstr "" @@ -2179,6 +2184,9 @@ msgstr "Megjegyzés" msgid "Nslookup" msgstr "Nslookup" +msgid "Number of cached DNS entries (max is 10000, 0 is no caching)" +msgstr "" + msgid "OK" msgstr "OK" @@ -2957,6 +2965,9 @@ msgstr "Méret" msgid "Size (.ipk)" msgstr "" +msgid "Size of DNS query cache" +msgstr "" + msgid "Skip" msgstr "Ugrás" @@ -3375,10 +3386,10 @@ msgstr "" msgid "" "This is the local endpoint address assigned by the tunnel broker, it usually " -"ends with :2" +"ends with ...:2/64" msgstr "" "Ez az alagút közvetítő (tunnel broker) által megadott helyi végpont címe, " -"általában így végződik: :2" +"általában így végződik: ...:2/64" msgid "" "This is the only DHCPLEDs if possible." msgstr "" @@ -2179,6 +2184,9 @@ msgstr "Notifica" msgid "Nslookup" msgstr "" +msgid "Number of cached DNS entries (max is 10000, 0 is no caching)" +msgstr "" + msgid "OK" msgstr "OK" @@ -2941,6 +2949,9 @@ msgstr "Dimensione" msgid "Size (.ipk)" msgstr "" +msgid "Size of DNS query cache" +msgstr "" + msgid "Skip" msgstr "Salta" @@ -3335,7 +3346,7 @@ msgstr "" msgid "" "This is the local endpoint address assigned by the tunnel broker, it usually " -"ends with :2" +"ends with ...:2/64" msgstr "" msgid "" diff --git a/modules/luci-base/po/ja/base.po b/modules/luci-base/po/ja/base.po index c06994002..b643e8cf5 100644 --- a/modules/luci-base/po/ja/base.po +++ b/modules/luci-base/po/ja/base.po @@ -3,18 +3,18 @@ msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2009-06-10 03:40+0200\n" -"PO-Revision-Date: 2017-10-20 13:54+0900\n" +"PO-Revision-Date: 2018-04-26 00:23+0900\n" "Last-Translator: INAGAKI Hiroshi \n" "Language: ja\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -"X-Generator: Poedit 2.0.4\n" +"X-Generator: Poedit 2.0.7\n" "Language-Team: \n" msgid "%.1f dB" -msgstr "" +msgstr "%.1f dB" msgid "%s is untagged in multiple VLANs!" msgstr "%s は複数のVLANにUntaggedしています!" @@ -137,7 +137,7 @@ msgid "MAC-Address" msgstr "MAC-アドレス" msgid "DUID" -msgstr "" +msgstr "DUID" msgid "" "Max. LEDs if possible." msgstr "" @@ -1254,7 +1263,7 @@ msgid "Force use of NAT-T" msgstr "NAT-Tの強制使用" msgid "Form token mismatch" -msgstr "" +msgstr "フォーム トークンの不一致" msgid "Forward DHCP traffic" msgstr "DHCPトラフィックを転送する" @@ -1661,7 +1670,7 @@ msgstr "" "ユーザー名かパスワード、もしくは両方が不正です!もう一度入力してください。" msgid "Isolate Clients" -msgstr "" +msgstr "クライアント間の分離" msgid "" "It appears that you are trying to flash an image that does not fit into the " @@ -1756,6 +1765,8 @@ msgstr "割り当て数" msgid "Limit DNS service to subnets interfaces on which we are serving DNS." msgstr "" +"DNS サービスを、現在 DNS を提供しているサブネットのインターフェースに限定しま" +"す。" msgid "Limit listening to these interfaces, and loopback." msgstr "待ち受けをこれらのインターフェースとループバックに制限します。" @@ -1840,7 +1851,7 @@ msgid "Local IPv6 address" msgstr "ローカル IPv6 アドレス" msgid "Local Service Only" -msgstr "" +msgstr "ローカルサービスのみ" msgid "Local Startup" msgstr "ローカル スタートアップ" @@ -1855,6 +1866,8 @@ msgid "" "Local domain specification. Names matching this domain are never forwarded " "and are resolved from DHCP or hosts files only" msgstr "" +"ローカル ドメインの定義です。このドメインに一致する名前は転送が行われず、 " +"DHCP または hosts ファイルのみにより解決されます。" msgid "Local domain suffix appended to DHCP names and hosts file entries" msgstr "" @@ -2178,6 +2191,9 @@ msgstr "注意" msgid "Nslookup" msgstr "Nslookup" +msgid "Number of cached DNS entries (max is 10000, 0 is no caching)" +msgstr "" + msgid "OK" msgstr "OK" @@ -2962,6 +2978,9 @@ msgstr "サイズ" msgid "Size (.ipk)" msgstr "サイズ (.ipk)" +msgid "Size of DNS query cache" +msgstr "" + msgid "Skip" msgstr "スキップ" @@ -3085,10 +3104,10 @@ msgid "Submit" msgstr "送信" msgid "Suppress logging" -msgstr "" +msgstr "ログの抑制" msgid "Suppress logging of the routine operation of these protocols" -msgstr "" +msgstr "これらのプロトコルのルーチン的操作についてのログを抑制します。" msgid "Swap" msgstr "スワップ" @@ -3110,7 +3129,7 @@ msgid "" msgstr "" msgid "Switch Port Mask" -msgstr "" +msgstr "スイッチポート マスク" msgid "Switch VLAN" msgstr "" @@ -3338,13 +3357,16 @@ msgstr "" "サービスを有効にするために、管理者パスワードを設定してください。" msgid "This IPv4 address of the relay" -msgstr "" +msgstr "リレーの IPv4 アドレス" msgid "" "This file may contain lines like 'server=/domain/1.2.3.4' or " "'server=1.2.3.4' fordomain-specific or full upstream DNS servers." msgstr "" +"このファイルは、特定ドメイン用、または上位 DNS サーバーのための 'server=/domain/1.2.3.4' や 'server=1.2.3.4' " +"というような行を含めることができます。" msgid "" "This is a list of shell glob patterns for matching files and directories to " @@ -3369,17 +3391,17 @@ msgstr "" msgid "" "This is the local endpoint address assigned by the tunnel broker, it usually " -"ends with :2" +"ends with ...:2/64" msgstr "" "プロバイダからアサインされた、ローカルのエンドポイント アドレスです。通常、" -":2が終端に設定されます。" +"...:2/64が終端に設定されます。" msgid "" "This is the only DHCP in the local network" msgstr "" -"ローカル ネットワーク内のみの DHCPとして使用する" +"これはローカル ネットワーク内のみの DHCP です。" msgid "This is the plain username for logging into the account" msgstr "" @@ -3946,24 +3968,3 @@ msgstr "はい" msgid "« Back" msgstr "« 戻る" - -#~ msgid "Action" -#~ msgstr "動作" - -#~ msgid "Buttons" -#~ msgstr "ボタン" - -#~ msgid "Handler" -#~ msgstr "ハンドラ" - -#~ msgid "Maximum hold time" -#~ msgstr "最大保持時間" - -#~ msgid "Minimum hold time" -#~ msgstr "最短保持時間" - -#~ msgid "Path to executable which handles the button event" -#~ msgstr "ボタンイベントをハンドルする実行ファイルのパス" - -#~ msgid "This page allows the configuration of custom button actions" -#~ msgstr "このページでは、ボタンの動作を変更することができます。" diff --git a/modules/luci-base/po/ko/base.po b/modules/luci-base/po/ko/base.po index c56c05e2a..04d3c6a23 100644 --- a/modules/luci-base/po/ko/base.po +++ b/modules/luci-base/po/ko/base.po @@ -732,6 +732,11 @@ msgid "Custom feeds" msgstr "Custom feed 들" msgid "" +"Custom files (certificates, scripts) may remain on the system. To prevent " +"this, perform a factory-reset first." +msgstr "" + +msgid "" "Customizes the behaviour of the device LEDs if possible." msgstr "" @@ -2128,6 +2133,9 @@ msgstr "" msgid "Nslookup" msgstr "" +msgid "Number of cached DNS entries (max is 10000, 0 is no caching)" +msgstr "" + msgid "OK" msgstr "" @@ -2890,6 +2898,9 @@ msgstr "Size" msgid "Size (.ipk)" msgstr "크기 (.ipk)" +msgid "Size of DNS query cache" +msgstr "" + msgid "Skip" msgstr "" @@ -3270,7 +3281,7 @@ msgstr "" msgid "" "This is the local endpoint address assigned by the tunnel broker, it usually " -"ends with :2" +"ends with ...:2/64" msgstr "" msgid "" diff --git a/modules/luci-base/po/ms/base.po b/modules/luci-base/po/ms/base.po index ff3324315..b478bd623 100644 --- a/modules/luci-base/po/ms/base.po +++ b/modules/luci-base/po/ms/base.po @@ -712,6 +712,11 @@ msgid "Custom feeds" msgstr "" msgid "" +"Custom files (certificates, scripts) may remain on the system. To prevent " +"this, perform a factory-reset first." +msgstr "" + +msgid "" "Customizes the behaviour of the device LEDs if possible." msgstr "Mengkustomisasi perilaku peranti LED jika mungkin." @@ -2108,6 +2113,9 @@ msgstr "" msgid "Nslookup" msgstr "" +msgid "Number of cached DNS entries (max is 10000, 0 is no caching)" +msgstr "" + msgid "OK" msgstr "Baik" @@ -2864,6 +2872,9 @@ msgstr "Saiz" msgid "Size (.ipk)" msgstr "" +msgid "Size of DNS query cache" +msgstr "" + msgid "Skip" msgstr "Skip" @@ -3238,7 +3249,7 @@ msgstr "" msgid "" "This is the local endpoint address assigned by the tunnel broker, it usually " -"ends with :2" +"ends with ...:2/64" msgstr "" msgid "" diff --git a/modules/luci-base/po/no/base.po b/modules/luci-base/po/no/base.po index f8b40c1e8..502c3b38a 100644 --- a/modules/luci-base/po/no/base.po +++ b/modules/luci-base/po/no/base.po @@ -734,6 +734,11 @@ msgid "Custom feeds" msgstr "" msgid "" +"Custom files (certificates, scripts) may remain on the system. To prevent " +"this, perform a factory-reset first." +msgstr "" + +msgid "" "Customizes the behaviour of the device LEDs if possible." msgstr "" @@ -2153,6 +2158,9 @@ msgstr "Merk" msgid "Nslookup" msgstr "Nslookup" +msgid "Number of cached DNS entries (max is 10000, 0 is no caching)" +msgstr "" + msgid "OK" msgstr "OK" @@ -2930,6 +2938,9 @@ msgstr "Størrelse" msgid "Size (.ipk)" msgstr "" +msgid "Size of DNS query cache" +msgstr "" + msgid "Skip" msgstr "Gå videre" @@ -3343,10 +3354,10 @@ msgstr "" msgid "" "This is the local endpoint address assigned by the tunnel broker, it usually " -"ends with :2" +"ends with ...:2/64" msgstr "" "Dette er den lokale endepunkt adressen som ble tildelt av tunnel 'broker', " -"adressen ender vanligvis med :2" +"adressen ender vanligvis med ...:2/64" msgid "" "This is the only DHCP:2
    " +"ends with ...:2/64" msgstr "" "To jest lokalny adres końcowy przypisany przez tunnel broker'a, zwykle " -"kończący się z :2" +"kończący się z ...:2/64" # w tłumaczeniu pojawiła się spacja po DHCP co powoduje niepoprawne wyświetlanie się strony z lang PL msgid "" diff --git a/modules/luci-base/po/pt-br/base.po b/modules/luci-base/po/pt-br/base.po index bf0de75dd..9c4901f3d 100644 --- a/modules/luci-base/po/pt-br/base.po +++ b/modules/luci-base/po/pt-br/base.po @@ -787,6 +787,11 @@ msgid "Custom feeds" msgstr "Fontes de pacotes customizadas" msgid "" +"Custom files (certificates, scripts) may remain on the system. To prevent " +"this, perform a factory-reset first." +msgstr "" + +msgid "" "Customizes the behaviour of the device LEDs if possible." msgstr "" @@ -2279,6 +2284,9 @@ msgstr "Aviso" msgid "Nslookup" msgstr "Nslookup" +msgid "Number of cached DNS entries (max is 10000, 0 is no caching)" +msgstr "" + msgid "OK" msgstr "OK" @@ -3084,6 +3092,9 @@ msgstr "Tamanho" msgid "Size (.ipk)" msgstr "Tamanho (.ipk)" +msgid "Size of DNS query cache" +msgstr "" + msgid "Skip" msgstr "Pular" @@ -3519,10 +3530,10 @@ msgstr "" msgid "" "This is the local endpoint address assigned by the tunnel broker, it usually " -"ends with :2" +"ends with ...:2/64" msgstr "" "Este é o endereço da ponta local designado pelo agente de túnel. normalmente " -"ele termina com :2" +"ele termina com ...:2/64" msgid "" "This is the only DHCPLEDs if possible." msgstr "" @@ -2177,6 +2182,9 @@ msgstr "Reparo" msgid "Nslookup" msgstr "Nslookup" +msgid "Number of cached DNS entries (max is 10000, 0 is no caching)" +msgstr "" + msgid "OK" msgstr "OK" @@ -2948,6 +2956,9 @@ msgstr "Tamanho" msgid "Size (.ipk)" msgstr "" +msgid "Size of DNS query cache" +msgstr "" + msgid "Skip" msgstr "Saltar" @@ -3347,7 +3358,7 @@ msgstr "" msgid "" "This is the local endpoint address assigned by the tunnel broker, it usually " -"ends with :2" +"ends with ...:2/64" msgstr "" msgid "" diff --git a/modules/luci-base/po/ro/base.po b/modules/luci-base/po/ro/base.po index 955cff650..86eaa6495 100644 --- a/modules/luci-base/po/ro/base.po +++ b/modules/luci-base/po/ro/base.po @@ -722,6 +722,11 @@ msgid "Custom feeds" msgstr "" msgid "" +"Custom files (certificates, scripts) may remain on the system. To prevent " +"this, perform a factory-reset first." +msgstr "" + +msgid "" "Customizes the behaviour of the device LEDs if possible." msgstr "" @@ -2107,6 +2112,9 @@ msgstr "Notificare" msgid "Nslookup" msgstr "" +msgid "Number of cached DNS entries (max is 10000, 0 is no caching)" +msgstr "" + msgid "OK" msgstr "OK" @@ -2858,6 +2866,9 @@ msgstr "Marime" msgid "Size (.ipk)" msgstr "" +msgid "Size of DNS query cache" +msgstr "" + msgid "Skip" msgstr "" @@ -3220,7 +3231,7 @@ msgstr "" msgid "" "This is the local endpoint address assigned by the tunnel broker, it usually " -"ends with :2" +"ends with ...:2/64" msgstr "" msgid "" diff --git a/modules/luci-base/po/ru/base.po b/modules/luci-base/po/ru/base.po index c0b53eb9d..4ffb7233c 100644 --- a/modules/luci-base/po/ru/base.po +++ b/modules/luci-base/po/ru/base.po @@ -778,6 +778,11 @@ msgid "Custom feeds" msgstr "Список custom-ных feed-ов" msgid "" +"Custom files (certificates, scripts) may remain on the system. To prevent " +"this, perform a factory-reset first." +msgstr "" + +msgid "" "Customizes the behaviour of the device LEDs if possible." msgstr "" @@ -2235,6 +2240,9 @@ msgstr "Заметка" msgid "Nslookup" msgstr "DNS-запрос" +msgid "Number of cached DNS entries (max is 10000, 0 is no caching)" +msgstr "" + msgid "OK" msgstr "OK" @@ -3043,6 +3051,9 @@ msgstr "Размер" msgid "Size (.ipk)" msgstr "Размер (.ipk)" +msgid "Size of DNS query cache" +msgstr "" + msgid "Skip" msgstr "Пропустить" @@ -3471,10 +3482,10 @@ msgstr "" msgid "" "This is the local endpoint address assigned by the tunnel broker, it usually " -"ends with :2" +"ends with ...:2/64" msgstr "" "Это локальный адрес, назначенный туннельным брокером, обычно заканчивается " -"на :2." +"на ...:2/64." msgid "" "This is the only DHCPLEDs if possible." msgstr "" @@ -2082,6 +2087,9 @@ msgstr "" msgid "Nslookup" msgstr "" +msgid "Number of cached DNS entries (max is 10000, 0 is no caching)" +msgstr "" + msgid "OK" msgstr "" @@ -2830,6 +2838,9 @@ msgstr "" msgid "Size (.ipk)" msgstr "" +msgid "Size of DNS query cache" +msgstr "" + msgid "Skip" msgstr "" @@ -3190,7 +3201,7 @@ msgstr "" msgid "" "This is the local endpoint address assigned by the tunnel broker, it usually " -"ends with :2" +"ends with ...:2/64" msgstr "" msgid "" diff --git a/modules/luci-base/po/sv/base.po b/modules/luci-base/po/sv/base.po index a7f906e81..089546a37 100644 --- a/modules/luci-base/po/sv/base.po +++ b/modules/luci-base/po/sv/base.po @@ -719,6 +719,11 @@ msgid "Custom feeds" msgstr "Anpassade flöden" msgid "" +"Custom files (certificates, scripts) may remain on the system. To prevent " +"this, perform a factory-reset first." +msgstr "" + +msgid "" "Customizes the behaviour of the device LEDs if possible." msgstr "" @@ -2103,6 +2108,9 @@ msgstr "Avisering" msgid "Nslookup" msgstr "Nslookup" +msgid "Number of cached DNS entries (max is 10000, 0 is no caching)" +msgstr "" + msgid "OK" msgstr "OK" @@ -2853,6 +2861,9 @@ msgstr "Storlek" msgid "Size (.ipk)" msgstr "Storlek (.ipk)" +msgid "Size of DNS query cache" +msgstr "" + msgid "Skip" msgstr "Hoppa över" @@ -3215,7 +3226,7 @@ msgstr "" msgid "" "This is the local endpoint address assigned by the tunnel broker, it usually " -"ends with :2" +"ends with ...:2/64" msgstr "" msgid "" diff --git a/modules/luci-base/po/templates/base.pot b/modules/luci-base/po/templates/base.pot index a8409213f..de8b7fb22 100644 --- a/modules/luci-base/po/templates/base.pot +++ b/modules/luci-base/po/templates/base.pot @@ -698,6 +698,11 @@ msgid "Custom feeds" msgstr "" msgid "" +"Custom files (certificates, scripts) may remain on the system. To prevent " +"this, perform a factory-reset first." +msgstr "" + +msgid "" "Customizes the behaviour of the device LEDs if possible." msgstr "" @@ -2075,6 +2080,9 @@ msgstr "" msgid "Nslookup" msgstr "" +msgid "Number of cached DNS entries (max is 10000, 0 is no caching)" +msgstr "" + msgid "OK" msgstr "" @@ -2823,6 +2831,9 @@ msgstr "" msgid "Size (.ipk)" msgstr "" +msgid "Size of DNS query cache" +msgstr "" + msgid "Skip" msgstr "" @@ -3183,7 +3194,7 @@ msgstr "" msgid "" "This is the local endpoint address assigned by the tunnel broker, it usually " -"ends with :2" +"ends with ...:2/64" msgstr "" msgid "" diff --git a/modules/luci-base/po/tr/base.po b/modules/luci-base/po/tr/base.po index 496d96f7c..45f4a7c34 100644 --- a/modules/luci-base/po/tr/base.po +++ b/modules/luci-base/po/tr/base.po @@ -718,6 +718,11 @@ msgid "Custom feeds" msgstr "" msgid "" +"Custom files (certificates, scripts) may remain on the system. To prevent " +"this, perform a factory-reset first." +msgstr "" + +msgid "" "Customizes the behaviour of the device LEDs if possible." msgstr "" @@ -2095,6 +2100,9 @@ msgstr "" msgid "Nslookup" msgstr "" +msgid "Number of cached DNS entries (max is 10000, 0 is no caching)" +msgstr "" + msgid "OK" msgstr "" @@ -2843,6 +2851,9 @@ msgstr "" msgid "Size (.ipk)" msgstr "" +msgid "Size of DNS query cache" +msgstr "" + msgid "Skip" msgstr "" @@ -3203,7 +3214,7 @@ msgstr "" msgid "" "This is the local endpoint address assigned by the tunnel broker, it usually " -"ends with :2" +"ends with ...:2/64" msgstr "" msgid "" diff --git a/modules/luci-base/po/uk/base.po b/modules/luci-base/po/uk/base.po index 520bff481..b1feed3d1 100644 --- a/modules/luci-base/po/uk/base.po +++ b/modules/luci-base/po/uk/base.po @@ -756,6 +756,11 @@ msgid "Custom feeds" msgstr "" msgid "" +"Custom files (certificates, scripts) may remain on the system. To prevent " +"this, perform a factory-reset first." +msgstr "" + +msgid "" "Customizes the behaviour of the device LEDs if possible." msgstr "" @@ -2191,6 +2196,9 @@ msgstr "Попередження" msgid "Nslookup" msgstr "DNS-запит" +msgid "Number of cached DNS entries (max is 10000, 0 is no caching)" +msgstr "" + msgid "OK" msgstr "OK" @@ -2973,6 +2981,9 @@ msgstr "Розмір" msgid "Size (.ipk)" msgstr "" +msgid "Size of DNS query cache" +msgstr "" + msgid "Skip" msgstr "Пропустити" @@ -3391,10 +3402,10 @@ msgstr "" msgid "" "This is the local endpoint address assigned by the tunnel broker, it usually " -"ends with :2" +"ends with ...:2/64" msgstr "" "Це локальна адреса кінцевої точки, присвоєна тунельним брокером, зазвичай " -"закінчується на :2" +"закінчується на ...:2/64" msgid "" "This is the only DHCPLEDs if possible." msgstr "" @@ -2112,6 +2117,9 @@ msgstr "" msgid "Nslookup" msgstr "" +msgid "Number of cached DNS entries (max is 10000, 0 is no caching)" +msgstr "" + msgid "OK" msgstr "OK " @@ -2870,6 +2878,9 @@ msgstr "Dung lượng " msgid "Size (.ipk)" msgstr "" +msgid "Size of DNS query cache" +msgstr "" + msgid "Skip" msgstr "" @@ -3240,7 +3251,7 @@ msgstr "" msgid "" "This is the local endpoint address assigned by the tunnel broker, it usually " -"ends with :2" +"ends with ...:2/64" msgstr "" msgid "" diff --git a/modules/luci-base/po/zh-cn/base.po b/modules/luci-base/po/zh-cn/base.po index c0a535157..c76511b99 100644 --- a/modules/luci-base/po/zh-cn/base.po +++ b/modules/luci-base/po/zh-cn/base.po @@ -721,6 +721,12 @@ msgid "Custom feeds" msgstr "自定义软件源" msgid "" +"Custom files (certificates, scripts) may remain on the system. To prevent " +"this, perform a factory-reset first." +msgstr "" +"自定义文件(证书、脚本)会保留在系统上。若无需保留,请先执行恢复出厂设置。" + +msgid "" "Customizes the behaviour of the device LEDs if possible." msgstr "自定义此设备的 LED 行为。" @@ -2127,6 +2133,9 @@ msgstr "注意" msgid "Nslookup" msgstr "Nslookup" +msgid "Number of cached DNS entries (max is 10000, 0 is no caching)" +msgstr "缓存的 DNS 条目数量(最大 10000,0 表示不缓存)" + msgid "OK" msgstr "确认" @@ -2900,6 +2909,9 @@ msgstr "大小" msgid "Size (.ipk)" msgstr "大小(.ipk)" +msgid "Size of DNS query cache" +msgstr "DNS 查询缓存的大小" + msgid "Skip" msgstr "跳过" @@ -3283,8 +3295,8 @@ msgstr "启动脚本插入到 'exit 0' 之前即可随系统启动运行。" msgid "" "This is the local endpoint address assigned by the tunnel broker, it usually " -"ends with :2" -msgstr "隧道代理分配的本地终端地址,通常以 :2 结尾" +"ends with ...:2/64" +msgstr "隧道代理分配的本地终端地址,通常以 ...:2/64 结尾" msgid "" "This is the only DHCPLEDs if possible." msgstr "" @@ -2119,6 +2124,9 @@ msgstr "通知" msgid "Nslookup" msgstr "DNS偵錯Nslookup" +msgid "Number of cached DNS entries (max is 10000, 0 is no caching)" +msgstr "" + msgid "OK" msgstr "行" @@ -2883,6 +2891,9 @@ msgstr "大小" msgid "Size (.ipk)" msgstr "" +msgid "Size of DNS query cache" +msgstr "" + msgid "Skip" msgstr "跳過" @@ -3275,8 +3286,8 @@ msgstr "" msgid "" "This is the local endpoint address assigned by the tunnel broker, it usually " -"ends with :2" -msgstr "這是由通道代理人指定的本地終端位址, 通常用 :2結尾." +"ends with ...:2/64" +msgstr "這是由通道代理人指定的本地終端位址, 通常用 ...:2/64結尾." msgid "" "This is the only DHCP/dev/null 2>/dev/null" % iface) + luci.sys.call("env -i /sbin/ifup %s >/dev/null 2>/dev/null" + % luci.util.shellquote(iface)) luci.http.status(200, "Reconnected") return end @@ -301,7 +302,8 @@ function iface_shutdown(iface) local netmd = require "luci.model.network".init() local net = netmd:get_network(iface) if net then - luci.sys.call("env -i /sbin/ifdown %q >/dev/null 2>/dev/null" % iface) + luci.sys.call("env -i /sbin/ifdown %s >/dev/null 2>/dev/null" + % luci.util.shellquote(iface)) luci.http.status(200, "Shutdown") return end @@ -313,7 +315,8 @@ function iface_delete(iface) local netmd = require "luci.model.network".init() local net = netmd:del_network(iface) if net then - luci.sys.call("env -i /sbin/ifdown %q >/dev/null 2>/dev/null" % iface) + luci.sys.call("env -i /sbin/ifdown %s >/dev/null 2>/dev/null" + % luci.util.shellquote(iface)) luci.http.redirect(luci.dispatcher.build_url("admin/network/network")) netmd:commit("network") netmd:commit("wireless") @@ -389,7 +392,7 @@ function diag_command(cmd, addr) if addr and addr:match("^[a-zA-Z0-9%-%.:_]+$") then luci.http.prepare_content("text/plain") - local util = io.popen(cmd % addr) + local util = io.popen(cmd % luci.util.shellquote(addr)) if util then while true do local ln = util:read("*l") @@ -408,21 +411,21 @@ function diag_command(cmd, addr) end function diag_ping(addr) - diag_command("ping -c 5 -W 1 %q 2>&1", addr) + diag_command("ping -c 5 -W 1 %s 2>&1", addr) end function diag_traceroute(addr) - diag_command("traceroute -q 1 -w 1 -n %q 2>&1", addr) + diag_command("traceroute -q 1 -w 1 -n %s 2>&1", addr) end function diag_nslookup(addr) - diag_command("nslookup %q 2>&1", addr) + diag_command("nslookup %s 2>&1", addr) end function diag_ping6(addr) - diag_command("ping6 -c 5 %q 2>&1", addr) + diag_command("ping6 -c 5 %s 2>&1", addr) end function diag_traceroute6(addr) - diag_command("traceroute6 -q 1 -w 2 -n %q 2>&1", addr) + diag_command("traceroute6 -q 1 -w 2 -n %s 2>&1", addr) end diff --git a/modules/luci-mod-admin-full/luasrc/controller/admin/status.lua b/modules/luci-mod-admin-full/luasrc/controller/admin/status.lua index 22e1b7e17..4471fd597 100644 --- a/modules/luci-mod-admin-full/luasrc/controller/admin/status.lua +++ b/modules/luci-mod-admin-full/luasrc/controller/admin/status.lua @@ -14,7 +14,7 @@ function index() entry({"admin", "status", "routes"}, template("admin_status/routes"), _("Routes"), 3) entry({"admin", "status", "syslog"}, call("action_syslog"), _("System Log"), 4) entry({"admin", "status", "dmesg"}, call("action_dmesg"), _("Kernel Log"), 5) - entry({"admin", "status", "processes"}, cbi("admin_status/processes"), _("Processes"), 6) + entry({"admin", "status", "processes"}, form("admin_status/processes"), _("Processes"), 6) entry({"admin", "status", "realtime"}, alias("admin", "status", "realtime", "load"), _("Realtime Graphs"), 7) @@ -62,7 +62,9 @@ end function action_bandwidth(iface) luci.http.prepare_content("application/json") - local bwc = io.popen("luci-bwc -i %q 2>/dev/null" % iface) + local bwc = io.popen("luci-bwc -i %s 2>/dev/null" + % luci.util.shellquote(iface)) + if bwc then luci.http.write("[") @@ -80,7 +82,9 @@ end function action_wireless(iface) luci.http.prepare_content("application/json") - local bwc = io.popen("luci-bwc -r %q 2>/dev/null" % iface) + local bwc = io.popen("luci-bwc -r %s 2>/dev/null" + % luci.util.shellquote(iface)) + if bwc then luci.http.write("[") diff --git a/modules/luci-mod-admin-full/luasrc/controller/admin/uci.lua b/modules/luci-mod-admin-full/luasrc/controller/admin/uci.lua index 9c33d9c18..ba317f9f4 100644 --- a/modules/luci-mod-admin-full/luasrc/controller/admin/uci.lua +++ b/modules/luci-mod-admin-full/luasrc/controller/admin/uci.lua @@ -5,8 +5,8 @@ module("luci.controller.admin.uci", package.seeall) function index() - local redir = luci.http.formvalue("redir", true) or - luci.dispatcher.build_url(unpack(luci.dispatcher.context.request)) + local redir = luci.http.formvalue("redir", true) + or table.concat(luci.dispatcher.context.request, "/") entry({"admin", "uci"}, nil, _("Configuration")) entry({"admin", "uci", "changes"}, call("action_changes"), _("Changes"), 40).query = {redir=redir} diff --git a/modules/luci-mod-admin-full/luasrc/model/cbi/admin_network/dhcp.lua b/modules/luci-mod-admin-full/luasrc/model/cbi/admin_network/dhcp.lua index 66d9942a1..fbde431df 100644 --- a/modules/luci-mod-admin-full/luasrc/model/cbi/admin_network/dhcp.lua +++ b/modules/luci-mod-admin-full/luasrc/model/cbi/admin_network/dhcp.lua @@ -115,7 +115,7 @@ s:taboption("advanced", Flag, "nonegcache", s:taboption("advanced", Value, "serversfile", translate("Additional servers file"), translate("This file may contain lines like 'server=/domain/1.2.3.4' or 'server=1.2.3.4' for".. - "domain-specific or full upstream DNS servers.")) + "domain-specific or full upstream DNS servers.")) s:taboption("advanced", Flag, "strictorder", translate("Strict order"), @@ -212,6 +212,12 @@ cq.optional = true cq.datatype = "uinteger" cq.placeholder = 150 +cs = s:taboption("advanced", Value, "cachesize", + translate("Size of DNS query cache"), + translate("Number of cached DNS entries (max is 10000, 0 is no caching)")) +cs.optional = true +cs.datatype = "range(0,10000)" +cs.placeholder = 150 s:taboption("tftp", Flag, "enable_tftp", translate("Enable TFTP server")).optional = true @@ -274,7 +280,7 @@ s.anonymous = true s.template = "cbi/tblsection" name = s:option(Value, "name", translate("Hostname")) -name.datatype = "hostname" +name.datatype = "hostname('strict')" name.rmempty = true function name.write(self, section, value) @@ -295,7 +301,7 @@ ip = s:option(Value, "ip", translate("DUID")) duid.datatype = "and(rangelength(20,36),hexstring)" diff --git a/modules/luci-mod-admin-full/luasrc/model/cbi/admin_network/vlan.lua b/modules/luci-mod-admin-full/luasrc/model/cbi/admin_network/vlan.lua index 89a73a5ca..b52dff13a 100644 --- a/modules/luci-mod-admin-full/luasrc/model/cbi/admin_network/vlan.lua +++ b/modules/luci-mod-admin-full/luasrc/model/cbi/admin_network/vlan.lua @@ -5,6 +5,7 @@ m = Map("network", translate("Switch"), translate("The network ports on this device can be combined to several VLANs in which computers can communicate directly with each other. VLANs are often used to separate different network segments. Often there is by default one Uplink port for a connection to the next greater network like the internet and other ports for a local network.")) local fs = require "nixio.fs" +local ut = require "luci.util" local nw = require "luci.model.network" local switches = { } @@ -74,7 +75,7 @@ m.uci:foreach("network", "switch", end -- Parse some common switch properties from swconfig help output. - local swc = io.popen("swconfig dev %q help 2>/dev/null" % switch_name) + local swc = io.popen("swconfig dev %s help 2>/dev/null" % ut.shellquote(switch_name)) if swc then local is_port_attr = false diff --git a/modules/luci-mod-admin-full/luasrc/model/cbi/admin_network/wifi.lua b/modules/luci-mod-admin-full/luasrc/model/cbi/admin_network/wifi.lua index c0bb38030..a574d3597 100644 --- a/modules/luci-mod-admin-full/luasrc/model/cbi/admin_network/wifi.lua +++ b/modules/luci-mod-admin-full/luasrc/model/cbi/admin_network/wifi.lua @@ -63,7 +63,7 @@ function m.parse(map) Map.parse(map) if m:get(wdev:name(), "type") == "mac80211" and new_cc and new_cc ~= old_cc then - luci.sys.call("iw reg set %q" % new_cc) + luci.sys.call("iw reg set %s" % ut.shellquote(new_cc)) luci.http.redirect(luci.dispatcher.build_url("admin/network/wireless", arg[1])) return end diff --git a/modules/luci-mod-admin-full/luasrc/view/admin_system/packages.htm b/modules/luci-mod-admin-full/luasrc/view/admin_system/packages.htm index d5d78289b..88e0fffd9 100644 --- a/modules/luci-mod-admin-full/luasrc/view/admin_system/packages.htm +++ b/modules/luci-mod-admin-full/luasrc/view/admin_system/packages.htm @@ -69,7 +69,7 @@ end <% if querypat then %>
    <%:Displaying only packages containing%> "<%=pcdata(query)%>" - +
    <% end %> diff --git a/modules/luci-mod-admin-full/luasrc/view/admin_uci/changes.htm b/modules/luci-mod-admin-full/luasrc/view/admin_uci/changes.htm index c3373604f..6e725c888 100644 --- a/modules/luci-mod-admin-full/luasrc/view/admin_uci/changes.htm +++ b/modules/luci-mod-admin-full/luasrc/view/admin_uci/changes.htm @@ -16,9 +16,9 @@ <% end %>
    - <% local r = luci.http.formvalue("redir"); if r and #r > 0 then %> + <% local node, url = luci.dispatcher.lookup(luci.http.formvalue("redir")); if url then %>
    - +
    diff --git a/modules/luci-mod-admin-full/luasrc/view/admin_uci/revert.htm b/modules/luci-mod-admin-full/luasrc/view/admin_uci/revert.htm index 5da7281a8..20327adff 100644 --- a/modules/luci-mod-admin-full/luasrc/view/admin_uci/revert.htm +++ b/modules/luci-mod-admin-full/luasrc/view/admin_uci/revert.htm @@ -18,10 +18,12 @@

    <%:There are no pending changes to revert!%>

    <% end %> -
    -
    "> - -
    -
    +<% local node, url = luci.dispatcher.lookup(luci.http.formvalue("redir")); if url then %> +
    +
    + +
    +
    +<% end %> <%+footer%> diff --git a/modules/luci-mod-freifunk/htdocs/luci-static/resources/OSMLatLon.htm b/modules/luci-mod-freifunk/htdocs/luci-static/resources/OSMLatLon.htm index 18be30be3..9f017c9e7 100644 --- a/modules/luci-mod-freifunk/htdocs/luci-static/resources/OSMLatLon.htm +++ b/modules/luci-mod-freifunk/htdocs/luci-static/resources/OSMLatLon.htm @@ -6,7 +6,7 @@ - +
    Map by openstreetmap.org, License CC-BY-SA @@ -16,5 +16,4 @@ Longitude:
    - diff --git a/modules/luci-mod-freifunk/luasrc/controller/freifunk/freifunk.lua b/modules/luci-mod-freifunk/luasrc/controller/freifunk/freifunk.lua index e2291e5ca..adad7508b 100644 --- a/modules/luci-mod-freifunk/luasrc/controller/freifunk/freifunk.lua +++ b/modules/luci-mod-freifunk/luasrc/controller/freifunk/freifunk.lua @@ -77,7 +77,7 @@ function index() page.order = 10 page = node("admin", "freifunk", "basics", "profile_expert") - page.target = cbi("freifunk/profile_expert") + page.target = form("freifunk/profile_expert") page.title = _("Profile (Expert)") page.order = 20 diff --git a/modules/luci-mod-rpc/luasrc/controller/rpc.lua b/modules/luci-mod-rpc/luasrc/controller/rpc.lua index 759bb749c..3326d57a9 100644 --- a/modules/luci-mod-rpc/luasrc/controller/rpc.lua +++ b/modules/luci-mod-rpc/luasrc/controller/rpc.lua @@ -7,23 +7,45 @@ local pairs = pairs local print = print local pcall = pcall local table = table +local type = type +local tonumber = tonumber module "luci.controller.rpc" -function index() - local function authenticator(validator, accs) - local auth = luci.http.formvalue("auth", true) - if auth then -- if authentication token was given - local sdat = (luci.util.ubus("session", "get", { ubus_rpc_session = auth }) or { }).values - if sdat then -- if given token is valid - if sdat.user and luci.util.contains(accs, sdat.user) then - return sdat.user, auth - end - end + +local function session_retrieve(sid, allowed_users) + local util = require "luci.util" + local sdat = util.ubus("session", "get", { + ubus_rpc_session = sid + }) + + if type(sdat) == "table" and + type(sdat.values) == "table" and + type(sdat.values.token) == "string" and + type(sdat.values.secret) == "string" and + type(sdat.values.username) == "string" and + util.contains(allowed_users, sdat.values.username) + then + return sid, sdat.values + end + + return nil +end + +local function authenticator(validator, accs) + local auth = luci.http.formvalue("auth", true) + or luci.http.getcookie("sysauth") + + if auth then -- if authentication token was given + local sid, sdat = session_retrieve(auth, accs) + if sdat then -- if given token is valid + return sdat.username, sid end luci.http.status(403, "Forbidden") end +end +function index() local rpc = node("rpc") rpc.sysauth = "root" rpc.sysauth_authenticator = authenticator @@ -43,39 +65,48 @@ function rpc_auth() local ltn12 = require "luci.ltn12" local util = require "luci.util" - local loginstat - local server = {} server.challenge = function(user, pass) - local sid, token, secret - local config = require "luci.config" - - if sys.user.checkpasswd(user, pass) then - local sdat = util.ubus("session", "create", { timeout = config.sauth.sessiontime }) + local login = util.ubus("session", "login", { + username = user, + password = pass, + timeout = tonumber(config.sauth.sessiontime) + }) + + if type(login) == "table" and + type(login.ubus_rpc_session) == "string" + then + util.ubus("session", "set", { + ubus_rpc_session = login.ubus_rpc_session, + values = { + token = sys.uniqueid(16), + secret = sys.uniqueid(16) + } + }) + + local sid, sdat = session_retrieve(login.ubus_rpc_session, { user }) if sdat then - sid = sdat.ubus_rpc_session - token = sys.uniqueid(16) - secret = sys.uniqueid(16) - - http.header("Set-Cookie", "sysauth="..sid.."; path=/") - util.ubus("session", "set", { - ubus_rpc_session = sid, - values = { - user = user, - token = token, - secret = secret - } - }) + return { + sid = sid, + token = sdat.token, + secret = sdat.secret + } end end - return sid and {sid=sid, token=token, secret=secret} + return nil end server.login = function(...) local challenge = server.challenge(...) - return challenge and challenge.sid + if challenge then + http.header("Set-Cookie", 'sysauth=%s; path=%s' %{ + challenge.sid, + http.getenv("SCRIPT_NAME") + }) + return challenge.sid + end end http.prepare_content("application/json") diff --git a/protocols/luci-proto-ipv6/luasrc/model/cbi/admin_network/proto_6in4.lua b/protocols/luci-proto-ipv6/luasrc/model/cbi/admin_network/proto_6in4.lua index 88dfe0928..16245b80e 100644 --- a/protocols/luci-proto-ipv6/luasrc/model/cbi/admin_network/proto_6in4.lua +++ b/protocols/luci-proto-ipv6/luasrc/model/cbi/admin_network/proto_6in4.lua @@ -24,7 +24,7 @@ peeraddr.datatype = "ip4addr" ip6addr = s:taboption("general", Value, "ip6addr", translate("Local IPv6 address"), - translate("This is the local endpoint address assigned by the tunnel broker, it usually ends with :2")) + translate("This is the local endpoint address assigned by the tunnel broker, it usually ends with ...:2/64")) ip6addr.datatype = "ip6addr" diff --git a/themes/luci-theme-bootstrap/luasrc/view/themes/bootstrap/header.htm b/themes/luci-theme-bootstrap/luasrc/view/themes/bootstrap/header.htm index 78b98e035..4881535ac 100644 --- a/themes/luci-theme-bootstrap/luasrc/view/themes/bootstrap/header.htm +++ b/themes/luci-theme-bootstrap/luasrc/view/themes/bootstrap/header.htm @@ -145,9 +145,9 @@ end if ucichanges > 0 then - write('%s: %d' %{ + write('%s: %d' %{ url(category, 'uci/changes'), - http.urlencode(http.formvalue('redir') or REQUEST_URI), + http.urlencode(http.formvalue('redir') or table.concat(disp.context.request, "/")), translate('Unsaved Changes'), ucichanges }) diff --git a/themes/luci-theme-freifunk-generic/luasrc/view/themes/freifunk-generic/header.htm b/themes/luci-theme-freifunk-generic/luasrc/view/themes/freifunk-generic/header.htm index 342a9d408..16ffc992a 100644 --- a/themes/luci-theme-freifunk-generic/luasrc/view/themes/freifunk-generic/header.htm +++ b/themes/luci-theme-freifunk-generic/luasrc/view/themes/freifunk-generic/header.htm @@ -205,7 +205,7 @@ if tree.nodes[category] and tree.nodes[category].ucidata then -%> <% end %> diff --git a/themes/luci-theme-material/htdocs/luci-static/material/css/style.css b/themes/luci-theme-material/htdocs/luci-static/material/css/style.css index 545c5fb3f..57bbaf6af 100755 --- a/themes/luci-theme-material/htdocs/luci-static/material/css/style.css +++ b/themes/luci-theme-material/htdocs/luci-static/material/css/style.css @@ -253,9 +253,19 @@ header > .container > .brand { vertical-align: text-bottom; } +.danger { + background-color: #FA8072 !important; + color: black; +} + .warning { - background-color: #FF7D60 !important; - color: #FFF; + background-color: #F0E68C !important; + color: black; +} + +.success { + background-color: #90EE90 !important; + color: black; } .errorbox, @@ -1546,4 +1556,4 @@ body.lang_pl.node-main-login .cbi-value-title { .cbi-value-field .cbi-input-select { min-width: 25rem; } -} \ No newline at end of file +} diff --git a/themes/luci-theme-material/luasrc/view/themes/material/header.htm b/themes/luci-theme-material/luasrc/view/themes/material/header.htm index d84fd278a..0aca882c0 100644 --- a/themes/luci-theme-material/luasrc/view/themes/material/header.htm +++ b/themes/luci-theme-material/luasrc/view/themes/material/header.htm @@ -170,9 +170,9 @@ end if ucichanges > 0 then - write('%s: %d' %{ + write('%s: %d' %{ url(category, 'uci/changes'), - http.urlencode(http.formvalue('redir') or REQUEST_URI), + http.urlencode(http.formvalue('redir') or table.concat(disp.context.request, "/")), translate('Unsaved Changes'), ucichanges }) diff --git a/themes/luci-theme-openwrt/luasrc/view/themes/openwrt.org/header.htm b/themes/luci-theme-openwrt/luasrc/view/themes/openwrt.org/header.htm index ae348f385..a560014d3 100644 --- a/themes/luci-theme-openwrt/luasrc/view/themes/openwrt.org/header.htm +++ b/themes/luci-theme-openwrt/luasrc/view/themes/openwrt.org/header.htm @@ -99,22 +99,14 @@ end end - write('
    ') - if ucic > 0 then - write('%s: %d' %{ + write('' %{ url(category, 'uci/changes'), - http.urlencode(http.formvalue('redir') or REQUEST_URI), + http.urlencode(http.formvalue('redir') or table.concat(disp.context.request, "/")), translate('Unsaved Changes'), ucic }) - else - write('%s: 0' %{ - translate('Unsaved Changes') - }) end - - write('
    ') end end -%>