summaryrefslogtreecommitdiffhomepage
path: root/libs/sys/luasrc
diff options
context:
space:
mode:
authorJo-Philipp Wich <jow@openwrt.org>2014-06-11 13:29:05 +0000
committerJo-Philipp Wich <jow@openwrt.org>2014-06-11 13:29:05 +0000
commit7043c30e0e55bbbfacdddf97619b6bae96d20ddb (patch)
treeece3254350b3ba01ba3135caed2364cc7ca7804c /libs/sys/luasrc
parentbbb44cf245c11bc0c1d59e836007c9e8c3bfa209 (diff)
build: introduce luci-base
Merges libs/core, libs/ipkg, libs/web, libs/sys, libs/sgi-cgi, libs/sgi-uhttpd, modules/admin-core, themes/base and protcols/core into modules/base and renames luci-lib-core to luci-base.
Diffstat (limited to 'libs/sys/luasrc')
-rw-r--r--libs/sys/luasrc/sys.lua961
-rw-r--r--libs/sys/luasrc/sys/iptparser.lua373
-rw-r--r--libs/sys/luasrc/sys/zoneinfo.lua28
-rw-r--r--libs/sys/luasrc/sys/zoneinfo/tzdata.lua420
-rw-r--r--libs/sys/luasrc/sys/zoneinfo/tzoffset.lua162
5 files changed, 0 insertions, 1944 deletions
diff --git a/libs/sys/luasrc/sys.lua b/libs/sys/luasrc/sys.lua
deleted file mode 100644
index df6280dda0..0000000000
--- a/libs/sys/luasrc/sys.lua
+++ /dev/null
@@ -1,961 +0,0 @@
---[[
-LuCI - System library
-
-Description:
-Utilities for interaction with the Linux system
-
-FileId:
-$Id$
-
-License:
-Copyright 2008 Steven Barth <steven@midlink.org>
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-
-]]--
-
-
-local io = require "io"
-local os = require "os"
-local table = require "table"
-local nixio = require "nixio"
-local fs = require "nixio.fs"
-local uci = require "luci.model.uci"
-
-local luci = {}
-luci.util = require "luci.util"
-luci.ip = require "luci.ip"
-
-local tonumber, ipairs, pairs, pcall, type, next, setmetatable, require, select =
- tonumber, ipairs, pairs, pcall, type, next, setmetatable, require, select
-
-
---- LuCI Linux and POSIX system utilities.
-module "luci.sys"
-
---- Execute a given shell command and return the error code
--- @class function
--- @name call
--- @param ... Command to call
--- @return Error code of the command
-function call(...)
- return os.execute(...) / 256
-end
-
---- Execute a given shell command and capture its standard output
--- @class function
--- @name exec
--- @param command Command to call
--- @return String containg the return the output of the command
-exec = luci.util.exec
-
---- Retrieve information about currently mounted file systems.
--- @return Table containing mount information
-function mounts()
- local data = {}
- local k = {"fs", "blocks", "used", "available", "percent", "mountpoint"}
- local ps = luci.util.execi("df")
-
- if not ps then
- return
- else
- ps()
- end
-
- for line in ps do
- local row = {}
-
- local j = 1
- for value in line:gmatch("[^%s]+") do
- row[k[j]] = value
- j = j + 1
- end
-
- if row[k[1]] then
-
- -- this is a rather ugly workaround to cope with wrapped lines in
- -- the df output:
- --
- -- /dev/scsi/host0/bus0/target0/lun0/part3
- -- 114382024 93566472 15005244 86% /mnt/usb
- --
-
- if not row[k[2]] then
- j = 2
- line = ps()
- for value in line:gmatch("[^%s]+") do
- row[k[j]] = value
- j = j + 1
- end
- end
-
- table.insert(data, row)
- end
- end
-
- return data
-end
-
---- Retrieve environment variables. If no variable is given then a table
--- containing the whole environment is returned otherwise this function returns
--- the corresponding string value for the given name or nil if no such variable
--- exists.
--- @class function
--- @name getenv
--- @param var Name of the environment variable to retrieve (optional)
--- @return String containg the value of the specified variable
--- @return Table containing all variables if no variable name is given
-getenv = nixio.getenv
-
---- Get or set the current hostname.
--- @param String containing a new hostname to set (optional)
--- @return String containing the system hostname
-function hostname(newname)
- if type(newname) == "string" and #newname > 0 then
- fs.writefile( "/proc/sys/kernel/hostname", newname )
- return newname
- else
- return nixio.uname().nodename
- end
-end
-
---- Returns the contents of a documented referred by an URL.
--- @param url The URL to retrieve
--- @param stream Return a stream instead of a buffer
--- @param target Directly write to target file name
--- @return String containing the contents of given the URL
-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("'", "").."'")
- else
- return os.execute("wget -qO '%s' '%s'" %
- {target:gsub("'", ""), url:gsub("'", "")})
- end
-end
-
---- Returns the system load average values.
--- @return String containing the average load value 1 minute ago
--- @return String containing the average load value 5 minutes ago
--- @return String containing the average load value 15 minutes ago
-function loadavg()
- local info = nixio.sysinfo()
- return info.loads[1], info.loads[2], info.loads[3]
-end
-
---- Initiate a system reboot.
--- @return Return value of os.execute()
-function reboot()
- return os.execute("reboot >/dev/null 2>&1")
-end
-
---- Returns the system type, cpu name and installed physical memory.
--- @return String containing the system or platform identifier
--- @return String containing hardware model information
--- @return String containing the total memory amount in kB
--- @return String containing the memory used for caching in kB
--- @return String containing the memory used for buffering in kB
--- @return String containing the free memory amount in kB
--- @return String containing the cpu bogomips (number)
-function sysinfo()
- local cpuinfo = fs.readfile("/proc/cpuinfo")
- local meminfo = fs.readfile("/proc/meminfo")
-
- local memtotal = tonumber(meminfo:match("MemTotal:%s*(%d+)"))
- local memcached = tonumber(meminfo:match("\nCached:%s*(%d+)"))
- local memfree = tonumber(meminfo:match("MemFree:%s*(%d+)"))
- local membuffers = tonumber(meminfo:match("Buffers:%s*(%d+)"))
- local bogomips = tonumber(cpuinfo:match("[Bb]ogo[Mm][Ii][Pp][Ss].-: ([^\n]+)")) or 0
- local swaptotal = tonumber(meminfo:match("SwapTotal:%s*(%d+)"))
- local swapcached = tonumber(meminfo:match("SwapCached:%s*(%d+)"))
- local swapfree = tonumber(meminfo:match("SwapFree:%s*(%d+)"))
-
- local system =
- cpuinfo:match("system type\t+: ([^\n]+)") or
- cpuinfo:match("Processor\t+: ([^\n]+)") or
- cpuinfo:match("model name\t+: ([^\n]+)")
-
- local model =
- luci.util.pcdata(fs.readfile("/tmp/sysinfo/model")) or
- cpuinfo:match("machine\t+: ([^\n]+)") or
- cpuinfo:match("Hardware\t+: ([^\n]+)") or
- luci.util.pcdata(fs.readfile("/proc/diag/model")) or
- nixio.uname().machine or
- system
-
- return system, model, memtotal, memcached, membuffers, memfree, bogomips, swaptotal, swapcached, swapfree
-end
-
---- Retrieves the output of the "logread" command.
--- @return String containing the current log buffer
-function syslog()
- return luci.util.exec("logread")
-end
-
---- Retrieves the output of the "dmesg" command.
--- @return String containing the current log buffer
-function dmesg()
- return luci.util.exec("dmesg")
-end
-
---- Generates a random id with specified length.
--- @param bytes Number of bytes for the unique id
--- @return String containing hex encoded id
-function uniqueid(bytes)
- local rand = fs.readfile("/dev/urandom", bytes)
- return rand and nixio.bin.hexlify(rand)
-end
-
---- Returns the current system uptime stats.
--- @return String containing total uptime in seconds
-function uptime()
- return nixio.sysinfo().uptime
-end
-
-
---- LuCI system utilities / network related functions.
--- @class module
--- @name luci.sys.net
-net = {}
-
---- Returns the current arp-table entries as two-dimensional table.
--- @return Table of table containing the current arp entries.
--- The following fields are defined for arp entry objects:
--- { "IP address", "HW address", "HW type", "Flags", "Mask", "Device" }
-function net.arptable(callback)
- local arp = (not callback) and {} or nil
- local e, r, v
- if fs.access("/proc/net/arp") then
- for e in io.lines("/proc/net/arp") do
- local r = { }, v
- for v in e:gmatch("%S+") do
- r[#r+1] = v
- end
-
- if r[1] ~= "IP" then
- local x = {
- ["IP address"] = r[1],
- ["HW type"] = r[2],
- ["Flags"] = r[3],
- ["HW address"] = r[4],
- ["Mask"] = r[5],
- ["Device"] = r[6]
- }
-
- if callback then
- callback(x)
- else
- arp = arp or { }
- arp[#arp+1] = x
- end
- end
- end
- end
- return arp
-end
-
-local function _nethints(what, callback)
- local _, k, e, mac, ip, name
- local cur = uci.cursor()
- local ifn = { }
- local hosts = { }
-
- local function _add(i, ...)
- local k = select(i, ...)
- if k then
- if not hosts[k] then hosts[k] = { } end
- hosts[k][1] = select(1, ...) or hosts[k][1]
- hosts[k][2] = select(2, ...) or hosts[k][2]
- hosts[k][3] = select(3, ...) or hosts[k][3]
- hosts[k][4] = select(4, ...) or hosts[k][4]
- end
- end
-
- if fs.access("/proc/net/arp") then
- for e in io.lines("/proc/net/arp") do
- ip, mac = e:match("^([%d%.]+)%s+%S+%s+%S+%s+([a-fA-F0-9:]+)%s+")
- if ip and mac then
- _add(what, mac:upper(), ip, nil, nil)
- end
- end
- end
-
- if fs.access("/etc/ethers") then
- for e in io.lines("/etc/ethers") do
- mac, ip = e:match("^([a-f0-9]%S+) (%S+)")
- if mac and ip then
- _add(what, mac:upper(), ip, nil, nil)
- end
- end
- end
-
- if fs.access("/var/dhcp.leases") then
- for e in io.lines("/var/dhcp.leases") do
- mac, ip, name = e:match("^%d+ (%S+) (%S+) (%S+)")
- if mac and ip then
- _add(what, mac:upper(), ip, nil, name ~= "*" and name)
- end
- end
- end
-
- cur:foreach("dhcp", "host",
- function(s)
- for mac in luci.util.imatch(s.mac) do
- _add(what, mac:upper(), s.ip, nil, s.name)
- end
- end)
-
- for _, e in ipairs(nixio.getifaddrs()) do
- if e.name ~= "lo" then
- ifn[e.name] = ifn[e.name] or { }
- if e.family == "packet" and e.addr and #e.addr == 17 then
- ifn[e.name][1] = e.addr:upper()
- elseif e.family == "inet" then
- ifn[e.name][2] = e.addr
- elseif e.family == "inet6" then
- ifn[e.name][3] = e.addr
- end
- end
- end
-
- for _, e in pairs(ifn) do
- if e[what] and (e[2] or e[3]) then
- _add(what, e[1], e[2], e[3], e[4])
- end
- end
-
- for _, e in luci.util.kspairs(hosts) do
- callback(e[1], e[2], e[3], e[4])
- end
-end
-
---- Returns a two-dimensional table of mac address hints.
--- @return Table of table containing known hosts from various sources.
--- Each entry contains the values in the following order:
--- [ "mac", "name" ]
-function net.mac_hints(callback)
- if callback then
- _nethints(1, function(mac, v4, v6, name)
- name = name or nixio.getnameinfo(v4 or v6, nil, 100) or v4
- if name and name ~= mac then
- callback(mac, name or nixio.getnameinfo(v4 or v6, nil, 100) or v4)
- end
- end)
- else
- local rv = { }
- _nethints(1, function(mac, v4, v6, name)
- name = name or nixio.getnameinfo(v4 or v6, nil, 100) or v4
- if name and name ~= mac then
- rv[#rv+1] = { mac, name or nixio.getnameinfo(v4 or v6, nil, 100) or v4 }
- end
- end)
- return rv
- end
-end
-
---- Returns a two-dimensional table of IPv4 address hints.
--- @return Table of table containing known hosts from various sources.
--- Each entry contains the values in the following order:
--- [ "ip", "name" ]
-function net.ipv4_hints(callback)
- if callback then
- _nethints(2, function(mac, v4, v6, name)
- name = name or nixio.getnameinfo(v4, nil, 100) or mac
- if name and name ~= v4 then
- callback(v4, name)
- end
- end)
- else
- local rv = { }
- _nethints(2, function(mac, v4, v6, name)
- name = name or nixio.getnameinfo(v4, nil, 100) or mac
- if name and name ~= v4 then
- rv[#rv+1] = { v4, name }
- end
- end)
- return rv
- end
-end
-
---- Returns a two-dimensional table of IPv6 address hints.
--- @return Table of table containing known hosts from various sources.
--- Each entry contains the values in the following order:
--- [ "ip", "name" ]
-function net.ipv6_hints(callback)
- if callback then
- _nethints(3, function(mac, v4, v6, name)
- name = name or nixio.getnameinfo(v6, nil, 100) or mac
- if name and name ~= v6 then
- callback(v6, name)
- end
- end)
- else
- local rv = { }
- _nethints(3, function(mac, v4, v6, name)
- name = name or nixio.getnameinfo(v6, nil, 100) or mac
- if name and name ~= v6 then
- rv[#rv+1] = { v6, name }
- end
- end)
- return rv
- end
-end
-
---- Returns conntrack information
--- @return Table with the currently tracked IP connections
-function net.conntrack(callback)
- local connt = {}
- if fs.access("/proc/net/nf_conntrack", "r") then
- for line in io.lines("/proc/net/nf_conntrack") do
- line = line:match "^(.-( [^ =]+=).-)%2"
- local entry, flags = _parse_mixed_record(line, " +")
- if flags[6] ~= "TIME_WAIT" then
- entry.layer3 = flags[1]
- entry.layer4 = flags[3]
- for i=1, #entry do
- entry[i] = nil
- end
-
- if callback then
- callback(entry)
- else
- connt[#connt+1] = entry
- end
- end
- end
- elseif fs.access("/proc/net/ip_conntrack", "r") then
- for line in io.lines("/proc/net/ip_conntrack") do
- line = line:match "^(.-( [^ =]+=).-)%2"
- local entry, flags = _parse_mixed_record(line, " +")
- if flags[4] ~= "TIME_WAIT" then
- entry.layer3 = "ipv4"
- entry.layer4 = flags[1]
- for i=1, #entry do
- entry[i] = nil
- end
-
- if callback then
- callback(entry)
- else
- connt[#connt+1] = entry
- end
- end
- end
- else
- return nil
- end
- return connt
-end
-
---- Determine the current IPv4 default route. If multiple default routes exist,
--- return the one with the lowest metric.
--- @return Table with the properties of the current default route.
--- The following fields are defined:
--- { "dest", "gateway", "metric", "refcount", "usecount", "irtt",
--- "flags", "device" }
-function net.defaultroute()
- local route
-
- net.routes(function(rt)
- if rt.dest:prefix() == 0 and (not route or route.metric > rt.metric) then
- route = rt
- end
- end)
-
- return route
-end
-
---- Determine the current IPv6 default route. If multiple default routes exist,
--- return the one with the lowest metric.
--- @return Table with the properties of the current default route.
--- The following fields are defined:
--- { "source", "dest", "nexthop", "metric", "refcount", "usecount",
--- "flags", "device" }
-function net.defaultroute6()
- local route
-
- net.routes6(function(rt)
- if rt.dest:prefix() == 0 and rt.device ~= "lo" and
- (not route or route.metric > rt.metric)
- then
- route = rt
- end
- end)
-
- if not route then
- local global_unicast = luci.ip.IPv6("2000::/3")
- net.routes6(function(rt)
- if rt.dest:equal(global_unicast) and
- (not route or route.metric > rt.metric)
- then
- route = rt
- end
- end)
- end
-
- return route
-end
-
---- Determine the names of available network interfaces.
--- @return Table containing all current interface names
-function net.devices()
- local devs = {}
- for k, v in ipairs(nixio.getifaddrs()) do
- if v.family == "packet" then
- devs[#devs+1] = v.name
- end
- end
- return devs
-end
-
-
---- Return information about available network interfaces.
--- @return Table containing all current interface names and their information
-function net.deviceinfo()
- local devs = {}
- for k, v in ipairs(nixio.getifaddrs()) do
- if v.family == "packet" then
- local d = v.data
- d[1] = d.rx_bytes
- d[2] = d.rx_packets
- d[3] = d.rx_errors
- d[4] = d.rx_dropped
- d[5] = 0
- d[6] = 0
- d[7] = 0
- d[8] = d.multicast
- d[9] = d.tx_bytes
- d[10] = d.tx_packets
- d[11] = d.tx_errors
- d[12] = d.tx_dropped
- d[13] = 0
- d[14] = d.collisions
- d[15] = 0
- d[16] = 0
- devs[v.name] = d
- end
- end
- return devs
-end
-
-
--- Determine the MAC address belonging to the given IP address.
--- @param ip IPv4 address
--- @return String containing the MAC address or nil if it cannot be found
-function net.ip4mac(ip)
- local mac = nil
- net.arptable(function(e)
- if e["IP address"] == ip then
- mac = e["HW address"]
- end
- end)
- return mac
-end
-
---- Returns the current kernel routing table entries.
--- @return Table of tables with properties of the corresponding routes.
--- The following fields are defined for route entry tables:
--- { "dest", "gateway", "metric", "refcount", "usecount", "irtt",
--- "flags", "device" }
-function net.routes(callback)
- local routes = { }
-
- for line in io.lines("/proc/net/route") do
-
- local dev, dst_ip, gateway, flags, refcnt, usecnt, metric,
- dst_mask, mtu, win, irtt = line:match(
- "([^%s]+)\t([A-F0-9]+)\t([A-F0-9]+)\t([A-F0-9]+)\t" ..
- "(%d+)\t(%d+)\t(%d+)\t([A-F0-9]+)\t(%d+)\t(%d+)\t(%d+)"
- )
-
- if dev then
- gateway = luci.ip.Hex( gateway, 32, luci.ip.FAMILY_INET4 )
- dst_mask = luci.ip.Hex( dst_mask, 32, luci.ip.FAMILY_INET4 )
- dst_ip = luci.ip.Hex(
- dst_ip, dst_mask:prefix(dst_mask), luci.ip.FAMILY_INET4
- )
-
- local rt = {
- dest = dst_ip,
- gateway = gateway,
- metric = tonumber(metric),
- refcount = tonumber(refcnt),
- usecount = tonumber(usecnt),
- mtu = tonumber(mtu),
- window = tonumber(window),
- irtt = tonumber(irtt),
- flags = tonumber(flags, 16),
- device = dev
- }
-
- if callback then
- callback(rt)
- else
- routes[#routes+1] = rt
- end
- end
- end
-
- return routes
-end
-
---- Returns the current ipv6 kernel routing table entries.
--- @return Table of tables with properties of the corresponding routes.
--- The following fields are defined for route entry tables:
--- { "source", "dest", "nexthop", "metric", "refcount", "usecount",
--- "flags", "device" }
-function net.routes6(callback)
- if fs.access("/proc/net/ipv6_route", "r") then
- local routes = { }
-
- for line in io.lines("/proc/net/ipv6_route") do
-
- local dst_ip, dst_prefix, src_ip, src_prefix, nexthop,
- metric, refcnt, usecnt, flags, dev = line:match(
- "([a-f0-9]+) ([a-f0-9]+) " ..
- "([a-f0-9]+) ([a-f0-9]+) " ..
- "([a-f0-9]+) ([a-f0-9]+) " ..
- "([a-f0-9]+) ([a-f0-9]+) " ..
- "([a-f0-9]+) +([^%s]+)"
- )
-
- if dst_ip and dst_prefix and
- src_ip and src_prefix and
- nexthop and metric and
- refcnt and usecnt and
- flags and dev
- then
- src_ip = luci.ip.Hex(
- src_ip, tonumber(src_prefix, 16), luci.ip.FAMILY_INET6, false
- )
-
- dst_ip = luci.ip.Hex(
- dst_ip, tonumber(dst_prefix, 16), luci.ip.FAMILY_INET6, false
- )
-
- nexthop = luci.ip.Hex( nexthop, 128, luci.ip.FAMILY_INET6, false )
-
- local rt = {
- source = src_ip,
- dest = dst_ip,
- nexthop = nexthop,
- metric = tonumber(metric, 16),
- refcount = tonumber(refcnt, 16),
- usecount = tonumber(usecnt, 16),
- flags = tonumber(flags, 16),
- device = dev,
-
- -- lua number is too small for storing the metric
- -- add a metric_raw field with the original content
- metric_raw = metric
- }
-
- if callback then
- callback(rt)
- else
- routes[#routes+1] = rt
- end
- end
- end
-
- return routes
- end
-end
-
---- Tests whether the given host responds to ping probes.
--- @param host String containing a hostname or IPv4 address
--- @return Number containing 0 on success and >= 1 on error
-function net.pingtest(host)
- return os.execute("ping -c1 '"..host:gsub("'", '').."' >/dev/null 2>&1")
-end
-
-
---- LuCI system utilities / process related functions.
--- @class module
--- @name luci.sys.process
-process = {}
-
---- Get the current process id.
--- @class function
--- @name process.info
--- @return Number containing the current pid
-function process.info(key)
- local s = {uid = nixio.getuid(), gid = nixio.getgid()}
- return not key and s or s[key]
-end
-
---- Retrieve information about currently running processes.
--- @return Table containing process information
-function process.list()
- local data = {}
- local k
- local ps = luci.util.execi("/bin/busybox top -bn1")
-
- if not ps then
- return
- end
-
- for line in ps do
- local pid, ppid, user, stat, vsz, mem, cpu, cmd = line:match(
- "^ *(%d+) +(%d+) +(%S.-%S) +([RSDZTW][W ][<N ]) +(%d+) +(%d+%%) +(%d+%%) +(.+)"
- )
-
- local idx = tonumber(pid)
- if idx then
- data[idx] = {
- ['PID'] = pid,
- ['PPID'] = ppid,
- ['USER'] = user,
- ['STAT'] = stat,
- ['VSZ'] = vsz,
- ['%MEM'] = mem,
- ['%CPU'] = cpu,
- ['COMMAND'] = cmd
- }
- end
- end
-
- return data
-end
-
---- Set the gid of a process identified by given pid.
--- @param gid Number containing the Unix group id
--- @return Boolean indicating successful operation
--- @return String containing the error message if failed
--- @return Number containing the error code if failed
-function process.setgroup(gid)
- return nixio.setgid(gid)
-end
-
---- Set the uid of a process identified by given pid.
--- @param uid Number containing the Unix user id
--- @return Boolean indicating successful operation
--- @return String containing the error message if failed
--- @return Number containing the error code if failed
-function process.setuser(uid)
- return nixio.setuid(uid)
-end
-
---- Send a signal to a process identified by given pid.
--- @class function
--- @name process.signal
--- @param pid Number containing the process id
--- @param sig Signal to send (default: 15 [SIGTERM])
--- @return Boolean indicating successful operation
--- @return Number containing the error code if failed
-process.signal = nixio.kill
-
-
---- LuCI system utilities / user related functions.
--- @class module
--- @name luci.sys.user
-user = {}
-
---- Retrieve user informations for given uid.
--- @class function
--- @name getuser
--- @param uid Number containing the Unix user id
--- @return Table containing the following fields:
--- { "uid", "gid", "name", "passwd", "dir", "shell", "gecos" }
-user.getuser = nixio.getpw
-
---- Retrieve the current user password hash.
--- @param username String containing the username to retrieve the password for
--- @return String containing the hash or nil if no password is set.
--- @return Password database entry
-function user.getpasswd(username)
- local pwe = nixio.getsp and nixio.getsp(username) or nixio.getpw(username)
- local pwh = pwe and (pwe.pwdp or pwe.passwd)
- if not pwh or #pwh < 1 or pwh == "!" or pwh == "x" then
- return nil, pwe
- else
- return pwh, pwe
- end
-end
-
---- Test whether given string matches the password of a given system user.
--- @param username String containing the Unix user name
--- @param pass String containing the password to compare
--- @return Boolean indicating wheather the passwords are equal
-function user.checkpasswd(username, pass)
- local pwh, pwe = user.getpasswd(username)
- if pwe then
- return (pwh == nil or nixio.crypt(pass, pwh) == pwh)
- end
- return false
-end
-
---- Change the password of given user.
--- @param username String containing the Unix user name
--- @param password String containing the password to compare
--- @return Number containing 0 on success and >= 1 on error
-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"
- )
-end
-
-
---- LuCI system utilities / wifi related functions.
--- @class module
--- @name luci.sys.wifi
-wifi = {}
-
---- Get wireless information for given interface.
--- @param ifname String containing the interface name
--- @return A wrapped iwinfo object instance
-function wifi.getiwinfo(ifname)
- local stat, iwinfo = pcall(require, "iwinfo")
-
- if ifname then
- local c = 0
- local u = uci.cursor_state()
- local d, n = ifname:match("^(%w+)%.network(%d+)")
- if d and n then
- ifname = d
- n = tonumber(n)
- u:foreach("wireless", "wifi-iface",
- function(s)
- if s.device == d then
- c = c + 1
- if c == n then
- ifname = s.ifname or s.device
- return false
- end
- end
- end)
- elseif u:get("wireless", ifname) == "wifi-device" then
- u:foreach("wireless", "wifi-iface",
- function(s)
- if s.device == ifname and s.ifname then
- ifname = s.ifname
- return false
- end
- end)
- end
-
- local t = stat and iwinfo.type(ifname)
- local x = t and iwinfo[t] or { }
- return setmetatable({}, {
- __index = function(t, k)
- if k == "ifname" then
- return ifname
- elseif x[k] then
- return x[k](ifname)
- end
- end
- })
- end
-end
-
-
---- LuCI system utilities / init related functions.
--- @class module
--- @name luci.sys.init
-init = {}
-init.dir = "/etc/init.d/"
-
---- Get the names of all installed init scripts
--- @return Table containing the names of all inistalled init scripts
-function init.names()
- local names = { }
- for name in fs.glob(init.dir.."*") do
- names[#names+1] = fs.basename(name)
- end
- return names
-end
-
---- Get the index of he given init script
--- @param name Name of the init script
--- @return Numeric index value
-function init.index(name)
- if fs.access(init.dir..name) then
- return call("env -i sh -c 'source %s%s enabled; exit ${START:-255}' >/dev/null"
- %{ init.dir, name })
- end
-end
-
-local function init_action(action, name)
- if fs.access(init.dir..name) then
- return call("env -i %s%s %s >/dev/null" %{ init.dir, name, action })
- end
-end
-
---- Test whether the given init script is enabled
--- @param name Name of the init script
--- @return Boolean indicating whether init is enabled
-function init.enabled(name)
- return (init_action("enabled", name) == 0)
-end
-
---- Enable the given init script
--- @param name Name of the init script
--- @return Boolean indicating success
-function init.enable(name)
- return (init_action("enable", name) == 1)
-end
-
---- Disable the given init script
--- @param name Name of the init script
--- @return Boolean indicating success
-function init.disable(name)
- return (init_action("disable", name) == 0)
-end
-
---- Start the given init script
--- @param name Name of the init script
--- @return Boolean indicating success
-function init.start(name)
- return (init_action("start", name) == 0)
-end
-
---- Stop the given init script
--- @param name Name of the init script
--- @return Boolean indicating success
-function init.stop(name)
- return (init_action("stop", name) == 0)
-end
-
-
--- Internal functions
-
-function _parse_mixed_record(cnt, delimiter)
- delimiter = delimiter or " "
- local data = {}
- local flags = {}
-
- for i, l in pairs(luci.util.split(luci.util.trim(cnt), "\n")) do
- for j, f in pairs(luci.util.split(luci.util.trim(l), delimiter, nil, true)) do
- local k, x, v = f:match('([^%s][^:=]*) *([:=]*) *"*([^\n"]*)"*')
-
- if k then
- if x == "" then
- table.insert(flags, k)
- else
- data[k] = v
- end
- end
- end
- end
-
- return data, flags
-end
diff --git a/libs/sys/luasrc/sys/iptparser.lua b/libs/sys/luasrc/sys/iptparser.lua
deleted file mode 100644
index d82363309a..0000000000
--- a/libs/sys/luasrc/sys/iptparser.lua
+++ /dev/null
@@ -1,373 +0,0 @@
---[[
-
-Iptables parser and query library
-(c) 2008-2009 Jo-Philipp Wich <xm@leipzig.freifunk.net>
-(c) 2008-2009 Steven Barth <steven@midlink.org>
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-$Id$
-
-]]--
-
-local luci = {}
-luci.util = require "luci.util"
-luci.sys = require "luci.sys"
-luci.ip = require "luci.ip"
-
-local tonumber, ipairs, table = tonumber, ipairs, table
-
---- LuCI iptables parser and query library
--- @cstyle instance
-module("luci.sys.iptparser")
-
---- Create a new iptables parser object.
--- @class function
--- @name IptParser
--- @param family Number specifying the address family. 4 for IPv4, 6 for IPv6
--- @return IptParser instance
-IptParser = luci.util.class()
-
-function IptParser.__init__( self, family )
- self._family = (tonumber(family) == 6) and 6 or 4
- self._rules = { }
- self._chains = { }
-
- if self._family == 4 then
- self._nulladdr = "0.0.0.0/0"
- self._tables = { "filter", "nat", "mangle", "raw" }
- self._command = "iptables -t %s --line-numbers -nxvL"
- else
- self._nulladdr = "::/0"
- self._tables = { "filter", "mangle", "raw" }
- self._command = "ip6tables -t %s --line-numbers -nxvL"
- end
-
- self:_parse_rules()
-end
-
---- Find all firewall rules that match the given criteria. Expects a table with
--- search criteria as only argument. If args is nil or an empty table then all
--- rules will be returned.
---
--- The following keys in the args table are recognized:
--- <ul>
--- <li> table - Match rules that are located within the given table
--- <li> chain - Match rules that are located within the given chain
--- <li> target - Match rules with the given target
--- <li> protocol - Match rules that match the given protocol, rules with
--- protocol "all" are always matched
--- <li> source - Match rules with the given source, rules with source
--- "0.0.0.0/0" (::/0) are always matched
--- <li> destination - Match rules with the given destination, rules with
--- destination "0.0.0.0/0" (::/0) are always matched
--- <li> inputif - Match rules with the given input interface, rules
--- with input interface "*" (=all) are always matched
--- <li> outputif - Match rules with the given output interface, rules
--- with output interface "*" (=all) are always matched
--- <li> flags - Match rules that match the given flags, current
--- supported values are "-f" (--fragment)
--- and "!f" (! --fragment)
--- <li> options - Match rules containing all given options
--- </ul>
--- The return value is a list of tables representing the matched rules.
--- Each rule table contains the following fields:
--- <ul>
--- <li> index - The index number of the rule
--- <li> table - The table where the rule is located, can be one
--- of "filter", "nat" or "mangle"
--- <li> chain - The chain where the rule is located, e.g. "INPUT"
--- or "postrouting_wan"
--- <li> target - The rule target, e.g. "REJECT" or "DROP"
--- <li> protocol The matching protocols, e.g. "all" or "tcp"
--- <li> flags - Special rule options ("--", "-f" or "!f")
--- <li> inputif - Input interface of the rule, e.g. "eth0.0"
--- or "*" for all interfaces
--- <li> outputif - Output interface of the rule,e.g. "eth0.0"
--- or "*" for all interfaces
--- <li> source - The source ip range, e.g. "0.0.0.0/0" (::/0)
--- <li> destination - The destination ip range, e.g. "0.0.0.0/0" (::/0)
--- <li> options - A list of specific options of the rule,
--- e.g. { "reject-with", "tcp-reset" }
--- <li> packets - The number of packets matched by the rule
--- <li> bytes - The number of total bytes matched by the rule
--- </ul>
--- Example:
--- <pre>
--- ip = luci.sys.iptparser.IptParser()
--- result = ip.find( {
--- target="REJECT",
--- protocol="tcp",
--- options={ "reject-with", "tcp-reset" }
--- } )
--- </pre>
--- This will match all rules with target "-j REJECT",
--- protocol "-p tcp" (or "-p all")
--- and the option "--reject-with tcp-reset".
--- @params args Table containing the search arguments (optional)
--- @return Table of matching rule tables
-function IptParser.find( self, args )
-
- local args = args or { }
- local rv = { }
-
- args.source = args.source and self:_parse_addr(args.source)
- args.destination = args.destination and self:_parse_addr(args.destination)
-
- for i, rule in ipairs(self._rules) do
- local match = true
-
- -- match table
- if not ( not args.table or args.table:lower() == rule.table ) then
- match = false
- end
-
- -- match chain
- if not ( match == true and (
- not args.chain or args.chain == rule.chain
- ) ) then
- match = false
- end
-
- -- match target
- if not ( match == true and (
- not args.target or args.target == rule.target
- ) ) then
- match = false
- end
-
- -- match protocol
- if not ( match == true and (
- not args.protocol or rule.protocol == "all" or
- args.protocol:lower() == rule.protocol
- ) ) then
- match = false
- end
-
- -- match source
- if not ( match == true and (
- not args.source or rule.source == self._nulladdr or
- self:_parse_addr(rule.source):contains(args.source)
- ) ) then
- match = false
- end
-
- -- match destination
- if not ( match == true and (
- not args.destination or rule.destination == self._nulladdr or
- self:_parse_addr(rule.destination):contains(args.destination)
- ) ) then
- match = false
- end
-
- -- match input interface
- if not ( match == true and (
- not args.inputif or rule.inputif == "*" or
- args.inputif == rule.inputif
- ) ) then
- match = false
- end
-
- -- match output interface
- if not ( match == true and (
- not args.outputif or rule.outputif == "*" or
- args.outputif == rule.outputif
- ) ) then
- match = false
- end
-
- -- match flags (the "opt" column)
- if not ( match == true and (
- not args.flags or rule.flags == args.flags
- ) ) then
- match = false
- end
-
- -- match specific options
- if not ( match == true and (
- not args.options or
- self:_match_options( rule.options, args.options )
- ) ) then
- match = false
- end
-
- -- insert match
- if match == true then
- rv[#rv+1] = rule
- end
- end
-
- return rv
-end
-
-
---- Rebuild the internal lookup table, for example when rules have changed
--- through external commands.
--- @return nothing
-function IptParser.resync( self )
- self._rules = { }
- self._chain = nil
- self:_parse_rules()
-end
-
-
---- Find the names of all tables.
--- @return Table of table names.
-function IptParser.tables( self )
- return self._tables
-end
-
-
---- Find the names of all chains within the given table name.
--- @param table String containing the table name
--- @return Table of chain names in the order they occur.
-function IptParser.chains( self, table )
- local lookup = { }
- local chains = { }
- for _, r in ipairs(self:find({table=table})) do
- if not lookup[r.chain] then
- lookup[r.chain] = true
- chains[#chains+1] = r.chain
- end
- end
- return chains
-end
-
-
---- Return the given firewall chain within the given table name.
--- @param table String containing the table name
--- @param chain String containing the chain name
--- @return Table containing the fields "policy", "packets", "bytes"
--- and "rules". The "rules" field is a table of rule tables.
-function IptParser.chain( self, table, chain )
- return self._chains[table:lower()] and self._chains[table:lower()][chain]
-end
-
-
---- Test whether the given target points to a custom chain.
--- @param target String containing the target action
--- @return Boolean indicating whether target is a custom chain.
-function IptParser.is_custom_target( self, target )
- for _, r in ipairs(self._rules) do
- if r.chain == target then
- return true
- end
- end
- return false
-end
-
-
--- [internal] Parse address according to family.
-function IptParser._parse_addr( self, addr )
- if self._family == 4 then
- return luci.ip.IPv4(addr)
- else
- return luci.ip.IPv6(addr)
- end
-end
-
--- [internal] Parse iptables output from all tables.
-function IptParser._parse_rules( self )
-
- for i, tbl in ipairs(self._tables) do
-
- self._chains[tbl] = { }
-
- for i, rule in ipairs(luci.util.execl(self._command % tbl)) do
-
- if rule:find( "^Chain " ) == 1 then
-
- local crefs
- local cname, cpol, cpkt, cbytes = rule:match(
- "^Chain ([^%s]*) %(policy (%w+) " ..
- "(%d+) packets, (%d+) bytes%)"
- )
-
- if not cname then
- cname, crefs = rule:match(
- "^Chain ([^%s]*) %((%d+) references%)"
- )
- end
-
- self._chain = cname
- self._chains[tbl][cname] = {
- policy = cpol,
- packets = tonumber(cpkt or 0),
- bytes = tonumber(cbytes or 0),
- references = tonumber(crefs or 0),
- rules = { }
- }
-
- else
- if rule:find("%d") == 1 then
-
- local rule_parts = luci.util.split( rule, "%s+", nil, true )
- local rule_details = { }
-
- -- cope with rules that have no target assigned
- if rule:match("^%d+%s+%d+%s+%d+%s%s") then
- table.insert(rule_parts, 4, nil)
- end
-
- -- ip6tables opt column is usually zero-width
- if self._family == 6 then
- table.insert(rule_parts, 6, "--")
- end
-
- rule_details["table"] = tbl
- rule_details["chain"] = self._chain
- rule_details["index"] = tonumber(rule_parts[1])
- rule_details["packets"] = tonumber(rule_parts[2])
- rule_details["bytes"] = tonumber(rule_parts[3])
- rule_details["target"] = rule_parts[4]
- rule_details["protocol"] = rule_parts[5]
- rule_details["flags"] = rule_parts[6]
- rule_details["inputif"] = rule_parts[7]
- rule_details["outputif"] = rule_parts[8]
- rule_details["source"] = rule_parts[9]
- rule_details["destination"] = rule_parts[10]
- rule_details["options"] = { }
-
- for i = 11, #rule_parts do
- if #rule_parts[i] > 0 then
- rule_details["options"][i-10] = rule_parts[i]
- end
- end
-
- self._rules[#self._rules+1] = rule_details
-
- self._chains[tbl][self._chain].rules[
- #self._chains[tbl][self._chain].rules + 1
- ] = rule_details
- end
- end
- end
- end
-
- self._chain = nil
-end
-
-
--- [internal] Return true if optlist1 contains all elements of optlist 2.
--- Return false in all other cases.
-function IptParser._match_options( self, o1, o2 )
-
- -- construct a hashtable of first options list to speed up lookups
- local oh = { }
- for i, opt in ipairs( o1 ) do oh[opt] = true end
-
- -- iterate over second options list
- -- each string in o2 must be also present in o1
- -- if o2 contains a string which is not found in o1 then return false
- for i, opt in ipairs( o2 ) do
- if not oh[opt] then
- return false
- end
- end
-
- return true
-end
diff --git a/libs/sys/luasrc/sys/zoneinfo.lua b/libs/sys/luasrc/sys/zoneinfo.lua
deleted file mode 100644
index f5a12bfcb6..0000000000
--- a/libs/sys/luasrc/sys/zoneinfo.lua
+++ /dev/null
@@ -1,28 +0,0 @@
---[[
-LuCI - Autogenerated Zoneinfo Module
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-]]--
-
-local setmetatable, require, rawget, rawset = setmetatable, require, rawget, rawset
-
-module "luci.sys.zoneinfo"
-
-setmetatable(_M, {
- __index = function(t, k)
- if k == "TZ" and not rawget(t, k) then
- local m = require "luci.sys.zoneinfo.tzdata"
- rawset(t, k, rawget(m, k))
- elseif k == "OFFSET" and not rawget(t, k) then
- local m = require "luci.sys.zoneinfo.tzoffset"
- rawset(t, k, rawget(m, k))
- end
-
- return rawget(t, k)
- end
-})
diff --git a/libs/sys/luasrc/sys/zoneinfo/tzdata.lua b/libs/sys/luasrc/sys/zoneinfo/tzdata.lua
deleted file mode 100644
index 1a99f6a7eb..0000000000
--- a/libs/sys/luasrc/sys/zoneinfo/tzdata.lua
+++ /dev/null
@@ -1,420 +0,0 @@
---[[
-LuCI - Autogenerated Zoneinfo Module
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-]]--
-
-module "luci.sys.zoneinfo.tzdata"
-
-TZ = {
- { 'Africa/Abidjan', 'GMT0' },
- { 'Africa/Accra', 'GMT0' },
- { 'Africa/Addis Ababa', 'EAT-3' },
- { 'Africa/Algiers', 'CET-1' },
- { 'Africa/Asmara', 'EAT-3' },
- { 'Africa/Bamako', 'GMT0' },
- { 'Africa/Bangui', 'WAT-1' },
- { 'Africa/Banjul', 'GMT0' },
- { 'Africa/Bissau', 'GMT0' },
- { 'Africa/Blantyre', 'CAT-2' },
- { 'Africa/Brazzaville', 'WAT-1' },
- { 'Africa/Bujumbura', 'CAT-2' },
- { 'Africa/Casablanca', 'WET0' },
- { 'Africa/Ceuta', 'CET-1CEST,M3.5.0,M10.5.0/3' },
- { 'Africa/Conakry', 'GMT0' },
- { 'Africa/Dakar', 'GMT0' },
- { 'Africa/Dar es Salaam', 'EAT-3' },
- { 'Africa/Djibouti', 'EAT-3' },
- { 'Africa/Douala', 'WAT-1' },
- { 'Africa/El Aaiun', 'WET0' },
- { 'Africa/Freetown', 'GMT0' },
- { 'Africa/Gaborone', 'CAT-2' },
- { 'Africa/Harare', 'CAT-2' },
- { 'Africa/Johannesburg', 'SAST-2' },
- { 'Africa/Juba', 'EAT-3' },
- { 'Africa/Kampala', 'EAT-3' },
- { 'Africa/Khartoum', 'EAT-3' },
- { 'Africa/Kigali', 'CAT-2' },
- { 'Africa/Kinshasa', 'WAT-1' },
- { 'Africa/Lagos', 'WAT-1' },
- { 'Africa/Libreville', 'WAT-1' },
- { 'Africa/Lome', 'GMT0' },
- { 'Africa/Luanda', 'WAT-1' },
- { 'Africa/Lubumbashi', 'CAT-2' },
- { 'Africa/Lusaka', 'CAT-2' },
- { 'Africa/Malabo', 'WAT-1' },
- { 'Africa/Maputo', 'CAT-2' },
- { 'Africa/Maseru', 'SAST-2' },
- { 'Africa/Mbabane', 'SAST-2' },
- { 'Africa/Mogadishu', 'EAT-3' },
- { 'Africa/Monrovia', 'GMT0' },
- { 'Africa/Nairobi', 'EAT-3' },
- { 'Africa/Ndjamena', 'WAT-1' },
- { 'Africa/Niamey', 'WAT-1' },
- { 'Africa/Nouakchott', 'GMT0' },
- { 'Africa/Ouagadougou', 'GMT0' },
- { 'Africa/Porto-Novo', 'WAT-1' },
- { 'Africa/Sao Tome', 'GMT0' },
- { 'Africa/Tripoli', 'EET-2' },
- { 'Africa/Tunis', 'CET-1' },
- { 'Africa/Windhoek', 'WAT-1WAST,M9.1.0,M4.1.0' },
- { 'America/Adak', 'HAST10HADT,M3.2.0,M11.1.0' },
- { 'America/Anchorage', 'AKST9AKDT,M3.2.0,M11.1.0' },
- { 'America/Anguilla', 'AST4' },
- { 'America/Antigua', 'AST4' },
- { 'America/Araguaina', 'BRT3' },
- { 'America/Argentina/Buenos Aires', 'ART3' },
- { 'America/Argentina/Catamarca', 'ART3' },
- { 'America/Argentina/Cordoba', 'ART3' },
- { 'America/Argentina/Jujuy', 'ART3' },
- { 'America/Argentina/La Rioja', 'ART3' },
- { 'America/Argentina/Mendoza', 'ART3' },
- { 'America/Argentina/Rio Gallegos', 'ART3' },
- { 'America/Argentina/Salta', 'ART3' },
- { 'America/Argentina/San Juan', 'ART3' },
- { 'America/Argentina/Tucuman', 'ART3' },
- { 'America/Argentina/Ushuaia', 'ART3' },
- { 'America/Aruba', 'AST4' },
- { 'America/Asuncion', 'PYT4PYST,M10.1.0/0,M4.2.0/0' },
- { 'America/Atikokan', 'EST5' },
- { 'America/Bahia', 'BRT3BRST,M10.3.0/0,M2.3.0/0' },
- { 'America/Bahia Banderas', 'CST6CDT,M4.1.0,M10.5.0' },
- { 'America/Barbados', 'AST4' },
- { 'America/Belem', 'BRT3' },
- { 'America/Belize', 'CST6' },
- { 'America/Blanc-Sablon', 'AST4' },
- { 'America/Boa Vista', 'AMT4' },
- { 'America/Bogota', 'COT5' },
- { 'America/Boise', 'MST7MDT,M3.2.0,M11.1.0' },
- { 'America/Cambridge Bay', 'MST7MDT,M3.2.0,M11.1.0' },
- { 'America/Campo Grande', 'AMT4AMST,M10.3.0/0,M2.3.0/0' },
- { 'America/Cancun', 'CST6CDT,M4.1.0,M10.5.0' },
- { 'America/Caracas', 'VET4:30' },
- { 'America/Cayenne', 'GFT3' },
- { 'America/Cayman', 'EST5' },
- { 'America/Chicago', 'CST6CDT,M3.2.0,M11.1.0' },
- { 'America/Chihuahua', 'MST7MDT,M4.1.0,M10.5.0' },
- { 'America/Costa Rica', 'CST6' },
- { 'America/Cuiaba', 'AMT4AMST,M10.3.0/0,M2.3.0/0' },
- { 'America/Curacao', 'AST4' },
- { 'America/Danmarkshavn', 'GMT0' },
- { 'America/Dawson', 'PST8PDT,M3.2.0,M11.1.0' },
- { 'America/Dawson Creek', 'MST7' },
- { 'America/Denver', 'MST7MDT,M3.2.0,M11.1.0' },
- { 'America/Detroit', 'EST5EDT,M3.2.0,M11.1.0' },
- { 'America/Dominica', 'AST4' },
- { 'America/Edmonton', 'MST7MDT,M3.2.0,M11.1.0' },
- { 'America/Eirunepe', 'AMT4' },
- { 'America/El Salvador', 'CST6' },
- { 'America/Fortaleza', 'BRT3' },
- { 'America/Glace Bay', 'AST4ADT,M3.2.0,M11.1.0' },
- { 'America/Goose Bay', 'AST4ADT,M3.2.0,M11.1.0' },
- { 'America/Grand Turk', 'EST5EDT,M3.2.0,M11.1.0' },
- { 'America/Grenada', 'AST4' },
- { 'America/Guadeloupe', 'AST4' },
- { 'America/Guatemala', 'CST6' },
- { 'America/Guayaquil', 'ECT5' },
- { 'America/Guyana', 'GYT4' },
- { 'America/Halifax', 'AST4ADT,M3.2.0,M11.1.0' },
- { 'America/Havana', 'CST5CDT,M3.2.0/0,M10.5.0/1' },
- { 'America/Hermosillo', 'MST7' },
- { 'America/Indiana/Indianapolis', 'EST5EDT,M3.2.0,M11.1.0' },
- { 'America/Indiana/Knox', 'CST6CDT,M3.2.0,M11.1.0' },
- { 'America/Indiana/Marengo', 'EST5EDT,M3.2.0,M11.1.0' },
- { 'America/Indiana/Petersburg', 'EST5EDT,M3.2.0,M11.1.0' },
- { 'America/Indiana/Tell City', 'CST6CDT,M3.2.0,M11.1.0' },
- { 'America/Indiana/Vevay', 'EST5EDT,M3.2.0,M11.1.0' },
- { 'America/Indiana/Vincennes', 'EST5EDT,M3.2.0,M11.1.0' },
- { 'America/Indiana/Winamac', 'EST5EDT,M3.2.0,M11.1.0' },
- { 'America/Inuvik', 'MST7MDT,M3.2.0,M11.1.0' },
- { 'America/Iqaluit', 'EST5EDT,M3.2.0,M11.1.0' },
- { 'America/Jamaica', 'EST5' },
- { 'America/Juneau', 'AKST9AKDT,M3.2.0,M11.1.0' },
- { 'America/Kentucky/Louisville', 'EST5EDT,M3.2.0,M11.1.0' },
- { 'America/Kentucky/Monticello', 'EST5EDT,M3.2.0,M11.1.0' },
- { 'America/Kralendijk', 'AST4' },
- { 'America/La Paz', 'BOT4' },
- { 'America/Lima', 'PET5' },
- { 'America/Los Angeles', 'PST8PDT,M3.2.0,M11.1.0' },
- { 'America/Lower Princes', 'AST4' },
- { 'America/Maceio', 'BRT3' },
- { 'America/Managua', 'CST6' },
- { 'America/Manaus', 'AMT4' },
- { 'America/Marigot', 'AST4' },
- { 'America/Martinique', 'AST4' },
- { 'America/Matamoros', 'CST6CDT,M3.2.0,M11.1.0' },
- { 'America/Mazatlan', 'MST7MDT,M4.1.0,M10.5.0' },
- { 'America/Menominee', 'CST6CDT,M3.2.0,M11.1.0' },
- { 'America/Merida', 'CST6CDT,M4.1.0,M10.5.0' },
- { 'America/Metlakatla', 'MeST8' },
- { 'America/Mexico City', 'CST6CDT,M4.1.0,M10.5.0' },
- { 'America/Miquelon', 'PMST3PMDT,M3.2.0,M11.1.0' },
- { 'America/Moncton', 'AST4ADT,M3.2.0,M11.1.0' },
- { 'America/Monterrey', 'CST6CDT,M4.1.0,M10.5.0' },
- { 'America/Montevideo', 'UYT3UYST,M10.1.0,M3.2.0' },
- { 'America/Montreal', 'EST5EDT,M3.2.0,M11.1.0' },
- { 'America/Montserrat', 'AST4' },
- { 'America/Nassau', 'EST5EDT,M3.2.0,M11.1.0' },
- { 'America/New York', 'EST5EDT,M3.2.0,M11.1.0' },
- { 'America/Nipigon', 'EST5EDT,M3.2.0,M11.1.0' },
- { 'America/Nome', 'AKST9AKDT,M3.2.0,M11.1.0' },
- { 'America/Noronha', 'FNT2' },
- { 'America/North Dakota/Beulah', 'CST6CDT,M3.2.0,M11.1.0' },
- { 'America/North Dakota/Center', 'CST6CDT,M3.2.0,M11.1.0' },
- { 'America/North Dakota/New Salem', 'CST6CDT,M3.2.0,M11.1.0' },
- { 'America/Ojinaga', 'MST7MDT,M3.2.0,M11.1.0' },
- { 'America/Panama', 'EST5' },
- { 'America/Pangnirtung', 'EST5EDT,M3.2.0,M11.1.0' },
- { 'America/Paramaribo', 'SRT3' },
- { 'America/Phoenix', 'MST7' },
- { 'America/Port of Spain', 'AST4' },
- { 'America/Port-au-Prince', 'EST5' },
- { 'America/Porto Velho', 'AMT4' },
- { 'America/Puerto Rico', 'AST4' },
- { 'America/Rainy River', 'CST6CDT,M3.2.0,M11.1.0' },
- { 'America/Rankin Inlet', 'CST6CDT,M3.2.0,M11.1.0' },
- { 'America/Recife', 'BRT3' },
- { 'America/Regina', 'CST6' },
- { 'America/Resolute', 'CST6CDT,M3.2.0,M11.1.0' },
- { 'America/Rio Branco', 'AMT4' },
- { 'America/Santa Isabel', 'PST8PDT,M4.1.0,M10.5.0' },
- { 'America/Santarem', 'BRT3' },
- { 'America/Santo Domingo', 'AST4' },
- { 'America/Sao Paulo', 'BRT3BRST,M10.3.0/0,M2.3.0/0' },
- { 'America/Scoresbysund', 'EGT1EGST,M3.5.0/0,M10.5.0/1' },
- { 'America/Shiprock', 'MST7MDT,M3.2.0,M11.1.0' },
- { 'America/Sitka', 'AKST9AKDT,M3.2.0,M11.1.0' },
- { 'America/St Barthelemy', 'AST4' },
- { 'America/St Johns', 'NST3:30NDT,M3.2.0,M11.1.0' },
- { 'America/St Kitts', 'AST4' },
- { 'America/St Lucia', 'AST4' },
- { 'America/St Thomas', 'AST4' },
- { 'America/St Vincent', 'AST4' },
- { 'America/Swift Current', 'CST6' },
- { 'America/Tegucigalpa', 'CST6' },
- { 'America/Thule', 'AST4ADT,M3.2.0,M11.1.0' },
- { 'America/Thunder Bay', 'EST5EDT,M3.2.0,M11.1.0' },
- { 'America/Tijuana', 'PST8PDT,M3.2.0,M11.1.0' },
- { 'America/Toronto', 'EST5EDT,M3.2.0,M11.1.0' },
- { 'America/Tortola', 'AST4' },
- { 'America/Vancouver', 'PST8PDT,M3.2.0,M11.1.0' },
- { 'America/Whitehorse', 'PST8PDT,M3.2.0,M11.1.0' },
- { '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', 'WST-8' },
- { 'Antarctica/Davis', 'DAVT-7' },
- { 'Antarctica/DumontDUrville', 'DDUT-10' },
- { 'Antarctica/Macquarie', 'MIST-11' },
- { 'Antarctica/Mawson', 'MAWT-5' },
- { 'Antarctica/McMurdo', 'NZST-12NZDT,M9.5.0,M4.1.0/3' },
- { 'Antarctica/Rothera', 'ROTT3' },
- { 'Antarctica/South Pole', 'NZST-12NZDT,M9.5.0,M4.1.0/3' },
- { 'Antarctica/Syowa', 'SYOT-3' },
- { 'Antarctica/Vostok', 'VOST-6' },
- { 'Arctic/Longyearbyen', 'CET-1CEST,M3.5.0,M10.5.0/3' },
- { 'Asia/Aden', 'AST-3' },
- { 'Asia/Almaty', 'ALMT-6' },
- { 'Asia/Anadyr', 'ANAT-12' },
- { 'Asia/Aqtau', 'AQTT-5' },
- { 'Asia/Aqtobe', 'AQTT-5' },
- { 'Asia/Ashgabat', 'TMT-5' },
- { 'Asia/Baghdad', 'AST-3' },
- { 'Asia/Bahrain', 'AST-3' },
- { 'Asia/Baku', 'AZT-4AZST,M3.5.0/4,M10.5.0/5' },
- { 'Asia/Bangkok', 'ICT-7' },
- { 'Asia/Beirut', 'EET-2EEST,M3.5.0/0,M10.5.0/0' },
- { 'Asia/Bishkek', 'KGT-6' },
- { 'Asia/Brunei', 'BNT-8' },
- { 'Asia/Choibalsan', 'CHOT-8' },
- { 'Asia/Chongqing', 'CST-8' },
- { 'Asia/Colombo', 'IST-5:30' },
- { 'Asia/Damascus', 'EET-2EEST,M4.1.5/0,M10.5.5/0' },
- { 'Asia/Dhaka', 'BDT-6' },
- { 'Asia/Dili', 'TLT-9' },
- { 'Asia/Dubai', 'GST-4' },
- { 'Asia/Dushanbe', 'TJT-5' },
- { 'Asia/Gaza', 'EET-2' },
- { 'Asia/Harbin', 'CST-8' },
- { 'Asia/Hebron', 'EET-2' },
- { 'Asia/Ho Chi Minh', 'ICT-7' },
- { 'Asia/Hong Kong', 'HKT-8' },
- { 'Asia/Hovd', 'HOVT-7' },
- { 'Asia/Irkutsk', 'IRKT-9' },
- { 'Asia/Jakarta', 'WIT-7' },
- { 'Asia/Jayapura', 'EIT-9' },
- { 'Asia/Kabul', 'AFT-4:30' },
- { 'Asia/Kamchatka', 'PETT-12' },
- { 'Asia/Karachi', 'PKT-5' },
- { 'Asia/Kashgar', 'CST-8' },
- { 'Asia/Kathmandu', 'NPT-5:45' },
- { 'Asia/Kolkata', 'IST-5:30' },
- { 'Asia/Krasnoyarsk', 'KRAT-8' },
- { 'Asia/Kuala Lumpur', 'MYT-8' },
- { 'Asia/Kuching', 'MYT-8' },
- { 'Asia/Kuwait', 'AST-3' },
- { 'Asia/Macau', 'CST-8' },
- { 'Asia/Magadan', 'MAGT-12' },
- { 'Asia/Makassar', 'CIT-8' },
- { 'Asia/Manila', 'PHT-8' },
- { 'Asia/Muscat', 'GST-4' },
- { 'Asia/Nicosia', 'EET-2EEST,M3.5.0/3,M10.5.0/4' },
- { 'Asia/Novokuznetsk', 'NOVT-7' },
- { 'Asia/Novosibirsk', 'NOVT-7' },
- { 'Asia/Omsk', 'OMST-7' },
- { 'Asia/Oral', 'ORAT-5' },
- { 'Asia/Phnom Penh', 'ICT-7' },
- { 'Asia/Pontianak', 'WIT-7' },
- { 'Asia/Pyongyang', 'KST-9' },
- { 'Asia/Qatar', 'AST-3' },
- { 'Asia/Qyzylorda', 'QYZT-6' },
- { 'Asia/Rangoon', 'MMT-6:30' },
- { 'Asia/Riyadh', 'AST-3' },
- { 'Asia/Sakhalin', 'SAKT-11' },
- { 'Asia/Samarkand', 'UZT-5' },
- { 'Asia/Seoul', 'KST-9' },
- { 'Asia/Shanghai', 'CST-8' },
- { 'Asia/Singapore', 'SGT-8' },
- { 'Asia/Taipei', 'CST-8' },
- { 'Asia/Tashkent', 'UZT-5' },
- { 'Asia/Tbilisi', 'GET-4' },
- { 'Asia/Thimphu', 'BTT-6' },
- { 'Asia/Tokyo', 'JST-9' },
- { 'Asia/Ulaanbaatar', 'ULAT-8' },
- { 'Asia/Urumqi', 'CST-8' },
- { 'Asia/Vientiane', 'ICT-7' },
- { 'Asia/Vladivostok', 'VLAT-11' },
- { 'Asia/Yakutsk', 'YAKT-10' },
- { 'Asia/Yekaterinburg', 'YEKT-6' },
- { 'Asia/Yerevan', 'AMT-4AMST,M3.5.0,M10.5.0/3' },
- { 'Atlantic/Azores', 'AZOT1AZOST,M3.5.0/0,M10.5.0/1' },
- { 'Atlantic/Bermuda', 'AST4ADT,M3.2.0,M11.1.0' },
- { 'Atlantic/Canary', 'WET0WEST,M3.5.0/1,M10.5.0' },
- { 'Atlantic/Cape Verde', 'CVT1' },
- { 'Atlantic/Faroe', 'WET0WEST,M3.5.0/1,M10.5.0' },
- { 'Atlantic/Madeira', 'WET0WEST,M3.5.0/1,M10.5.0' },
- { 'Atlantic/Reykjavik', 'GMT0' },
- { 'Atlantic/South Georgia', 'GST2' },
- { 'Atlantic/St Helena', 'GMT0' },
- { 'Atlantic/Stanley', 'FKT4FKST,M9.1.0,M4.3.0' },
- { 'Australia/Adelaide', 'CST-9:30CST,M10.1.0,M4.1.0/3' },
- { 'Australia/Brisbane', 'EST-10' },
- { 'Australia/Broken Hill', 'CST-9:30CST,M10.1.0,M4.1.0/3' },
- { 'Australia/Currie', 'EST-10EST,M10.1.0,M4.1.0/3' },
- { 'Australia/Darwin', 'CST-9:30' },
- { 'Australia/Eucla', 'CWST-8:45' },
- { 'Australia/Hobart', 'EST-10EST,M10.1.0,M4.1.0/3' },
- { 'Australia/Lindeman', 'EST-10' },
- { 'Australia/Lord Howe', 'LHST-10:30LHST-11,M10.1.0,M4.1.0' },
- { 'Australia/Melbourne', 'EST-10EST,M10.1.0,M4.1.0/3' },
- { 'Australia/Perth', 'WST-8' },
- { 'Australia/Sydney', 'EST-10EST,M10.1.0,M4.1.0/3' },
- { 'Europe/Amsterdam', 'CET-1CEST,M3.5.0,M10.5.0/3' },
- { 'Europe/Andorra', 'CET-1CEST,M3.5.0,M10.5.0/3' },
- { 'Europe/Athens', 'EET-2EEST,M3.5.0/3,M10.5.0/4' },
- { 'Europe/Belgrade', 'CET-1CEST,M3.5.0,M10.5.0/3' },
- { 'Europe/Berlin', 'CET-1CEST,M3.5.0,M10.5.0/3' },
- { 'Europe/Bratislava', 'CET-1CEST,M3.5.0,M10.5.0/3' },
- { 'Europe/Brussels', 'CET-1CEST,M3.5.0,M10.5.0/3' },
- { 'Europe/Bucharest', 'EET-2EEST,M3.5.0/3,M10.5.0/4' },
- { 'Europe/Budapest', 'CET-1CEST,M3.5.0,M10.5.0/3' },
- { 'Europe/Chisinau', 'EET-2EEST,M3.5.0/3,M10.5.0/4' },
- { 'Europe/Copenhagen', 'CET-1CEST,M3.5.0,M10.5.0/3' },
- { 'Europe/Dublin', 'GMT0IST,M3.5.0/1,M10.5.0' },
- { 'Europe/Gibraltar', 'CET-1CEST,M3.5.0,M10.5.0/3' },
- { 'Europe/Guernsey', 'GMT0BST,M3.5.0/1,M10.5.0' },
- { 'Europe/Helsinki', 'EET-2EEST,M3.5.0/3,M10.5.0/4' },
- { 'Europe/Isle of Man', 'GMT0BST,M3.5.0/1,M10.5.0' },
- { 'Europe/Istanbul', 'EET-2EEST,M3.5.0/3,M10.5.0/4' },
- { 'Europe/Jersey', 'GMT0BST,M3.5.0/1,M10.5.0' },
- { 'Europe/Kaliningrad', 'FET-3' },
- { 'Europe/Kiev', 'EET-2EEST,M3.5.0/3,M10.5.0/4' },
- { 'Europe/Lisbon', 'WET0WEST,M3.5.0/1,M10.5.0' },
- { 'Europe/Ljubljana', 'CET-1CEST,M3.5.0,M10.5.0/3' },
- { 'Europe/London', 'GMT0BST,M3.5.0/1,M10.5.0' },
- { 'Europe/Luxembourg', 'CET-1CEST,M3.5.0,M10.5.0/3' },
- { 'Europe/Madrid', 'CET-1CEST,M3.5.0,M10.5.0/3' },
- { 'Europe/Malta', 'CET-1CEST,M3.5.0,M10.5.0/3' },
- { 'Europe/Mariehamn', 'EET-2EEST,M3.5.0/3,M10.5.0/4' },
- { 'Europe/Minsk', 'FET-3' },
- { 'Europe/Monaco', 'CET-1CEST,M3.5.0,M10.5.0/3' },
- { 'Europe/Moscow', 'MSK-4' },
- { 'Europe/Oslo', 'CET-1CEST,M3.5.0,M10.5.0/3' },
- { 'Europe/Paris', 'CET-1CEST,M3.5.0,M10.5.0/3' },
- { 'Europe/Podgorica', 'CET-1CEST,M3.5.0,M10.5.0/3' },
- { 'Europe/Prague', 'CET-1CEST,M3.5.0,M10.5.0/3' },
- { 'Europe/Riga', 'EET-2EEST,M3.5.0/3,M10.5.0/4' },
- { 'Europe/Rome', 'CET-1CEST,M3.5.0,M10.5.0/3' },
- { 'Europe/Samara', 'SAMT-4' },
- { 'Europe/San Marino', 'CET-1CEST,M3.5.0,M10.5.0/3' },
- { 'Europe/Sarajevo', 'CET-1CEST,M3.5.0,M10.5.0/3' },
- { 'Europe/Simferopol', 'EET-2EEST,M3.5.0/3,M10.5.0/4' },
- { 'Europe/Skopje', 'CET-1CEST,M3.5.0,M10.5.0/3' },
- { 'Europe/Sofia', 'EET-2EEST,M3.5.0/3,M10.5.0/4' },
- { 'Europe/Stockholm', 'CET-1CEST,M3.5.0,M10.5.0/3' },
- { 'Europe/Tallinn', 'EET-2EEST,M3.5.0/3,M10.5.0/4' },
- { 'Europe/Tirane', 'CET-1CEST,M3.5.0,M10.5.0/3' },
- { 'Europe/Uzhgorod', 'EET-2EEST,M3.5.0/3,M10.5.0/4' },
- { 'Europe/Vaduz', 'CET-1CEST,M3.5.0,M10.5.0/3' },
- { 'Europe/Vatican', 'CET-1CEST,M3.5.0,M10.5.0/3' },
- { 'Europe/Vienna', 'CET-1CEST,M3.5.0,M10.5.0/3' },
- { 'Europe/Vilnius', 'EET-2EEST,M3.5.0/3,M10.5.0/4' },
- { 'Europe/Volgograd', 'VOLT-4' },
- { 'Europe/Warsaw', 'CET-1CEST,M3.5.0,M10.5.0/3' },
- { 'Europe/Zagreb', 'CET-1CEST,M3.5.0,M10.5.0/3' },
- { 'Europe/Zaporozhye', 'EET-2EEST,M3.5.0/3,M10.5.0/4' },
- { 'Europe/Zurich', 'CET-1CEST,M3.5.0,M10.5.0/3' },
- { 'Indian/Antananarivo', 'EAT-3' },
- { 'Indian/Chagos', 'IOT-6' },
- { 'Indian/Christmas', 'CXT-7' },
- { 'Indian/Cocos', 'CCT-6:30' },
- { 'Indian/Comoro', 'EAT-3' },
- { 'Indian/Kerguelen', 'TFT-5' },
- { 'Indian/Mahe', 'SCT-4' },
- { 'Indian/Maldives', 'MVT-5' },
- { 'Indian/Mauritius', 'MUT-4' },
- { 'Indian/Mayotte', 'EAT-3' },
- { 'Indian/Reunion', 'RET-4' },
- { 'Pacific/Apia', 'WST-13' },
- { 'Pacific/Auckland', 'NZST-12NZDT,M9.5.0,M4.1.0/3' },
- { 'Pacific/Chatham', 'CHAST-12:45CHADT,M9.5.0/2:45,M4.1.0/3:45' },
- { 'Pacific/Chuuk', 'CHUT-10' },
- { 'Pacific/Efate', 'VUT-11' },
- { 'Pacific/Enderbury', 'PHOT-13' },
- { 'Pacific/Fakaofo', 'TKT10' },
- { 'Pacific/Fiji', 'FJT-12' },
- { 'Pacific/Funafuti', 'TVT-12' },
- { 'Pacific/Galapagos', 'GALT6' },
- { 'Pacific/Gambier', 'GAMT9' },
- { 'Pacific/Guadalcanal', 'SBT-11' },
- { 'Pacific/Guam', 'ChST-10' },
- { 'Pacific/Honolulu', 'HST10' },
- { 'Pacific/Johnston', 'HST10' },
- { 'Pacific/Kiritimati', 'LINT-14' },
- { 'Pacific/Kosrae', 'KOST-11' },
- { 'Pacific/Kwajalein', 'MHT-12' },
- { 'Pacific/Majuro', 'MHT-12' },
- { 'Pacific/Marquesas', 'MART9:30' },
- { 'Pacific/Midway', 'SST11' },
- { 'Pacific/Nauru', 'NRT-12' },
- { 'Pacific/Niue', 'NUT11' },
- { 'Pacific/Norfolk', 'NFT-11:30' },
- { 'Pacific/Noumea', 'NCT-11' },
- { 'Pacific/Pago Pago', 'SST11' },
- { 'Pacific/Palau', 'PWT-9' },
- { 'Pacific/Pitcairn', 'PST8' },
- { 'Pacific/Pohnpei', 'PONT-11' },
- { 'Pacific/Port Moresby', 'PGT-10' },
- { 'Pacific/Rarotonga', 'CKT10' },
- { 'Pacific/Saipan', 'ChST-10' },
- { 'Pacific/Tahiti', 'TAHT10' },
- { 'Pacific/Tarawa', 'GILT-12' },
- { 'Pacific/Tongatapu', 'TOT-13' },
- { 'Pacific/Wake', 'WAKT-12' },
- { 'Pacific/Wallis', 'WFT-12' },
-}
diff --git a/libs/sys/luasrc/sys/zoneinfo/tzoffset.lua b/libs/sys/luasrc/sys/zoneinfo/tzoffset.lua
deleted file mode 100644
index bbe75d5a47..0000000000
--- a/libs/sys/luasrc/sys/zoneinfo/tzoffset.lua
+++ /dev/null
@@ -1,162 +0,0 @@
---[[
-LuCI - Autogenerated Zoneinfo Module
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-]]--
-
-module "luci.sys.zoneinfo.tzoffset"
-
-OFFSET = {
- gmt = 0, -- GMT
- eat = 10800, -- EAT
- cet = 3600, -- CET
- wat = 3600, -- WAT
- cat = 7200, -- CAT
- wet = 0, -- WET
- sast = 7200, -- SAST
- eet = 7200, -- EET
- hast = -36000, -- HAST
- hadt = -32400, -- HADT
- akst = -32400, -- AKST
- akdt = -28800, -- AKDT
- ast = -14400, -- AST
- brt = -10800, -- BRT
- art = -10800, -- ART
- pyt = -14400, -- PYT
- pyst = -10800, -- PYST
- est = -18000, -- EST
- cst = -21600, -- CST
- cdt = -18000, -- CDT
- amt = -14400, -- AMT
- cot = -18000, -- COT
- mst = -25200, -- MST
- mdt = -21600, -- MDT
- vet = -16200, -- VET
- gft = -10800, -- GFT
- pst = -28800, -- PST
- pdt = -25200, -- PDT
- ect = -18000, -- ECT
- gyt = -14400, -- GYT
- bot = -14400, -- BOT
- pet = -18000, -- PET
- pmst = -10800, -- PMST
- pmdt = -7200, -- PMDT
- uyt = -10800, -- UYT
- uyst = -7200, -- UYST
- fnt = -7200, -- FNT
- srt = -10800, -- SRT
- egt = -3600, -- EGT
- egst = 0, -- EGST
- nst = -12600, -- NST
- ndt = -9000, -- NDT
- wst = 28800, -- WST
- davt = 25200, -- DAVT
- ddut = 36000, -- DDUT
- mist = 39600, -- MIST
- mawt = 18000, -- MAWT
- nzst = 43200, -- NZST
- nzdt = 46800, -- NZDT
- rott = -10800, -- ROTT
- syot = 10800, -- SYOT
- vost = 21600, -- VOST
- almt = 21600, -- ALMT
- anat = 43200, -- ANAT
- aqtt = 18000, -- AQTT
- tmt = 18000, -- TMT
- azt = 14400, -- AZT
- azst = 18000, -- AZST
- ict = 25200, -- ICT
- kgt = 21600, -- KGT
- bnt = 28800, -- BNT
- chot = 28800, -- CHOT
- ist = 19800, -- IST
- bdt = 21600, -- BDT
- tlt = 32400, -- TLT
- gst = 14400, -- GST
- tjt = 18000, -- TJT
- hkt = 28800, -- HKT
- hovt = 25200, -- HOVT
- irkt = 32400, -- IRKT
- wit = 25200, -- WIT
- eit = 32400, -- EIT
- aft = 16200, -- AFT
- pett = 43200, -- PETT
- pkt = 18000, -- PKT
- npt = 20700, -- NPT
- krat = 28800, -- KRAT
- myt = 28800, -- MYT
- magt = 43200, -- MAGT
- cit = 28800, -- CIT
- pht = 28800, -- PHT
- novt = 25200, -- NOVT
- omst = 25200, -- OMST
- orat = 18000, -- ORAT
- kst = 32400, -- KST
- qyzt = 21600, -- QYZT
- mmt = 23400, -- MMT
- sakt = 39600, -- SAKT
- uzt = 18000, -- UZT
- sgt = 28800, -- SGT
- get = 14400, -- GET
- btt = 21600, -- BTT
- jst = 32400, -- JST
- ulat = 28800, -- ULAT
- vlat = 39600, -- VLAT
- yakt = 36000, -- YAKT
- yekt = 21600, -- YEKT
- azot = -3600, -- AZOT
- azost = 0, -- AZOST
- cvt = -3600, -- CVT
- fkt = -14400, -- FKT
- fkst = -10800, -- FKST
- cwst = 31500, -- CWST
- lhst = 37800, -- LHST
- lhst = 39600, -- LHST
- fet = 10800, -- FET
- msk = 14400, -- MSK
- samt = 14400, -- SAMT
- volt = 14400, -- VOLT
- iot = 21600, -- IOT
- cxt = 25200, -- CXT
- cct = 23400, -- CCT
- tft = 18000, -- TFT
- sct = 14400, -- SCT
- mvt = 18000, -- MVT
- mut = 14400, -- MUT
- ret = 14400, -- RET
- chast = 45900, -- CHAST
- chadt = 49500, -- CHADT
- chut = 36000, -- CHUT
- vut = 39600, -- VUT
- phot = 46800, -- PHOT
- tkt = -36000, -- TKT
- fjt = 43200, -- FJT
- tvt = 43200, -- TVT
- galt = -21600, -- GALT
- gamt = -32400, -- GAMT
- sbt = 39600, -- SBT
- hst = -36000, -- HST
- lint = 50400, -- LINT
- kost = 39600, -- KOST
- mht = 43200, -- MHT
- mart = -34200, -- MART
- sst = -39600, -- SST
- nrt = 43200, -- NRT
- nut = -39600, -- NUT
- nft = 41400, -- NFT
- nct = 39600, -- NCT
- pwt = 32400, -- PWT
- pont = 39600, -- PONT
- pgt = 36000, -- PGT
- ckt = -36000, -- CKT
- taht = -36000, -- TAHT
- gilt = 43200, -- GILT
- tot = 46800, -- TOT
- wakt = 43200, -- WAKT
- wft = 43200, -- WFT
-}