mirror of
https://github.com/gSpotx2f/luci-app-internet-detector.git
synced 2025-12-06 11:36:49 +03:00
v1.7. New optional checking feature: URL test.
This commit is contained in:
39
README.md
39
README.md
@@ -3,7 +3,8 @@ Internet-detector is an application for checking the availability of the Interne
|
|||||||
|
|
||||||
**Features:**
|
**Features:**
|
||||||
- It can run continuously as a system service or only in an open web interface.
|
- It can run continuously as a system service or only in an open web interface.
|
||||||
- Checking the availability of a host using ping or by connecting via TCP to a specified port.
|
- Checking the availability of a host using ping (L3) or by connecting via TCP to a specified port (L4).
|
||||||
|
- Testing URL accessibility via HTTP (L7) (curl).
|
||||||
- LED indication of Internet availability.
|
- LED indication of Internet availability.
|
||||||

|

|
||||||
- Performing actions when connecting and disconnecting the Internet: rebooting device, restarting network or modem (internet-detector-mod-modem-restart), executing custom shell scripts.
|
- Performing actions when connecting and disconnecting the Internet: rebooting device, restarting network or modem (internet-detector-mod-modem-restart), executing custom shell scripts.
|
||||||
@@ -20,22 +21,22 @@ Internet-detector is an application for checking the availability of the Interne
|
|||||||
## Installation notes:
|
## Installation notes:
|
||||||
|
|
||||||
opkg update
|
opkg update
|
||||||
wget --no-check-certificate -O /tmp/internet-detector_1.6.7-r1_all.ipk https://github.com/gSpotx2f/packages-openwrt/raw/master/current/internet-detector_1.6.7-r1_all.ipk
|
wget --no-check-certificate -O /tmp/internet-detector_1.7.0-r1_all.ipk https://github.com/gSpotx2f/packages-openwrt/raw/master/current/internet-detector_1.7.0-r1_all.ipk
|
||||||
opkg install /tmp/internet-detector_1.6.7-r1_all.ipk
|
opkg install /tmp/internet-detector_1.7.0-r1_all.ipk
|
||||||
rm /tmp/internet-detector_1.6.7-r1_all.ipk
|
rm /tmp/internet-detector_1.7.0-r1_all.ipk
|
||||||
service internet-detector start
|
service internet-detector start
|
||||||
service internet-detector enable
|
service internet-detector enable
|
||||||
|
|
||||||
wget --no-check-certificate -O /tmp/luci-app-internet-detector_1.6.7-r1_all.ipk https://github.com/gSpotx2f/packages-openwrt/raw/master/current/luci-app-internet-detector_1.6.7-r1_all.ipk
|
wget --no-check-certificate -O /tmp/luci-app-internet-detector_1.7.0-r1_all.ipk https://github.com/gSpotx2f/packages-openwrt/raw/master/current/luci-app-internet-detector_1.7.0-r1_all.ipk
|
||||||
opkg install /tmp/luci-app-internet-detector_1.6.7-r1_all.ipk
|
opkg install /tmp/luci-app-internet-detector_1.7.0-r1_all.ipk
|
||||||
rm /tmp/luci-app-internet-detector_1.6.7-r1_all.ipk
|
rm /tmp/luci-app-internet-detector_1.7.0-r1_all.ipk
|
||||||
service rpcd restart
|
service rpcd restart
|
||||||
|
|
||||||
i18n-ru:
|
i18n-ru:
|
||||||
|
|
||||||
wget --no-check-certificate -O /tmp/luci-i18n-internet-detector-ru_1.6.7-r1_all.ipk https://github.com/gSpotx2f/packages-openwrt/raw/master/current/luci-i18n-internet-detector-ru_1.6.7-r1_all.ipk
|
wget --no-check-certificate -O /tmp/luci-i18n-internet-detector-ru_1.7.0-r1_all.ipk https://github.com/gSpotx2f/packages-openwrt/raw/master/current/luci-i18n-internet-detector-ru_1.7.0-r1_all.ipk
|
||||||
opkg install /tmp/luci-i18n-internet-detector-ru_1.6.7-r1_all.ipk
|
opkg install /tmp/luci-i18n-internet-detector-ru_1.7.0-r1_all.ipk
|
||||||
rm /tmp/luci-i18n-internet-detector-ru_1.6.7-r1_all.ipk
|
rm /tmp/luci-i18n-internet-detector-ru_1.7.0-r1_all.ipk
|
||||||
|
|
||||||
## Screenshots:
|
## Screenshots:
|
||||||
|
|
||||||
@@ -47,9 +48,9 @@ i18n-ru:
|
|||||||
|
|
||||||
**Dependences:** modemmanager.
|
**Dependences:** modemmanager.
|
||||||
|
|
||||||
wget --no-check-certificate -O /tmp/internet-detector-mod-modem-restart_1.6.7-r1_all.ipk https://github.com/gSpotx2f/packages-openwrt/raw/master/current/internet-detector-mod-modem-restart_1.6.7-r1_all.ipk
|
wget --no-check-certificate -O /tmp/internet-detector-mod-modem-restart_1.7.0-r1_all.ipk https://github.com/gSpotx2f/packages-openwrt/raw/master/current/internet-detector-mod-modem-restart_1.7.0-r1_all.ipk
|
||||||
opkg install /tmp/internet-detector-mod-modem-restart_1.6.7-r1_all.ipk
|
opkg install /tmp/internet-detector-mod-modem-restart_1.7.0-r1_all.ipk
|
||||||
rm /tmp/internet-detector-mod-modem-restart_1.6.7-r1_all.ipk
|
rm /tmp/internet-detector-mod-modem-restart_1.7.0-r1_all.ipk
|
||||||
service internet-detector restart
|
service internet-detector restart
|
||||||
|
|
||||||

|

|
||||||
@@ -58,9 +59,9 @@ i18n-ru:
|
|||||||
|
|
||||||
**Dependences:** mailsend.
|
**Dependences:** mailsend.
|
||||||
|
|
||||||
wget --no-check-certificate -O /tmp/internet-detector-mod-email_1.6.7-r1_all.ipk https://github.com/gSpotx2f/packages-openwrt/raw/master/current/internet-detector-mod-email_1.6.7-r1_all.ipk
|
wget --no-check-certificate -O /tmp/internet-detector-mod-email_1.7.0-r1_all.ipk https://github.com/gSpotx2f/packages-openwrt/raw/master/current/internet-detector-mod-email_1.7.0-r1_all.ipk
|
||||||
opkg install /tmp/internet-detector-mod-email_1.6.7-r1_all.ipk
|
opkg install /tmp/internet-detector-mod-email_1.7.0-r1_all.ipk
|
||||||
rm /tmp/internet-detector-mod-email_1.6.7-r1_all.ipk
|
rm /tmp/internet-detector-mod-email_1.7.0-r1_all.ipk
|
||||||
service internet-detector restart
|
service internet-detector restart
|
||||||
|
|
||||||

|

|
||||||
@@ -69,9 +70,9 @@ i18n-ru:
|
|||||||
|
|
||||||
**Dependences:** curl.
|
**Dependences:** curl.
|
||||||
|
|
||||||
wget --no-check-certificate -O /tmp/internet-detector-mod-telegram_1.6.7-r1_all.ipk https://github.com/gSpotx2f/packages-openwrt/raw/master/current/internet-detector-mod-telegram_1.6.7-r1_all.ipk
|
wget --no-check-certificate -O /tmp/internet-detector-mod-telegram_1.7.0-r1_all.ipk https://github.com/gSpotx2f/packages-openwrt/raw/master/current/internet-detector-mod-telegram_1.7.0-r1_all.ipk
|
||||||
opkg install /tmp/internet-detector-mod-telegram_1.6.7-r1_all.ipk
|
opkg install /tmp/internet-detector-mod-telegram_1.7.0-r1_all.ipk
|
||||||
rm /tmp/internet-detector-mod-telegram_1.6.7-r1_all.ipk
|
rm /tmp/internet-detector-mod-telegram_1.7.0-r1_all.ipk
|
||||||
service internet-detector restart
|
service internet-detector restart
|
||||||
|
|
||||||

|

|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
include $(TOPDIR)/rules.mk
|
include $(TOPDIR)/rules.mk
|
||||||
|
|
||||||
PKG_NAME:=internet-detector-mod-email
|
PKG_NAME:=internet-detector-mod-email
|
||||||
PKG_VERSION:=1.6.7
|
PKG_VERSION:=1.7.0
|
||||||
PKG_RELEASE:=1
|
PKG_RELEASE:=1
|
||||||
PKG_MAINTAINER:=gSpot <https://github.com/gSpotx2f/luci-app-internet-detector>
|
PKG_MAINTAINER:=gSpot <https://github.com/gSpotx2f/luci-app-internet-detector>
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
include $(TOPDIR)/rules.mk
|
include $(TOPDIR)/rules.mk
|
||||||
|
|
||||||
PKG_NAME:=internet-detector-mod-modem-restart
|
PKG_NAME:=internet-detector-mod-modem-restart
|
||||||
PKG_VERSION:=1.6.7
|
PKG_VERSION:=1.7.0
|
||||||
PKG_RELEASE:=1
|
PKG_RELEASE:=1
|
||||||
PKG_MAINTAINER:=gSpot <https://github.com/gSpotx2f/luci-app-internet-detector>
|
PKG_MAINTAINER:=gSpot <https://github.com/gSpotx2f/luci-app-internet-detector>
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
include $(TOPDIR)/rules.mk
|
include $(TOPDIR)/rules.mk
|
||||||
|
|
||||||
PKG_NAME:=internet-detector-mod-telegram
|
PKG_NAME:=internet-detector-mod-telegram
|
||||||
PKG_VERSION:=1.6.7
|
PKG_VERSION:=1.7.0
|
||||||
PKG_RELEASE:=1
|
PKG_RELEASE:=1
|
||||||
PKG_MAINTAINER:=gSpot <https://github.com/gSpotx2f/luci-app-internet-detector>
|
PKG_MAINTAINER:=gSpot <https://github.com/gSpotx2f/luci-app-internet-detector>
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ local Module = {
|
|||||||
msgSendAttempts = 3,
|
msgSendAttempts = 3,
|
||||||
msgSendTimeout = 5,
|
msgSendTimeout = 5,
|
||||||
curlExec = "/usr/bin/curl",
|
curlExec = "/usr/bin/curl",
|
||||||
curlParams = "-s",
|
curlParams = "-s --no-keepalive",
|
||||||
status = nil,
|
status = nil,
|
||||||
_enabled = false,
|
_enabled = false,
|
||||||
_deadCounter = 0,
|
_deadCounter = 0,
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
include $(TOPDIR)/rules.mk
|
include $(TOPDIR)/rules.mk
|
||||||
|
|
||||||
PKG_NAME:=internet-detector
|
PKG_NAME:=internet-detector
|
||||||
PKG_VERSION:=1.6.7
|
PKG_VERSION:=1.7.0
|
||||||
PKG_RELEASE:=1
|
PKG_RELEASE:=1
|
||||||
PKG_MAINTAINER:=gSpot <https://github.com/gSpotx2f/luci-app-internet-detector>
|
PKG_MAINTAINER:=gSpot <https://github.com/gSpotx2f/luci-app-internet-detector>
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ config instance 'internet'
|
|||||||
option description 'Default instance'
|
option description 'Default instance'
|
||||||
list hosts '8.8.8.8'
|
list hosts '8.8.8.8'
|
||||||
list hosts '1.1.1.1'
|
list hosts '1.1.1.1'
|
||||||
|
list urls 'https://www.google.com'
|
||||||
option check_type '0'
|
option check_type '0'
|
||||||
option tcp_port '53'
|
option tcp_port '53'
|
||||||
option interval_up '30'
|
option interval_up '30'
|
||||||
|
|||||||
@@ -12,32 +12,8 @@ local uci = require("uci")
|
|||||||
-- Default settings
|
-- Default settings
|
||||||
|
|
||||||
local InternetDetector = {
|
local InternetDetector = {
|
||||||
mode = 0, -- 0: disabled, 1: Service, 2: UI detector
|
|
||||||
loggingLevel = 6,
|
|
||||||
hostname = "OpenWrt",
|
|
||||||
appName = "internet-detector",
|
appName = "internet-detector",
|
||||||
libDir = "/usr/lib/lua",
|
libDir = "/usr/lib/lua",
|
||||||
pingCmd = "/bin/ping",
|
|
||||||
pingParams = "-c 1",
|
|
||||||
uiRunTime = 30,
|
|
||||||
noModules = false,
|
|
||||||
uiAvailModules = { mod_public_ip = true },
|
|
||||||
debug = false,
|
|
||||||
serviceConfig = {
|
|
||||||
hosts = {
|
|
||||||
[1] = "8.8.8.8",
|
|
||||||
[2] = "1.1.1.1",
|
|
||||||
},
|
|
||||||
check_type = 0, -- 0: TCP, 1: ICMP
|
|
||||||
tcp_port = 53,
|
|
||||||
icmp_packet_size = 56,
|
|
||||||
interval_up = 30,
|
|
||||||
interval_down = 5,
|
|
||||||
connection_attempts = 2,
|
|
||||||
connection_timeout = 2,
|
|
||||||
iface = nil,
|
|
||||||
instance = nil,
|
|
||||||
},
|
|
||||||
logLevels = {
|
logLevels = {
|
||||||
emerg = { level = syslog.LOG_EMERG, num = 0 },
|
emerg = { level = syslog.LOG_EMERG, num = 0 },
|
||||||
alert = { level = syslog.LOG_ALERT, num = 1 },
|
alert = { level = syslog.LOG_ALERT, num = 1 },
|
||||||
@@ -48,8 +24,41 @@ local InternetDetector = {
|
|||||||
info = { level = syslog.LOG_INFO, num = 6 },
|
info = { level = syslog.LOG_INFO, num = 6 },
|
||||||
debug = { level = syslog.LOG_DEBUG, num = 7 },
|
debug = { level = syslog.LOG_DEBUG, num = 7 },
|
||||||
},
|
},
|
||||||
|
pingCmd = "/bin/ping",
|
||||||
|
pingParams = "-c 1",
|
||||||
|
curlExec = "/usr/bin/curl",
|
||||||
|
curlParams = '-s --no-keepalive --head --user-agent "Mozilla/5.0 (X11; Linux x86_64; rv:142.0) Gecko/20100101 Firefox/142.0"',
|
||||||
|
mode = 0, -- 0: disabled, 1: Service, 2: UI detector
|
||||||
|
loggingLevel = 6,
|
||||||
|
hostname = "OpenWrt",
|
||||||
|
uiRunTime = 30,
|
||||||
|
noModules = false,
|
||||||
|
uiAvailModules = { mod_public_ip = true },
|
||||||
|
debug = false,
|
||||||
|
serviceConfig = {
|
||||||
|
hosts = {
|
||||||
|
[1] = "8.8.8.8",
|
||||||
|
[2] = "1.1.1.1",
|
||||||
|
},
|
||||||
|
urls = {
|
||||||
|
[1] = "https://www.google.com",
|
||||||
|
},
|
||||||
|
check_type = 0, -- 0: TCP, 1: ICMP
|
||||||
|
tcp_port = 53,
|
||||||
|
icmp_packet_size = 56,
|
||||||
|
interval_up = 30,
|
||||||
|
interval_down = 5,
|
||||||
|
connection_attempts = 2,
|
||||||
|
connection_timeout = 2,
|
||||||
|
proxy_type = nil,
|
||||||
|
proxy_host = nil,
|
||||||
|
proxy_port = nil,
|
||||||
|
iface = nil,
|
||||||
|
instance = nil,
|
||||||
|
},
|
||||||
modules = {},
|
modules = {},
|
||||||
parsedHosts = {},
|
parsedHosts = {},
|
||||||
|
proxyString = "",
|
||||||
uiCounter = 0,
|
uiCounter = 0,
|
||||||
pidFile = nil,
|
pidFile = nil,
|
||||||
statusFile = nil,
|
statusFile = nil,
|
||||||
@@ -213,6 +222,13 @@ function InternetDetector:parseHosts()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function InternetDetector:parseUrls()
|
||||||
|
self.parsedHosts = {}
|
||||||
|
for k, v in ipairs(self.serviceConfig.urls) do
|
||||||
|
self.parsedHosts[k] = { addr = v }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
function InternetDetector:pingHost(host)
|
function InternetDetector:pingHost(host)
|
||||||
local ping = string.format(
|
local ping = string.format(
|
||||||
"%s %s -W %d -s %d%s %s > /dev/null 2>&1",
|
"%s %s -W %d -s %d%s %s > /dev/null 2>&1",
|
||||||
@@ -240,6 +256,7 @@ function InternetDetector:TCPConnectionToHost(host, port)
|
|||||||
"GETADDRINFO ERROR: %s, %s", errMsg, errNum))
|
"GETADDRINFO ERROR: %s, %s", errMsg, errNum))
|
||||||
else
|
else
|
||||||
local family = saTable[1].family
|
local family = saTable[1].family
|
||||||
|
|
||||||
if family then
|
if family then
|
||||||
local sock, errMsg, errNum = socket.socket(family, socket.SOCK_STREAM, 0)
|
local sock, errMsg, errNum = socket.socket(family, socket.SOCK_STREAM, 0)
|
||||||
|
|
||||||
@@ -307,6 +324,60 @@ function InternetDetector:TCPConnectionToHost(host, port)
|
|||||||
return retCode
|
return retCode
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function InternetDetector:httpRequest(url)
|
||||||
|
local retCode = 1, data
|
||||||
|
local curl = string.format(
|
||||||
|
'%s%s%s --connect-timeout %s %s "%s"; printf "\n$?";',
|
||||||
|
self.curlExec,
|
||||||
|
self.serviceConfig.iface and (" --interface " .. self.serviceConfig.iface) or "",
|
||||||
|
self.proxyString,
|
||||||
|
self.serviceConfig.connection_timeout,
|
||||||
|
self.curlParams,
|
||||||
|
url
|
||||||
|
)
|
||||||
|
local fh = io.popen(curl, "r")
|
||||||
|
if fh then
|
||||||
|
data = fh:read("*a")
|
||||||
|
fh:close()
|
||||||
|
if data ~= nil then
|
||||||
|
local s, e = data:find("[0-9]+\n?$")
|
||||||
|
retCode = tonumber(data:sub(s))
|
||||||
|
data = data:sub(0, s - 2)
|
||||||
|
if not data or data == "" then
|
||||||
|
data = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
retCode = 1
|
||||||
|
end
|
||||||
|
|
||||||
|
self:debugOutput(string.format(
|
||||||
|
"--- Curl ---\ntime = %s\n%s\nretCode = %s\ndata = [\n%s]\n",
|
||||||
|
os.time(),
|
||||||
|
curl,
|
||||||
|
retCode,
|
||||||
|
tostring(data)))
|
||||||
|
return retCode, data
|
||||||
|
end
|
||||||
|
|
||||||
|
function InternetDetector:getHTTPCode(data)
|
||||||
|
local httpCode
|
||||||
|
local respHeader = data:match("^HTTP/[^%c]+")
|
||||||
|
if respHeader then
|
||||||
|
httpCode = respHeader:match("%d%d%d")
|
||||||
|
end
|
||||||
|
return tonumber(httpCode)
|
||||||
|
end
|
||||||
|
|
||||||
|
function InternetDetector:checkURL(url)
|
||||||
|
local httpCode
|
||||||
|
local retCode, data = self:httpRequest(url)
|
||||||
|
if retCode == 0 and data then
|
||||||
|
httpCode = self:getHTTPCode(data)
|
||||||
|
end
|
||||||
|
return (httpCode ~= 200) and 1 or 0
|
||||||
|
end
|
||||||
|
|
||||||
function InternetDetector:exit()
|
function InternetDetector:exit()
|
||||||
for _, e in ipairs(self.modules) do
|
for _, e in ipairs(self.modules) do
|
||||||
e:onExit()
|
e:onExit()
|
||||||
@@ -339,7 +410,25 @@ function InternetDetector:mainLoop()
|
|||||||
local checking = false
|
local checking = false
|
||||||
local hostNum = 1
|
local hostNum = 1
|
||||||
local attempt = 1
|
local attempt = 1
|
||||||
local checkFunc = (self.serviceConfig.check_type == 1) and self.pingHost or self.TCPConnectionToHost
|
|
||||||
|
local checkFunc = self.TCPConnectionToHost
|
||||||
|
if self.serviceConfig.check_type == 1 then
|
||||||
|
checkFunc = self.pingHost
|
||||||
|
self:parseHosts()
|
||||||
|
elseif self.serviceConfig.check_type == 2 then
|
||||||
|
checkFunc = self.checkURL
|
||||||
|
self:parseUrls()
|
||||||
|
if (self.serviceConfig.proxy_type and self.serviceConfig.proxy_host and
|
||||||
|
self.serviceConfig.proxy_port) then
|
||||||
|
self.proxyString = string.format(
|
||||||
|
" --proxy %s://%s:%d",
|
||||||
|
self.serviceConfig.proxy_type,
|
||||||
|
self.serviceConfig.proxy_host,
|
||||||
|
self.serviceConfig.proxy_port)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
self:parseHosts()
|
||||||
|
end
|
||||||
|
|
||||||
self:writeValueToFile(
|
self:writeValueToFile(
|
||||||
self.statusFile, self:statusJson(currentStatus, self.serviceConfig.instance))
|
self.statusFile, self:statusJson(currentStatus, self.serviceConfig.instance))
|
||||||
@@ -599,6 +688,11 @@ function InternetDetector:preRun()
|
|||||||
os.exit(1)
|
os.exit(1)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
if self.serviceConfig.check_type == 2 and not unistd.access(self.curlExec, "x") then
|
||||||
|
io.stderr:write(string.format(
|
||||||
|
"Error, %s is not available. You need to install curl.\n", self.curlExec))
|
||||||
|
os.exit(1)
|
||||||
|
end
|
||||||
local ok, commonDir = pcall(dirent.files, self.commonDir)
|
local ok, commonDir = pcall(dirent.files, self.commonDir)
|
||||||
if ok then
|
if ok then
|
||||||
local instancePattern = "^" .. self.appNamePattern .. "%." .. self.serviceConfig.instance .. "%.[%d]+%.pid$"
|
local instancePattern = "^" .. self.appNamePattern .. "%." .. self.serviceConfig.instance .. "%.[%d]+%.pid$"
|
||||||
@@ -689,7 +783,6 @@ end
|
|||||||
|
|
||||||
function InternetDetector:setServiceConfig(instance)
|
function InternetDetector:setServiceConfig(instance)
|
||||||
if self:loadInstanceConfig(instance) then
|
if self:loadInstanceConfig(instance) then
|
||||||
self:parseHosts()
|
|
||||||
if self.mode == 2 then
|
if self.mode == 2 then
|
||||||
self.loggingLevel = 0
|
self.loggingLevel = 0
|
||||||
self.noModules = true
|
self.noModules = true
|
||||||
|
|||||||
@@ -11,6 +11,9 @@ local Module = {
|
|||||||
debug = false,
|
debug = false,
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
iface = nil,
|
iface = nil,
|
||||||
|
proxy_type = nil,
|
||||||
|
proxy_host = nil,
|
||||||
|
proxy_port = nil,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
syslog = function(level, msg) return true end,
|
syslog = function(level, msg) return true end,
|
||||||
@@ -24,7 +27,7 @@ local Module = {
|
|||||||
requestAttempts = 2,
|
requestAttempts = 2,
|
||||||
timeout = 3,
|
timeout = 3,
|
||||||
curlExec = "/usr/bin/curl",
|
curlExec = "/usr/bin/curl",
|
||||||
curlParams = "-s",
|
curlParams = '-s --no-keepalive --user-agent "Mozilla/5.0 (X11; Linux x86_64; rv:142.0) Gecko/20100101 Firefox/142.0"',
|
||||||
providers = {
|
providers = {
|
||||||
opendns1 = {
|
opendns1 = {
|
||||||
name = "opendns1", type = "dns", host = "myip.opendns.com",
|
name = "opendns1", type = "dns", host = "myip.opendns.com",
|
||||||
@@ -88,6 +91,7 @@ local Module = {
|
|||||||
ipScript = "",
|
ipScript = "",
|
||||||
enableIpScript = false,
|
enableIpScript = false,
|
||||||
status = nil,
|
status = nil,
|
||||||
|
_proxyString = "",
|
||||||
_provider = nil,
|
_provider = nil,
|
||||||
_qtype = false,
|
_qtype = false,
|
||||||
_currentIp = nil,
|
_currentIp = nil,
|
||||||
@@ -177,6 +181,7 @@ function Module:sendUDPMessage(message, server, port)
|
|||||||
"GETADDRINFO ERROR: %s, %s", errMsg, errNum))
|
"GETADDRINFO ERROR: %s, %s", errMsg, errNum))
|
||||||
else
|
else
|
||||||
local family = saTable[1].family
|
local family = saTable[1].family
|
||||||
|
|
||||||
if family then
|
if family then
|
||||||
local sock, errMsg, errNum = socket.socket(family, socket.SOCK_DGRAM, 0)
|
local sock, errMsg, errNum = socket.socket(family, socket.SOCK_DGRAM, 0)
|
||||||
|
|
||||||
@@ -266,12 +271,13 @@ function Module:decodeMessage(message)
|
|||||||
local NSCOUNT = message:sub(17, 20)
|
local NSCOUNT = message:sub(17, 20)
|
||||||
local ARCOUNT = message:sub(21, 24)
|
local ARCOUNT = message:sub(21, 24)
|
||||||
|
|
||||||
|
-- Question section
|
||||||
local questionSectionStarts = 25
|
local questionSectionStarts = 25
|
||||||
|
|
||||||
local questionParts = self:parseParts(message, questionSectionStarts, {})
|
local questionParts = self:parseParts(message, questionSectionStarts, {})
|
||||||
local qtypeStarts = questionSectionStarts + (#table.concat(questionParts)) + (#questionParts * 2) + 1
|
local qtypeStarts = questionSectionStarts + (#table.concat(questionParts)) + (#questionParts * 2) + 1
|
||||||
local qclassStarts = qtypeStarts + 4
|
local qclassStarts = qtypeStarts + 4
|
||||||
|
|
||||||
|
-- Answer section
|
||||||
local answerSectionStarts = qclassStarts + 4
|
local answerSectionStarts = qclassStarts + 4
|
||||||
local numAnswers = math.max(
|
local numAnswers = math.max(
|
||||||
tonumber(ANCOUNT, 16), tonumber(NSCOUNT, 16), tonumber(ARCOUNT, 16))
|
tonumber(ANCOUNT, 16), tonumber(NSCOUNT, 16), tonumber(ARCOUNT, 16))
|
||||||
@@ -351,9 +357,10 @@ end
|
|||||||
function Module:httpRequest(url)
|
function Module:httpRequest(url)
|
||||||
local retCode = 1, data
|
local retCode = 1, data
|
||||||
local curl = string.format(
|
local curl = string.format(
|
||||||
'%s%s --connect-timeout %s %s "%s"; printf "\n$?";',
|
'%s%s%s --connect-timeout %s %s "%s"; printf "\n$?";',
|
||||||
self.curlExec,
|
self.curlExec,
|
||||||
self.config.serviceConfig.iface and (" --interface " .. self.config.serviceConfig.iface) or "",
|
self.config.serviceConfig.iface and (" --interface " .. self.config.serviceConfig.iface) or "",
|
||||||
|
self._proxyString,
|
||||||
self.timeout,
|
self.timeout,
|
||||||
self.curlParams,
|
self.curlParams,
|
||||||
url
|
url
|
||||||
@@ -373,6 +380,14 @@ function Module:httpRequest(url)
|
|||||||
else
|
else
|
||||||
retCode = 1
|
retCode = 1
|
||||||
end
|
end
|
||||||
|
|
||||||
|
self.debugOutput(string.format(
|
||||||
|
"--- Curl ---\ntime = %s\n%s\nretCode = %s\ndata = [\n%s]\n",
|
||||||
|
os.time(),
|
||||||
|
curl,
|
||||||
|
retCode,
|
||||||
|
tostring(data))
|
||||||
|
)
|
||||||
return retCode, data
|
return retCode, data
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -454,6 +469,15 @@ function Module:init(t)
|
|||||||
self._enabled = false
|
self._enabled = false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
if (self.config.serviceConfig.proxy_type and
|
||||||
|
self.config.serviceConfig.proxy_host and
|
||||||
|
self.config.serviceConfig.proxy_port) then
|
||||||
|
self._proxyString = string.format(
|
||||||
|
" --proxy %s://%s:%d",
|
||||||
|
self.config.serviceConfig.proxy_type,
|
||||||
|
self.config.serviceConfig.proxy_host,
|
||||||
|
self.config.serviceConfig.proxy_port)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function Module:run(currentStatus, lastStatus, timeDiff, timeNow, inetChecked)
|
function Module:run(currentStatus, lastStatus, timeDiff, timeNow, inetChecked)
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
include $(TOPDIR)/rules.mk
|
include $(TOPDIR)/rules.mk
|
||||||
|
|
||||||
PKG_NAME:=luci-app-internet-detector
|
PKG_NAME:=luci-app-internet-detector
|
||||||
PKG_VERSION:=1.6.7
|
PKG_VERSION:=1.7.0
|
||||||
PKG_RELEASE:=1
|
PKG_RELEASE:=1
|
||||||
LUCI_TITLE:=LuCI support for internet-detector
|
LUCI_TITLE:=LuCI support for internet-detector
|
||||||
LUCI_DEPENDS:=+internet-detector
|
LUCI_DEPENDS:=+internet-detector
|
||||||
|
|||||||
@@ -173,9 +173,29 @@ return view.extend({
|
|||||||
initButton : null,
|
initButton : null,
|
||||||
currentAppMode : '0',
|
currentAppMode : '0',
|
||||||
defaultHosts : [ '8.8.8.8', '1.1.1.1' ],
|
defaultHosts : [ '8.8.8.8', '1.1.1.1' ],
|
||||||
|
defaultURLs : [ 'https://www.google.com' ],
|
||||||
ledsPath : '/sys/class/leds',
|
ledsPath : '/sys/class/leds',
|
||||||
ledsPerInstance : 3,
|
ledsPerInstance : 3,
|
||||||
leds : [],
|
leds : [],
|
||||||
|
publicIPProviders : {
|
||||||
|
dns : [
|
||||||
|
{ name: 'opendns1', title: 'opendns1 (DNS)' },
|
||||||
|
{ name: 'opendns2', title: 'opendns2 (DNS)' },
|
||||||
|
{ name: 'opendns3', title: 'opendns3 (DNS)' },
|
||||||
|
{ name: 'opendns4', title: 'opendns4 (DNS)' },
|
||||||
|
{ name: 'google', title: 'google (DNS)' },
|
||||||
|
{ name: 'akamai', title: 'akamai (DNS)' },
|
||||||
|
],
|
||||||
|
http: [
|
||||||
|
{ name: 'akamai_http', title: 'akamai (HTTP)' },
|
||||||
|
{ name: 'amazonaws', title: 'amazonaws (HTTP)' },
|
||||||
|
{ name: 'wgetip', title: 'wgetip.com (HTTP)' },
|
||||||
|
{ name: 'ifconfig', title: 'ifconfig.me (HTTP)' },
|
||||||
|
{ name: 'ipecho', title: 'ipecho.net (HTTP)' },
|
||||||
|
{ name: 'canhazip', title: 'canhazip.com (HTTP)' },
|
||||||
|
{ name: 'icanhazip', title: 'icanhazip.com (HTTP)' },
|
||||||
|
],
|
||||||
|
},
|
||||||
tgUpdatesURLPattern : 'https://api.telegram.org/bot%s/getUpdates',
|
tgUpdatesURLPattern : 'https://api.telegram.org/bot%s/getUpdates',
|
||||||
mm : false,
|
mm : false,
|
||||||
mmInit : false,
|
mmInit : false,
|
||||||
@@ -415,6 +435,11 @@ return view.extend({
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
validateUrl(section, value) {
|
||||||
|
return (/^$|^https?:\/\/[\w.-]+(:[0-9]{2,5})?[\w\/~.&?+=-]*$/.test(value)) ?
|
||||||
|
true : _('Expecting:') + ` ${_('valid URL')}\n`;
|
||||||
|
},
|
||||||
|
|
||||||
CBITimeInput: form.Value.extend({
|
CBITimeInput: form.Value.extend({
|
||||||
__name__ : 'CBI.TimeInput',
|
__name__ : 'CBI.TimeInput',
|
||||||
|
|
||||||
@@ -771,19 +796,41 @@ return view.extend({
|
|||||||
// hosts
|
// hosts
|
||||||
o = s.taboption('main', form.DynamicList,
|
o = s.taboption('main', form.DynamicList,
|
||||||
'hosts', _('Hosts'),
|
'hosts', _('Hosts'),
|
||||||
_('Hosts to check Internet availability. Hosts are polled (in list order) until at least one of them responds.')
|
_('Hosts for checking Internet availability. Hosts are polled (in list order) until at least one responds.')
|
||||||
);
|
);
|
||||||
o.datatype = 'or(host,hostport,ipaddrport(1))';
|
o.datatype = 'or(host,hostport,ipaddrport(1))';
|
||||||
o.default = this.defaultHosts;
|
o.default = this.defaultHosts;
|
||||||
|
o.depends({ check_type: '0' });
|
||||||
|
o.depends({ check_type: '1' });
|
||||||
o.rmempty = false;
|
o.rmempty = false;
|
||||||
|
o.modalonly = true;
|
||||||
|
|
||||||
|
if(this.curlExec) {
|
||||||
|
|
||||||
|
// urls
|
||||||
|
o = s.taboption('main', form.DynamicList,
|
||||||
|
'urls', _('URLs'),
|
||||||
|
_('URLs for checking Internet availability. URLs are polled (in list order) until at least one returns HTTP status code 200.')
|
||||||
|
);
|
||||||
|
o.validate = this.validateUrl;
|
||||||
|
o.default = this.defaultURLs;
|
||||||
|
o.rmempty = false;
|
||||||
|
o.depends({ check_type: '2' });
|
||||||
|
o.modalonly = true;
|
||||||
|
};
|
||||||
|
|
||||||
// check_type
|
// check_type
|
||||||
o = s.taboption('main', form.ListValue,
|
o = s.taboption('main', form.ListValue,
|
||||||
'check_type', _('Check type'),
|
'check_type', _('Check type'),
|
||||||
_('Host availability check type.')
|
_('Host availability check type.') + '<br />' +
|
||||||
|
((this.curlExec) ? '' :
|
||||||
|
_('To support URL checking, you need to install curl.'))
|
||||||
);
|
);
|
||||||
o.value(0, _('TCP port connection'));
|
|
||||||
o.value(1, _('ICMP-echo request (ping)'));
|
o.value(1, _('ICMP-echo request (ping)'));
|
||||||
|
o.value(0, _('TCP port connection'));
|
||||||
|
if(this.curlExec) {
|
||||||
|
o.value(2, _('URL test (HTTP)'));
|
||||||
|
};
|
||||||
o.default = '0';
|
o.default = '0';
|
||||||
o.modalonly = true;
|
o.modalonly = true;
|
||||||
|
|
||||||
@@ -810,6 +857,41 @@ return view.extend({
|
|||||||
o.depends({ check_type: '1' });
|
o.depends({ check_type: '1' });
|
||||||
o.modalonly = true;
|
o.modalonly = true;
|
||||||
|
|
||||||
|
if(this.curlExec) {
|
||||||
|
|
||||||
|
// proxy_type
|
||||||
|
o = s.taboption('main', form.ListValue,
|
||||||
|
'proxy_type', _('Proxy')
|
||||||
|
);
|
||||||
|
o.value('', _('Disabled'));
|
||||||
|
o.value('http');
|
||||||
|
o.value('socks4');
|
||||||
|
o.value('socks4a');
|
||||||
|
o.value('socks5');
|
||||||
|
o.value('socks5h');
|
||||||
|
o.default = '';
|
||||||
|
o.depends({ check_type: '2' });
|
||||||
|
o.modalonly = true;
|
||||||
|
|
||||||
|
// proxy_host
|
||||||
|
o = s.taboption('main', form.Value,
|
||||||
|
'proxy_host', _('Proxy host')
|
||||||
|
);
|
||||||
|
o.datatype = 'host';
|
||||||
|
o.rmempty = false;
|
||||||
|
o.depends({ proxy_type: /.+/ });
|
||||||
|
o.modalonly = true;
|
||||||
|
|
||||||
|
// proxy_port
|
||||||
|
o = s.taboption('main', form.Value,
|
||||||
|
'proxy_port', _('Proxy port')
|
||||||
|
);
|
||||||
|
o.datatype = 'port';
|
||||||
|
o.rmempty = false;
|
||||||
|
o.depends({ proxy_type: /.+/ });
|
||||||
|
o.modalonly = true;
|
||||||
|
};
|
||||||
|
|
||||||
// iface
|
// iface
|
||||||
o = s.taboption('main', widgets.DeviceSelect,
|
o = s.taboption('main', widgets.DeviceSelect,
|
||||||
'iface', _('Device'),
|
'iface', _('Device'),
|
||||||
@@ -857,6 +939,11 @@ return view.extend({
|
|||||||
o.value(3, '3 ' + _('sec'));
|
o.value(3, '3 ' + _('sec'));
|
||||||
o.value(4, '4 ' + _('sec'));
|
o.value(4, '4 ' + _('sec'));
|
||||||
o.value(5, '5 ' + _('sec'));
|
o.value(5, '5 ' + _('sec'));
|
||||||
|
o.value(6, '6 ' + _('sec'));
|
||||||
|
o.value(7, '7 ' + _('sec'));
|
||||||
|
o.value(8, '8 ' + _('sec'));
|
||||||
|
o.value(9, '9 ' + _('sec'));
|
||||||
|
o.value(10, '10 ' + _('sec'));
|
||||||
o.default = '2';
|
o.default = '2';
|
||||||
|
|
||||||
// enabled
|
// enabled
|
||||||
@@ -1146,6 +1233,7 @@ return view.extend({
|
|||||||
);
|
);
|
||||||
o.modalonly = true;
|
o.modalonly = true;
|
||||||
o.multiple = true;
|
o.multiple = true;
|
||||||
|
o.modalonly = true;
|
||||||
|
|
||||||
// attempts
|
// attempts
|
||||||
o = s.taboption('restart_network', form.ListValue,
|
o = s.taboption('restart_network', form.ListValue,
|
||||||
@@ -1327,25 +1415,18 @@ return view.extend({
|
|||||||
'mod_public_ip_provider', _('Provider'),
|
'mod_public_ip_provider', _('Provider'),
|
||||||
_('Service for determining the public IP address.') + '<br />' +
|
_('Service for determining the public IP address.') + '<br />' +
|
||||||
((this.curlExec) ? '' :
|
((this.curlExec) ? '' :
|
||||||
_('To support HTTP services you need to install curl.'))
|
_('To support HTTP services, you need to install curl.'))
|
||||||
);
|
);
|
||||||
o.modalonly = true;
|
o.modalonly = true;
|
||||||
o.value('opendns1', 'opendns1 (DNS)');
|
for(let i of this.publicIPProviders.dns) {
|
||||||
o.value('opendns2', 'opendns2 (DNS)');
|
o.value(i.name, i.title);
|
||||||
o.value('opendns3', 'opendns3 (DNS)');
|
|
||||||
o.value('opendns4', 'opendns4 (DNS)');
|
|
||||||
o.value('google', 'google (DNS)');
|
|
||||||
o.value('akamai', 'akamai (DNS)');
|
|
||||||
if(this.curlExec) {
|
|
||||||
o.value('akamai_http', "akamai (HTTP)");
|
|
||||||
o.value('amazonaws', "amazonaws (HTTP)");
|
|
||||||
o.value('wgetip', "wgetip.com (HTTP)");
|
|
||||||
o.value('ifconfig', "ifconfig.me (HTTP)");
|
|
||||||
o.value('ipecho', "ipecho.net (HTTP)");
|
|
||||||
o.value('canhazip', "canhazip.com (HTTP)");
|
|
||||||
o.value('icanhazip', "icanhazip.com (HTTP)");
|
|
||||||
};
|
};
|
||||||
o.default = 'opendns1';
|
if(this.curlExec) {
|
||||||
|
for(let i of this.publicIPProviders.http) {
|
||||||
|
o.value(i.name, i.title);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
o.default = this.publicIPProviders.dns[0].name;
|
||||||
|
|
||||||
// ipv6
|
// ipv6
|
||||||
o = s.taboption('public_ip', form.ListValue,
|
o = s.taboption('public_ip', form.ListValue,
|
||||||
@@ -1356,12 +1437,9 @@ return view.extend({
|
|||||||
o.value('0', 'A (IPv4)');
|
o.value('0', 'A (IPv4)');
|
||||||
o.value('1', 'AAAA (IPv6)');
|
o.value('1', 'AAAA (IPv6)');
|
||||||
o.default = '0';
|
o.default = '0';
|
||||||
o.depends({ 'mod_public_ip_provider': 'opendns1' });
|
for(let i of this.publicIPProviders.dns) {
|
||||||
o.depends({ 'mod_public_ip_provider': 'opendns2' });
|
o.depends({ mod_public_ip_provider: i.name });
|
||||||
o.depends({ 'mod_public_ip_provider': 'opendns3' });
|
};
|
||||||
o.depends({ 'mod_public_ip_provider': 'opendns4' });
|
|
||||||
o.depends({ 'mod_public_ip_provider': 'google' });
|
|
||||||
o.depends({ 'mod_public_ip_provider': 'akamai' });
|
|
||||||
|
|
||||||
// interval
|
// interval
|
||||||
o = s.taboption('public_ip', form.ListValue,
|
o = s.taboption('public_ip', form.ListValue,
|
||||||
@@ -1620,7 +1698,6 @@ return view.extend({
|
|||||||
o.password = true;
|
o.password = true;
|
||||||
o.modalonly = true;
|
o.modalonly = true;
|
||||||
|
|
||||||
// tg_chat_id
|
|
||||||
o = s.taboption('telegram', this.CBITextfieldButtonInput,
|
o = s.taboption('telegram', this.CBITextfieldButtonInput,
|
||||||
'mod_telegram_chat_id', _('Chat ID'),
|
'mod_telegram_chat_id', _('Chat ID'),
|
||||||
_('ID of the Telegram chat to which messages will be sent.')
|
_('ID of the Telegram chat to which messages will be sent.')
|
||||||
|
|||||||
@@ -212,8 +212,8 @@ msgid "Hosts polling interval when the Internet is up."
|
|||||||
msgstr "Интервал опроса хостов если Интернет доступен."
|
msgstr "Интервал опроса хостов если Интернет доступен."
|
||||||
|
|
||||||
msgid ""
|
msgid ""
|
||||||
"Hosts to check Internet availability. Hosts are polled (in list order) until "
|
"Hosts for checking Internet availability. Hosts are polled (in list "
|
||||||
"at least one of them responds."
|
"order) until at least one responds."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Хосты для проверки доступности Интернет. Хосты опрашиваются (в порядке "
|
"Хосты для проверки доступности Интернет. Хосты опрашиваются (в порядке "
|
||||||
"списка) до тех пор, пока хотя бы один из них не ответит."
|
"списка) до тех пор, пока хотя бы один из них не ответит."
|
||||||
@@ -444,6 +444,15 @@ msgstr "Интервал опроса"
|
|||||||
msgid "Provider"
|
msgid "Provider"
|
||||||
msgstr "Провайдер"
|
msgstr "Провайдер"
|
||||||
|
|
||||||
|
msgid "Proxy"
|
||||||
|
msgstr "Прокси"
|
||||||
|
|
||||||
|
msgid "Proxy host"
|
||||||
|
msgstr "Хост прокси"
|
||||||
|
|
||||||
|
msgid "Proxy port"
|
||||||
|
msgstr "Порт прокси"
|
||||||
|
|
||||||
msgid "Public IP"
|
msgid "Public IP"
|
||||||
msgstr "Публичный IP"
|
msgstr "Публичный IP"
|
||||||
|
|
||||||
@@ -600,9 +609,12 @@ msgstr "Таймаут между остановкой и запуском се
|
|||||||
msgid "Timeout between stopping and starting a ModemManger interface when restarting."
|
msgid "Timeout between stopping and starting a ModemManger interface when restarting."
|
||||||
msgstr "Таймаут между остановкой и запуском интерфейса ModemManger при перезапуске."
|
msgstr "Таймаут между остановкой и запуском интерфейса ModemManger при перезапуске."
|
||||||
|
|
||||||
msgid "To support HTTP services you need to install curl."
|
msgid "To support HTTP services, you need to install curl."
|
||||||
msgstr "Для поддержки HTTP сервисов необходимо установить curl."
|
msgstr "Для поддержки HTTP сервисов необходимо установить curl."
|
||||||
|
|
||||||
|
msgid "To support URL checking, you need to install curl."
|
||||||
|
msgstr "Для поддержки проверки URL необходимо установить curl."
|
||||||
|
|
||||||
msgid "Transmit"
|
msgid "Transmit"
|
||||||
msgstr "Передача"
|
msgstr "Передача"
|
||||||
|
|
||||||
@@ -621,6 +633,16 @@ msgstr "Неопределён"
|
|||||||
msgid "Unlock modem bands"
|
msgid "Unlock modem bands"
|
||||||
msgstr "Освободить частоты модема"
|
msgstr "Освободить частоты модема"
|
||||||
|
|
||||||
|
msgid "URL test (HTTP)"
|
||||||
|
msgstr "Тест URL (HTTP)"
|
||||||
|
|
||||||
|
msgid ""
|
||||||
|
"URLs for checking Internet availability. URLs are polled (in list "
|
||||||
|
"order) until at least one returns HTTP status code 200."
|
||||||
|
msgstr ""
|
||||||
|
"URL для проверки доступности Интернет. URL опрашиваются (в порядке "
|
||||||
|
"списка) до тех пор, пока хотя бы один из них не вернёт код статуса HTTP 200."
|
||||||
|
|
||||||
msgid "User"
|
msgid "User"
|
||||||
msgstr "Пользователь"
|
msgstr "Пользователь"
|
||||||
|
|
||||||
|
|||||||
@@ -199,8 +199,8 @@ msgid "Hosts polling interval when the Internet is up."
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid ""
|
msgid ""
|
||||||
"Hosts to check Internet availability. Hosts are polled (in list order) until "
|
"Hosts for checking Internet availability. Hosts are polled (in list "
|
||||||
"at least one of them responds."
|
"order) until at least one responds."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Huge: 1492 bytes"
|
msgid "Huge: 1492 bytes"
|
||||||
@@ -415,6 +415,15 @@ msgstr ""
|
|||||||
msgid "Provider"
|
msgid "Provider"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Proxy"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Proxy host"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Proxy port"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Public IP"
|
msgid "Public IP"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -571,7 +580,10 @@ msgstr ""
|
|||||||
msgid "Timeout between stopping and starting a ModemManger interface when restarting."
|
msgid "Timeout between stopping and starting a ModemManger interface when restarting."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "To support HTTP services you need to install curl."
|
msgid "To support HTTP services, you need to install curl."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "To support URL checking, you need to install curl."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Transmit"
|
msgid "Transmit"
|
||||||
@@ -592,6 +604,14 @@ msgstr ""
|
|||||||
msgid "Unlock modem bands"
|
msgid "Unlock modem bands"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "URL test (HTTP)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid ""
|
||||||
|
"URLs for checking Internet availability. URLs are polled (in list "
|
||||||
|
"order) until at least one returns HTTP status code 200."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "User"
|
msgid "User"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 124 KiB After Width: | Height: | Size: 120 KiB |
Reference in New Issue
Block a user