diff --git a/ipk-source/libucode20230711_aarch64_cortex-a53/CONTROL/control b/ipk-source/libucode20230711_aarch64_cortex-a53/CONTROL/control new file mode 100644 index 0000000..a39e74e --- /dev/null +++ b/ipk-source/libucode20230711_aarch64_cortex-a53/CONTROL/control @@ -0,0 +1,14 @@ +Package: libucode20230711 +Version: 2024.07.22~b610860d-r3 +Depends: libc, libjson-c5 +Provides: libucode +Source: feeds/base/package/utils/ucode +SourceName: ucode +License: ISC +Section: libs +SourceDateEpoch: 1729600843 +ABIVersion: 20230711 +Maintainer: Jo-Philipp Wich +Architecture: aarch64_cortex-a53 +Installed-Size: 204800 +Description: The libucode package provides the shared runtime library for the ucode interpreter. diff --git a/ipk-source/libucode20230711_aarch64_cortex-a53/CONTROL/postinst b/ipk-source/libucode20230711_aarch64_cortex-a53/CONTROL/postinst new file mode 100755 index 0000000..3bba77c --- /dev/null +++ b/ipk-source/libucode20230711_aarch64_cortex-a53/CONTROL/postinst @@ -0,0 +1,5 @@ +#!/bin/sh +[ "${IPKG_NO_SCRIPT}" = "1" ] && exit 0 +[ -s ${IPKG_INSTROOT}/lib/functions.sh ] || exit 0 +. ${IPKG_INSTROOT}/lib/functions.sh +default_postinst $0 $@ diff --git a/ipk-source/libucode20230711_aarch64_cortex-a53/CONTROL/prerm b/ipk-source/libucode20230711_aarch64_cortex-a53/CONTROL/prerm new file mode 100755 index 0000000..12d06ec --- /dev/null +++ b/ipk-source/libucode20230711_aarch64_cortex-a53/CONTROL/prerm @@ -0,0 +1,4 @@ +#!/bin/sh +[ -s ${IPKG_INSTROOT}/lib/functions.sh ] || exit 0 +. ${IPKG_INSTROOT}/lib/functions.sh +default_prerm $0 $@ diff --git a/ipk-source/libucode20230711_aarch64_cortex-a53/build-ipk b/ipk-source/libucode20230711_aarch64_cortex-a53/build-ipk new file mode 100755 index 0000000..eb83cf6 --- /dev/null +++ b/ipk-source/libucode20230711_aarch64_cortex-a53/build-ipk @@ -0,0 +1,74 @@ +#!/bin/sh + +# Script for building OpenWRT .ipk packages using tar by iamromulan +# Works with SDXPPINN OpenWRT - iamromulan +# This script accepts an optional path to the directory containing the `CONTROL` and `root` directories. +# Usage: ./build-ipk.sh [path] +# If no path is provided, the script will look in the current directory for `CONTROL` and `root` directories. +# This will spit out an ipk in the current directory + +# Check if the script is run as root. If not, rerun with sudo. +if [ "$(id -u)" -ne 0 ]; then + echo "Script is not running as root. Re-executing with sudo..." + exec sudo "$0" "$@" +fi + +# Set the default build path to the current directory +build_path="." + +# Check if a path is provided as the first argument +if [ "$1" ]; then + build_path="$1" +fi + +# Check if the required directories are present in the specified path +if [ ! -d "${build_path}/CONTROL" ] || [ ! -d "${build_path}/root" ]; then + echo "Error: CONTROL and root directories must be present in the specified path (${build_path})." + exit 1 +fi + +# Extract values from the CONTROL/control file in the specified path +pkgname=$(grep -i '^Package:' "${build_path}/CONTROL/control" | awk '{print $2}') +version=$(grep -i '^Version:' "${build_path}/CONTROL/control" | awk '{print $2}') +architecture=$(grep -i '^Architecture:' "${build_path}/CONTROL/control" | awk '{print $2}') + +# Check if values are extracted correctly +if [ -z "$pkgname" ] || [ -z "$version" ] || [ -z "$architecture" ]; then + echo "Error: Failed to extract Package, Version, or Architecture from ${build_path}/CONTROL/control." + exit 1 +fi + +# Set the final IPK name based on the extracted values +ipkname="${pkgname}_${version}_${architecture}.ipk" + +# Ensure all CONTROL scripts are executable +echo "Setting permissions for CONTROL scripts..." +chmod +x "${build_path}/CONTROL"/* + +# Set ownership for CONTROL and root files +echo "Setting ownership for all package files..." +chown -R root:root "${build_path}/CONTROL"/* +chown -R root:root "${build_path}/root"/* + +# Create control.tar.gz from the CONTROL directory +echo "Creating control.tar.gz..." +tar -czvf control.tar.gz -C "${build_path}/CONTROL" . + +# Create data.tar.gz from the root directory +echo "Creating data.tar.gz..." +tar -czvf data.tar.gz -C "${build_path}/root" . + +# Create debian-binary file (must contain exactly "2.0" without a newline) +echo -n "2.0" > debian-binary +chown -R root:root debian-binary + +# Combine the components into the final .ipk file using tar +echo "Packaging ${ipkname}..." +tar -czvf "$ipkname" debian-binary control.tar.gz data.tar.gz + +# Clean up intermediate files +echo "Cleaning up temporary files..." +rm -f control.tar.gz data.tar.gz debian-binary + +echo "IPK package ${ipkname} created successfully using tar." + diff --git a/ipk-source/libucode20230711_aarch64_cortex-a53/root/usr/lib/libucode.so.20230711 b/ipk-source/libucode20230711_aarch64_cortex-a53/root/usr/lib/libucode.so.20230711 new file mode 100644 index 0000000..f17cd38 Binary files /dev/null and b/ipk-source/libucode20230711_aarch64_cortex-a53/root/usr/lib/libucode.so.20230711 differ diff --git a/ipk-source/luci-app-argon-config/CONTROL/conffiles b/ipk-source/luci-app-argon-config/CONTROL/conffiles new file mode 100644 index 0000000..bc3a0e2 --- /dev/null +++ b/ipk-source/luci-app-argon-config/CONTROL/conffiles @@ -0,0 +1 @@ +/etc/config/argon diff --git a/ipk-source/luci-app-argon-config/CONTROL/control b/ipk-source/luci-app-argon-config/CONTROL/control new file mode 100644 index 0000000..15b607d --- /dev/null +++ b/ipk-source/luci-app-argon-config/CONTROL/control @@ -0,0 +1,11 @@ +Package: luci-app-argon-config +Version: 0.9 +Depends: libc, luci-compat +Source: /home/runner/work/gl-sdk-action/gl-sdk-action/buildsource/luci-app-argon-config +SourceName: luci-app-argon-config +Section: luci +SourceDateEpoch: 1650782942 +Maintainer: OpenWrt LuCI community +Architecture: all +Installed-Size: 3586 +Description: LuCI page for Argon Config diff --git a/ipk-source/luci-app-argon-config/CONTROL/postinst b/ipk-source/luci-app-argon-config/CONTROL/postinst new file mode 100755 index 0000000..3bba77c --- /dev/null +++ b/ipk-source/luci-app-argon-config/CONTROL/postinst @@ -0,0 +1,5 @@ +#!/bin/sh +[ "${IPKG_NO_SCRIPT}" = "1" ] && exit 0 +[ -s ${IPKG_INSTROOT}/lib/functions.sh ] || exit 0 +. ${IPKG_INSTROOT}/lib/functions.sh +default_postinst $0 $@ diff --git a/ipk-source/luci-app-argon-config/CONTROL/postinst-pkg b/ipk-source/luci-app-argon-config/CONTROL/postinst-pkg new file mode 100755 index 0000000..ecfe266 --- /dev/null +++ b/ipk-source/luci-app-argon-config/CONTROL/postinst-pkg @@ -0,0 +1,7 @@ +[ -n "${IPKG_INSTROOT}" ] || { + (. /etc/uci-defaults/luci-argon-config) && rm -f /etc/uci-defaults/luci-argon-config + rm -f /tmp/luci-indexcache + rm -rf /tmp/luci-modulecache/ + killall -HUP rpcd 2>/dev/null + exit 0 +} diff --git a/ipk-source/luci-app-argon-config/CONTROL/prerm b/ipk-source/luci-app-argon-config/CONTROL/prerm new file mode 100755 index 0000000..12d06ec --- /dev/null +++ b/ipk-source/luci-app-argon-config/CONTROL/prerm @@ -0,0 +1,4 @@ +#!/bin/sh +[ -s ${IPKG_INSTROOT}/lib/functions.sh ] || exit 0 +. ${IPKG_INSTROOT}/lib/functions.sh +default_prerm $0 $@ diff --git a/ipk-source/luci-app-argon-config/build-ipk b/ipk-source/luci-app-argon-config/build-ipk new file mode 100755 index 0000000..eb83cf6 --- /dev/null +++ b/ipk-source/luci-app-argon-config/build-ipk @@ -0,0 +1,74 @@ +#!/bin/sh + +# Script for building OpenWRT .ipk packages using tar by iamromulan +# Works with SDXPPINN OpenWRT - iamromulan +# This script accepts an optional path to the directory containing the `CONTROL` and `root` directories. +# Usage: ./build-ipk.sh [path] +# If no path is provided, the script will look in the current directory for `CONTROL` and `root` directories. +# This will spit out an ipk in the current directory + +# Check if the script is run as root. If not, rerun with sudo. +if [ "$(id -u)" -ne 0 ]; then + echo "Script is not running as root. Re-executing with sudo..." + exec sudo "$0" "$@" +fi + +# Set the default build path to the current directory +build_path="." + +# Check if a path is provided as the first argument +if [ "$1" ]; then + build_path="$1" +fi + +# Check if the required directories are present in the specified path +if [ ! -d "${build_path}/CONTROL" ] || [ ! -d "${build_path}/root" ]; then + echo "Error: CONTROL and root directories must be present in the specified path (${build_path})." + exit 1 +fi + +# Extract values from the CONTROL/control file in the specified path +pkgname=$(grep -i '^Package:' "${build_path}/CONTROL/control" | awk '{print $2}') +version=$(grep -i '^Version:' "${build_path}/CONTROL/control" | awk '{print $2}') +architecture=$(grep -i '^Architecture:' "${build_path}/CONTROL/control" | awk '{print $2}') + +# Check if values are extracted correctly +if [ -z "$pkgname" ] || [ -z "$version" ] || [ -z "$architecture" ]; then + echo "Error: Failed to extract Package, Version, or Architecture from ${build_path}/CONTROL/control." + exit 1 +fi + +# Set the final IPK name based on the extracted values +ipkname="${pkgname}_${version}_${architecture}.ipk" + +# Ensure all CONTROL scripts are executable +echo "Setting permissions for CONTROL scripts..." +chmod +x "${build_path}/CONTROL"/* + +# Set ownership for CONTROL and root files +echo "Setting ownership for all package files..." +chown -R root:root "${build_path}/CONTROL"/* +chown -R root:root "${build_path}/root"/* + +# Create control.tar.gz from the CONTROL directory +echo "Creating control.tar.gz..." +tar -czvf control.tar.gz -C "${build_path}/CONTROL" . + +# Create data.tar.gz from the root directory +echo "Creating data.tar.gz..." +tar -czvf data.tar.gz -C "${build_path}/root" . + +# Create debian-binary file (must contain exactly "2.0" without a newline) +echo -n "2.0" > debian-binary +chown -R root:root debian-binary + +# Combine the components into the final .ipk file using tar +echo "Packaging ${ipkname}..." +tar -czvf "$ipkname" debian-binary control.tar.gz data.tar.gz + +# Clean up intermediate files +echo "Cleaning up temporary files..." +rm -f control.tar.gz data.tar.gz debian-binary + +echo "IPK package ${ipkname} created successfully using tar." + diff --git a/ipk-source/luci-app-argon-config/root/etc/config/argon b/ipk-source/luci-app-argon-config/root/etc/config/argon new file mode 100644 index 0000000..fb7f35d --- /dev/null +++ b/ipk-source/luci-app-argon-config/root/etc/config/argon @@ -0,0 +1,9 @@ +config global + option primary '#5e72e4' + option dark_primary '#483d8b' + option blur '10' + option blur_dark '10' + option transparency '0.5' + option transparency_dark '0.5' + option mode 'normal' + option bing_background '0' diff --git a/ipk-source/luci-app-argon-config/root/etc/uci-defaults/luci-argon-config b/ipk-source/luci-app-argon-config/root/etc/uci-defaults/luci-argon-config new file mode 100755 index 0000000..935d7c8 --- /dev/null +++ b/ipk-source/luci-app-argon-config/root/etc/uci-defaults/luci-argon-config @@ -0,0 +1,6 @@ +#!/bin/sh + +sed -i 's/cbi.submit\"] = true/cbi.submit\"] = \"1\"/g' /usr/lib/lua/luci/dispatcher.lua + +rm -f /tmp/luci-indexcache +exit 0 diff --git a/ipk-source/luci-app-argon-config/root/usr/lib/lua/luci/controller/argon-config.lua b/ipk-source/luci-app-argon-config/root/usr/lib/lua/luci/controller/argon-config.lua new file mode 100644 index 0000000..5d7faf4 --- /dev/null +++ b/ipk-source/luci-app-argon-config/root/usr/lib/lua/luci/controller/argon-config.lua @@ -0,0 +1,10 @@ +module("luci.controller.argon-config", package.seeall) + +function index() + if not nixio.fs.access('/www/luci-static/argon/css/cascade.css') then + return + end + + local page = entry({"admin", "system", "argon-config"}, form("argon-config"), _("Argon Config"), 90) + page.acl_depends = { "luci-app-argon-config" } +end diff --git a/ipk-source/luci-app-argon-config/root/usr/lib/lua/luci/model/cbi/argon-config.lua b/ipk-source/luci-app-argon-config/root/usr/lib/lua/luci/model/cbi/argon-config.lua new file mode 100644 index 0000000..19e9aee --- /dev/null +++ b/ipk-source/luci-app-argon-config/root/usr/lib/lua/luci/model/cbi/argon-config.lua @@ -0,0 +1,217 @@ +local nxfs = require 'nixio.fs' +local wa = require 'luci.tools.webadmin' +local opkg = require 'luci.model.ipkg' +local sys = require 'luci.sys' +local http = require 'luci.http' +local nutil = require 'nixio.util' +local name = 'argon' +local uci = require 'luci.model.uci'.cursor() + +local fstat = nxfs.statvfs(opkg.overlay_root()) +local space_total = fstat and fstat.blocks or 0 +local space_free = fstat and fstat.bfree or 0 +local space_used = space_total - space_free + +local free_byte = space_free * fstat.frsize + +local primary, dark_primary, blur_radius, blur_radius_dark, blur_opacity, mode +if nxfs.access('/etc/config/argon') then + primary = uci:get_first('argon', 'global', 'primary') + dark_primary = uci:get_first('argon', 'global', 'dark_primary') + blur_radius = uci:get_first('argon', 'global', 'blur') + blur_radius_dark = uci:get_first('argon', 'global', 'blur_dark') + blur_opacity = uci:get_first('argon', 'global', 'transparency') + blur_opacity_dark = uci:get_first('argon', 'global', 'transparency_dark') + mode = uci:get_first('argon', 'global', 'mode') + bing_background = uci:get_first('argon', 'global', 'bing_background') +end + +function glob(...) + local iter, code, msg = nxfs.glob(...) + if iter then + return nutil.consume(iter) + else + return nil, code, msg + end +end + +local transparency_sets = { + 0, + 0.1, + 0.2, + 0.3, + 0.4, + 0.5, + 0.6, + 0.7, + 0.8, + 0.9, + 1 +} + +-- [[ 模糊设置 ]]-- +br = SimpleForm('config', translate('Argon Config'), translate('Here you can set the blur and transparency of the login page of argon theme, and manage the background pictures and videos.[Chrome is recommended]')) +br.reset = false +br.submit = false +s = br:section(SimpleSection) + +o = s:option(ListValue, 'bing_background', translate('Wallpaper Source')) +o:value('0', translate('Built-in')) +o:value('1', translate('Bing Wallpapers')) +o.default = bing_background +o.rmempty = false + +o = s:option(ListValue, 'mode', translate('Theme mode')) +o:value('normal', translate('Follow System')) +o:value('light', translate('Force Light')) +o:value('dark', translate('Force Dark')) +o.default = mode +o.rmempty = false +o.description = translate('You can choose Theme color mode here') + +o = s:option(Value, 'primary', translate('[Light mode] Primary Color'), translate('A HEX Color ; ( Default: #5e72e4 )')) +o.default = primary +o.datatype = ufloat +o.rmempty = false + + + +o = s:option(ListValue, 'transparency', translate('[Light mode] Transparency'), translate('0 transparent - 1 opaque ; ( Suggest: transparent: 0 or translucent preset: 0.5 )')) +for _, v in ipairs(transparency_sets) do + o:value(v) +end +o.default = blur_opacity +o.datatype = ufloat +o.rmempty = false + +o = s:option(Value, 'blur', translate('[Light mode] Frosted Glass Radius'), translate('Larger value will more blurred ; ( Suggest: clear: 1 or blur preset: 10 )')) +o.default = blur_radius +o.datatype = ufloat +o.rmempty = false + +o = s:option(Value, 'dark_primary', translate('[Dark mode] Primary Color'), translate('A HEX Color ; ( Default: #483d8b )')) +o.default = dark_primary +o.datatype = ufloat +o.rmempty = false + +o = s:option(ListValue, 'transparency_dark', translate('[Dark mode] Transparency'), translate('0 transparent - 1 opaque ; ( Suggest: Black translucent preset: 0.5 )')) +for _, v in ipairs(transparency_sets) do + o:value(v) +end +o.default = blur_opacity_dark +o.datatype = ufloat +o.rmempty = false + +o = s:option(Value, 'blur_dark', translate('[Dark mode] Frosted Glass Radius'), translate('Larger value will more blurred ; ( Suggest: clear: 1 or blur preset: 10 )')) +o.default = blur_radius_dark +o.datatype = ufloat +o.rmempty = false + +o = s:option(Button, 'save', translate('Save Changes')) +o.inputstyle = 'reload' + +function br.handle(self, state, data) + if (state == FORM_VALID and data.blur ~= nil and data.blur_dark ~= nil and data.transparency ~= nil and data.transparency_dark ~= nil and data.mode ~= nil) then + nxfs.writefile('/tmp/aaa', data) + for key, value in pairs(data) do + uci:set('argon','@global[0]',key,value) + end + uci:commit('argon') + end + return true +end + +ful = SimpleForm('upload', translate('Upload (Free: ') .. wa.byte_format(free_byte) .. ')', translate("You can upload files such as jpg,png,gif,mp4,webm files, To change the login page background.")) +ful.reset = false +ful.submit = false + +sul = ful:section(SimpleSection, '', translate("Upload file to '/www/luci-static/argon/background/'")) +fu = sul:option(FileUpload, '') +fu.template = 'argon-config/other_upload' +um = sul:option(DummyValue, '', nil) +um.template = 'argon-config/other_dvalue' + +local dir, fd +dir = '/www/luci-static/argon/background/' +nxfs.mkdir(dir) +http.setfilehandler( + function(meta, chunk, eof) + if not fd then + if not meta then + return + end + + if meta and chunk then + fd = nixio.open(dir .. meta.file, 'w') + end + + if not fd then + um.value = translate('Create upload file error.') + return + end + end + if chunk and fd then + fd:write(chunk) + end + if eof and fd then + fd:close() + fd = nil + um.value = translate('File saved to') .. ' "/www/luci-static/argon/background/' .. meta.file .. '"' + end + end +) + +if http.formvalue('upload') then + local f = http.formvalue('ulfile') + if #f <= 0 then + um.value = translate('No specify upload file.') + end +end + +local function getSizeStr(size) + local i = 0 + local byteUnits = {' kB', ' MB', ' GB', ' TB'} + repeat + size = size / 1024 + i = i + 1 + until (size <= 1024) + return string.format('%.1f', size) .. byteUnits[i] +end + +local inits, attr = {} +for i, f in ipairs(glob(dir .. '*')) do + attr = nxfs.stat(f) + if attr then + inits[i] = {} + inits[i].name = nxfs.basename(f) + inits[i].mtime = os.date('%Y-%m-%d %H:%M:%S', attr.mtime) + inits[i].modestr = attr.modestr + inits[i].size = getSizeStr(attr.size) + inits[i].remove = 0 + inits[i].install = false + end +end + +form = SimpleForm('filelist', translate('Background file list'), nil) +form.reset = false +form.submit = false + +tb = form:section(Table, inits) +nm = tb:option(DummyValue, 'name', translate('File name')) +mt = tb:option(DummyValue, 'mtime', translate('Modify time')) +sz = tb:option(DummyValue, 'size', translate('Size')) +btnrm = tb:option(Button, 'remove', translate('Remove')) +btnrm.render = function(self, section, scope) + self.inputstyle = 'remove' + Button.render(self, section, scope) +end + +btnrm.write = function(self, section) + local v = nxfs.unlink(dir .. nxfs.basename(inits[section].name)) + if v then + table.remove(inits, section) + end + return v +end + +return br, ful, form diff --git a/ipk-source/luci-app-argon-config/root/usr/lib/lua/luci/view/argon-config/other_button.htm b/ipk-source/luci-app-argon-config/root/usr/lib/lua/luci/view/argon-config/other_button.htm new file mode 100644 index 0000000..1c391ad --- /dev/null +++ b/ipk-source/luci-app-argon-config/root/usr/lib/lua/luci/view/argon-config/other_button.htm @@ -0,0 +1,7 @@ +<%+cbi/valueheader%> + <% if self:cfgvalue(section) ~= false then %> + " style="display: <%= display %>" type="submit"<%= attr("name", cbid) .. attr("id", cbid) .. attr("value", self.inputtitle or self.title)%> /> + <% else %> + - + <% end %> +<%+cbi/valuefooter%> diff --git a/ipk-source/luci-app-argon-config/root/usr/lib/lua/luci/view/argon-config/other_dvalue.htm b/ipk-source/luci-app-argon-config/root/usr/lib/lua/luci/view/argon-config/other_dvalue.htm new file mode 100644 index 0000000..296c61e --- /dev/null +++ b/ipk-source/luci-app-argon-config/root/usr/lib/lua/luci/view/argon-config/other_dvalue.htm @@ -0,0 +1,8 @@ +<%+cbi/valueheader%> + +<% + local val = self:cfgvalue(section) or self.default or "" + write(pcdata(val)) +%> + +<%+cbi/valuefooter%> diff --git a/ipk-source/luci-app-argon-config/root/usr/lib/lua/luci/view/argon-config/other_upload.htm b/ipk-source/luci-app-argon-config/root/usr/lib/lua/luci/view/argon-config/other_upload.htm new file mode 100644 index 0000000..63a9b4f --- /dev/null +++ b/ipk-source/luci-app-argon-config/root/usr/lib/lua/luci/view/argon-config/other_upload.htm @@ -0,0 +1,5 @@ +<%+cbi/valueheader%> + + + +<%+cbi/valuefooter%> diff --git a/ipk-source/luci-app-argon-config/root/usr/share/rpcd/acl.d/luci-app-argon-config.json b/ipk-source/luci-app-argon-config/root/usr/share/rpcd/acl.d/luci-app-argon-config.json new file mode 100644 index 0000000..f0a3137 --- /dev/null +++ b/ipk-source/luci-app-argon-config/root/usr/share/rpcd/acl.d/luci-app-argon-config.json @@ -0,0 +1,11 @@ +{ + "luci-app-argon-config": { + "description": "Grant UCI access for luci-app-argon-config", + "read": { + "uci": [ "argon" ] + }, + "write": { + "uci": [ "argon" ] + } + } +} diff --git a/ipk-source/luci-lua-runtime_aarch64_cortex-a53/CONTROL/control b/ipk-source/luci-lua-runtime_aarch64_cortex-a53/CONTROL/control new file mode 100644 index 0000000..04e40ab --- /dev/null +++ b/ipk-source/luci-lua-runtime_aarch64_cortex-a53/CONTROL/control @@ -0,0 +1,13 @@ +Package: luci-lua-runtime +Version: 25.034.70690~7b0663a +Depends: libc, luci-base, lua, luci-lib-base, luci-lib-nixio, luci-lib-ip, luci-lib-jsonc, libubus-lua, liblucihttp-lua, ucode-mod-lua +Source: feeds/luci/modules/luci-lua-runtime +SourceName: luci-lua-runtime +License: Apache-2.0 +Section: luci +SourceDateEpoch: 1738611490 +URL: https://github.com/openwrt/luci +Maintainer: OpenWrt LuCI community +Architecture: aarch64_cortex-a53 +Installed-Size: 153600 +Description: LuCI Lua runtime libraries diff --git a/ipk-source/luci-lua-runtime_aarch64_cortex-a53/CONTROL/postinst b/ipk-source/luci-lua-runtime_aarch64_cortex-a53/CONTROL/postinst new file mode 100755 index 0000000..3bba77c --- /dev/null +++ b/ipk-source/luci-lua-runtime_aarch64_cortex-a53/CONTROL/postinst @@ -0,0 +1,5 @@ +#!/bin/sh +[ "${IPKG_NO_SCRIPT}" = "1" ] && exit 0 +[ -s ${IPKG_INSTROOT}/lib/functions.sh ] || exit 0 +. ${IPKG_INSTROOT}/lib/functions.sh +default_postinst $0 $@ diff --git a/ipk-source/luci-lua-runtime_aarch64_cortex-a53/CONTROL/postinst-pkg b/ipk-source/luci-lua-runtime_aarch64_cortex-a53/CONTROL/postinst-pkg new file mode 100755 index 0000000..2e52d45 --- /dev/null +++ b/ipk-source/luci-lua-runtime_aarch64_cortex-a53/CONTROL/postinst-pkg @@ -0,0 +1,5 @@ +[ -n "${IPKG_INSTROOT}" ] || { rm -f /tmp/luci-indexcache.* + rm -rf /tmp/luci-modulecache/ + killall -HUP rpcd 2>/dev/null + exit 0 +} diff --git a/ipk-source/luci-lua-runtime_aarch64_cortex-a53/CONTROL/prerm b/ipk-source/luci-lua-runtime_aarch64_cortex-a53/CONTROL/prerm new file mode 100755 index 0000000..12d06ec --- /dev/null +++ b/ipk-source/luci-lua-runtime_aarch64_cortex-a53/CONTROL/prerm @@ -0,0 +1,4 @@ +#!/bin/sh +[ -s ${IPKG_INSTROOT}/lib/functions.sh ] || exit 0 +. ${IPKG_INSTROOT}/lib/functions.sh +default_prerm $0 $@ diff --git a/ipk-source/luci-lua-runtime_aarch64_cortex-a53/build-ipk b/ipk-source/luci-lua-runtime_aarch64_cortex-a53/build-ipk new file mode 100755 index 0000000..eb83cf6 --- /dev/null +++ b/ipk-source/luci-lua-runtime_aarch64_cortex-a53/build-ipk @@ -0,0 +1,74 @@ +#!/bin/sh + +# Script for building OpenWRT .ipk packages using tar by iamromulan +# Works with SDXPPINN OpenWRT - iamromulan +# This script accepts an optional path to the directory containing the `CONTROL` and `root` directories. +# Usage: ./build-ipk.sh [path] +# If no path is provided, the script will look in the current directory for `CONTROL` and `root` directories. +# This will spit out an ipk in the current directory + +# Check if the script is run as root. If not, rerun with sudo. +if [ "$(id -u)" -ne 0 ]; then + echo "Script is not running as root. Re-executing with sudo..." + exec sudo "$0" "$@" +fi + +# Set the default build path to the current directory +build_path="." + +# Check if a path is provided as the first argument +if [ "$1" ]; then + build_path="$1" +fi + +# Check if the required directories are present in the specified path +if [ ! -d "${build_path}/CONTROL" ] || [ ! -d "${build_path}/root" ]; then + echo "Error: CONTROL and root directories must be present in the specified path (${build_path})." + exit 1 +fi + +# Extract values from the CONTROL/control file in the specified path +pkgname=$(grep -i '^Package:' "${build_path}/CONTROL/control" | awk '{print $2}') +version=$(grep -i '^Version:' "${build_path}/CONTROL/control" | awk '{print $2}') +architecture=$(grep -i '^Architecture:' "${build_path}/CONTROL/control" | awk '{print $2}') + +# Check if values are extracted correctly +if [ -z "$pkgname" ] || [ -z "$version" ] || [ -z "$architecture" ]; then + echo "Error: Failed to extract Package, Version, or Architecture from ${build_path}/CONTROL/control." + exit 1 +fi + +# Set the final IPK name based on the extracted values +ipkname="${pkgname}_${version}_${architecture}.ipk" + +# Ensure all CONTROL scripts are executable +echo "Setting permissions for CONTROL scripts..." +chmod +x "${build_path}/CONTROL"/* + +# Set ownership for CONTROL and root files +echo "Setting ownership for all package files..." +chown -R root:root "${build_path}/CONTROL"/* +chown -R root:root "${build_path}/root"/* + +# Create control.tar.gz from the CONTROL directory +echo "Creating control.tar.gz..." +tar -czvf control.tar.gz -C "${build_path}/CONTROL" . + +# Create data.tar.gz from the root directory +echo "Creating data.tar.gz..." +tar -czvf data.tar.gz -C "${build_path}/root" . + +# Create debian-binary file (must contain exactly "2.0" without a newline) +echo -n "2.0" > debian-binary +chown -R root:root debian-binary + +# Combine the components into the final .ipk file using tar +echo "Packaging ${ipkname}..." +tar -czvf "$ipkname" debian-binary control.tar.gz data.tar.gz + +# Clean up intermediate files +echo "Cleaning up temporary files..." +rm -f control.tar.gz data.tar.gz debian-binary + +echo "IPK package ${ipkname} created successfully using tar." + diff --git a/ipk-source/luci-lua-runtime_aarch64_cortex-a53/root/usr/lib/lua/luci/cacheloader.lua b/ipk-source/luci-lua-runtime_aarch64_cortex-a53/root/usr/lib/lua/luci/cacheloader.lua new file mode 100644 index 0000000..7ef971d --- /dev/null +++ b/ipk-source/luci-lua-runtime_aarch64_cortex-a53/root/usr/lib/lua/luci/cacheloader.lua @@ -0,0 +1,12 @@ +-- Copyright 2008 Steven Barth +-- Copyright 2008 Jo-Philipp Wich +-- Licensed to the public under the Apache License 2.0. + +local config = require "luci.config" +local ccache = require "luci.ccache" + +module "luci.cacheloader" + +if config.ccache and config.ccache.enable == "1" then + ccache.cache_ondemand() +end diff --git a/ipk-source/luci-lua-runtime_aarch64_cortex-a53/root/usr/lib/lua/luci/ccache.lua b/ipk-source/luci-lua-runtime_aarch64_cortex-a53/root/usr/lib/lua/luci/ccache.lua new file mode 100644 index 0000000..d3be7cb --- /dev/null +++ b/ipk-source/luci-lua-runtime_aarch64_cortex-a53/root/usr/lib/lua/luci/ccache.lua @@ -0,0 +1,76 @@ +-- Copyright 2008 Steven Barth +-- Copyright 2008 Jo-Philipp Wich +-- Licensed to the public under the Apache License 2.0. + +local io = require "io" +local fs = require "nixio.fs" +local util = require "luci.util" +local nixio = require "nixio" +local debug = require "debug" +local string = require "string" +local package = require "package" + +local type, loadfile = type, loadfile + + +module "luci.ccache" + +function cache_ondemand(...) + if debug.getinfo(1, 'S').source ~= "=?" then + cache_enable(...) + end +end + +function cache_enable(cachepath, mode) + cachepath = cachepath or "/tmp/luci-modulecache" + mode = mode or "r--r--r--" + + local loader = package.loaders[2] + local uid = nixio.getuid() + + if not fs.stat(cachepath) then + fs.mkdir(cachepath) + end + + local function _encode_filename(name) + local encoded = "" + for i=1, #name do + encoded = encoded .. ("%2X" % string.byte(name, i)) + end + return encoded + end + + local function _load_sane(file) + local stat = fs.stat(file) + if stat and stat.uid == uid and stat.modestr == mode then + return loadfile(file) + end + end + + local function _write_sane(file, func) + if nixio.getuid() == uid then + local fp = io.open(file, "w") + if fp then + fp:write(util.get_bytecode(func)) + fp:close() + fs.chmod(file, mode) + end + end + end + + package.loaders[2] = function(mod) + local encoded = cachepath .. "/" .. _encode_filename(mod) + local modcons = _load_sane(encoded) + + if modcons then + return modcons + end + + -- No cachefile + modcons = loader(mod) + if type(modcons) == "function" then + _write_sane(encoded, modcons) + end + return modcons + end +end diff --git a/ipk-source/luci-lua-runtime_aarch64_cortex-a53/root/usr/lib/lua/luci/config.lua b/ipk-source/luci-lua-runtime_aarch64_cortex-a53/root/usr/lib/lua/luci/config.lua new file mode 100644 index 0000000..d01153f --- /dev/null +++ b/ipk-source/luci-lua-runtime_aarch64_cortex-a53/root/usr/lib/lua/luci/config.lua @@ -0,0 +1,18 @@ +-- Copyright 2008 Steven Barth +-- Licensed to the public under the Apache License 2.0. + +local util = require "luci.util" +module("luci.config", + function(m) + if pcall(require, "luci.model.uci") then + local config = util.threadlocal() + setmetatable(m, { + __index = function(tbl, key) + if not config[key] then + config[key] = luci.model.uci.cursor():get_all("luci", key) + end + return config[key] + end + }) + end + end) diff --git a/ipk-source/luci-lua-runtime_aarch64_cortex-a53/root/usr/lib/lua/luci/dispatcher.lua b/ipk-source/luci-lua-runtime_aarch64_cortex-a53/root/usr/lib/lua/luci/dispatcher.lua new file mode 100644 index 0000000..bbe7600 --- /dev/null +++ b/ipk-source/luci-lua-runtime_aarch64_cortex-a53/root/usr/lib/lua/luci/dispatcher.lua @@ -0,0 +1,484 @@ +-- Copyright 2008 Steven Barth +-- Copyright 2008-2015 Jo-Philipp Wich +-- Licensed to the public under the Apache License 2.0. + +module("luci.dispatcher", package.seeall) + +local http = _G.L.http + +context = setmetatable({}, { + __index = function(t, k) + if k == "request" or k == "requestpath" then + return _G.L.ctx.request_path + elseif k == "requestargs" then + return _G.L.ctx.request_args + else + return _G.L.ctx[k] + end + end +}) + +uci = require "luci.model.uci" +uci:set_session_id(_G.L.ctx.authsession) + +i18n = require "luci.i18n" +i18n.setlanguage(_G.L.dispatcher.lang) + +build_url = _G.L.dispatcher.build_url +menu_json = _G.L.dispatcher.menu_json +error404 = _G.L.dispatcher.error404 +error500 = _G.L.dispatcher.error500 + +function is_authenticated(auth) + local session = _G.L.dispatcher.is_authenticated(auth) + if session then + return session.sid, session.data, session.acls + end +end + +function assign(path, clone, title, order) + local obj = node(unpack(path)) + + obj.title = title + obj.order = order + + setmetatable(obj, {__index = node(unpack(clone))}) + + return obj +end + +function entry(path, target, title, order) + local c = node(unpack(path)) + + c.title = title + c.order = order + c.action = target + + return c +end + +-- enabling the node. +function get(...) + return node(...) +end + +function node(...) + local p = table.concat({ ... }, "/") + + if not __entries[p] then + __entries[p] = {} + end + + return __entries[p] +end + +function lookup(...) + local i, path = nil, {} + for i = 1, select('#', ...) do + local name, arg = nil, tostring(select(i, ...)) + for name in arg:gmatch("[^/]+") do + path[#path+1] = name + end + end + + local node = menu_json() + for i = 1, #path do + node = node.children[path[i]] + + if not node then + return nil + elseif node.leaf then + break + end + end + + return node, build_url(unpack(path)) +end + + +function process_lua_controller(path) + local base = "/usr/lib/lua/luci/controller/" + local modname = "luci.controller." .. path:sub(#base+1, #path-4):gsub("/", ".") + local mod = require(modname) + assert(mod ~= true, + "Invalid controller file found\n" .. + "The file '" .. path .. "' contains an invalid module line.\n" .. + "Please verify whether the module name is set to '" .. modname .. + "' - It must correspond to the file path!") + + local idx = mod.index + if type(idx) ~= "function" then + return nil + end + + local entries = {} + + __entries = entries + __controller = modname + + setfenv(idx, setmetatable({}, { __index = luci.dispatcher }))() + + __entries = nil + __controller = nil + + -- fixup gathered node specs + for path, entry in pairs(entries) do + if entry.leaf then + entry.wildcard = true + end + + if type(entry.file_depends) == "table" then + for _, v in ipairs(entry.file_depends) do + entry.depends = entry.depends or {} + entry.depends.fs = entry.depends.fs or {} + + local ft = fs.stat(v, "type") + if ft == "dir" then + entry.depends.fs[v] = "directory" + elseif v:match("/s?bin/") then + entry.depends.fs[v] = "executable" + else + entry.depends.fs[v] = "file" + end + end + end + + if type(entry.uci_depends) == "table" then + for k, v in pairs(entry.uci_depends) do + entry.depends = entry.depends or {} + entry.depends.uci = entry.depends.uci or {} + entry.depends.uci[k] = v + end + end + + if type(entry.acl_depends) == "table" then + for _, acl in ipairs(entry.acl_depends) do + entry.depends = entry.depends or {} + entry.depends.acl = entry.depends.acl or {} + entry.depends.acl[#entry.depends.acl + 1] = acl + end + end + + if (entry.sysauth_authenticator ~= nil) or + (entry.sysauth ~= nil and entry.sysauth ~= false) + then + if entry.sysauth_authenticator == "htmlauth" then + entry.auth = { + login = true, + methods = { "cookie:sysauth_https", "cookie:sysauth_http" } + } + elseif path == "rpc" and modname == "luci.controller.rpc" then + entry.auth = { + login = false, + methods = { "query:auth", "cookie:sysauth_https", "cookie:sysauth_http", "cookie:sysauth" } + } + elseif modname == "luci.controller.admin.uci" then + entry.auth = { + login = false, + methods = { "param:sid" } + } + end + elseif entry.sysauth == false then + entry.auth = {} + end + + if entry.action == nil and type(entry.target) == "table" then + entry.action = entry.target + entry.target = nil + end + + entry.leaf = nil + + entry.file_depends = nil + entry.uci_depends = nil + entry.acl_depends = nil + + entry.sysauth = nil + entry.sysauth_authenticator = nil + end + + return entries +end + +function invoke_cbi_action(model, config, ...) + local cbi = require "luci.cbi" + local tpl = require "luci.template" + local util = require "luci.util" + + if not config then + config = {} + end + + local maps = cbi.load(model, ...) + + local state = nil + + local function has_uci_access(config, level) + local rv = util.ubus("session", "access", { + ubus_rpc_session = context.authsession, + scope = "uci", object = config, + ["function"] = level + }) + + return (type(rv) == "table" and rv.access == true) or false + end + + local i, res + for i, res in ipairs(maps) do + if util.instanceof(res, cbi.SimpleForm) then + io.stderr:write("Model %s returns SimpleForm but is dispatched via cbi(),\n" + % model) + + io.stderr:write("please change %s to use the form() action instead.\n" + % table.concat(context.request, "/")) + end + + res.flow = config + local cstate = res:parse() + if cstate and (not state or cstate < state) then + state = cstate + end + end + + local function _resolve_path(path) + return type(path) == "table" and build_url(unpack(path)) or path + end + + if config.on_valid_to and state and state > 0 and state < 2 then + http:redirect(_resolve_path(config.on_valid_to)) + return + end + + if config.on_changed_to and state and state > 1 then + http:redirect(_resolve_path(config.on_changed_to)) + return + end + + if config.on_success_to and state and state > 0 then + http:redirect(_resolve_path(config.on_success_to)) + return + end + + if config.state_handler then + if not config.state_handler(state, maps) then + return + end + end + + http:header("X-CBI-State", state or 0) + + if not config.noheader then + _G.L.include("cbi/header", {state = state}) + end + + local redirect + local messages + local applymap = false + local pageaction = true + local parsechain = { } + local writable = false + + for i, res in ipairs(maps) do + if res.apply_needed and res.parsechain then + local c + for _, c in ipairs(res.parsechain) do + parsechain[#parsechain+1] = c + end + applymap = true + end + + if res.redirect then + redirect = redirect or res.redirect + end + + if res.pageaction == false then + pageaction = false + end + + if res.message then + messages = messages or { } + messages[#messages+1] = res.message + end + end + + for i, res in ipairs(maps) do + local is_readable_map = has_uci_access(res.config, "read") + local is_writable_map = has_uci_access(res.config, "write") + + writable = writable or is_writable_map + + res:render({ + firstmap = (i == 1), + redirect = redirect, + messages = messages, + pageaction = pageaction, + parsechain = parsechain, + readable = is_readable_map, + writable = is_writable_map + }) + end + + if not config.nofooter then + _G.L.include("cbi/footer", { + flow = config, + pageaction = pageaction, + redirect = redirect, + state = state, + autoapply = config.autoapply, + trigger_apply = applymap, + writable = writable + }) + end +end + +function invoke_form_action(model, ...) + local cbi = require "luci.cbi" + local tpl = require "luci.template" + + local maps = luci.cbi.load(model, ...) + local state = nil + + local i, res + for i, res in ipairs(maps) do + local cstate = res:parse() + if cstate and (not state or cstate < state) then + state = cstate + end + end + + http:header("X-CBI-State", state or 0) + _G.L.include("header") + for i, res in ipairs(maps) do + res:render() + end + _G.L.include("footer") +end + +function render_lua_template(path) + local tpl = require "luci.template" + + tpl.render(path, getfenv(1)) +end + +function test_post_security() + if http:getenv("REQUEST_METHOD") ~= "POST" then + http:status(405, "Method Not Allowed") + http:header("Allow", "POST") + return false + end + + if http:formvalue("token") ~= context.authtoken then + http:status(403, "Forbidden") + _G.L.include("csrftoken") + return false + end + + return true +end + + +function call(name, ...) + return { + ["type"] = "call", + ["module"] = __controller, + ["function"] = name, + ["parameters"] = select('#', ...) > 0 and {...} or nil + } +end + +function post_on(params, name, ...) + return { + ["type"] = "call", + ["module"] = __controller, + ["function"] = name, + ["parameters"] = select('#', ...) > 0 and {...} or nil, + ["post"] = params + } +end + +function post(...) + return post_on(true, ...) +end + +function view(name) + return { + ["type"] = "view", + ["path"] = name + } +end + +function template(name) + return { + ["type"] = "template", + ["path"] = name + } +end + +function cbi(model, config) + return { + ["type"] = "call", + ["module"] = "luci.dispatcher", + ["function"] = "invoke_cbi_action", + ["parameters"] = { model, config or {} }, + ["post"] = { + ["cbi.submit"] = true + } + } +end + +function form(model) + return { + ["type"] = "call", + ["module"] = "luci.dispatcher", + ["function"] = "invoke_form_action", + ["parameters"] = { model }, + ["post"] = { + ["cbi.submit"] = true + } + } +end + +function firstchild() + return { + ["type"] = "firstchild" + } +end + +function firstnode() + return { + ["type"] = "firstchild", + ["recurse"] = true + } +end + +function arcombine(trg1, trg2) + return { + ["type"] = "arcombine", + ["targets"] = { trg1, trg2 } --, + --env = getfenv(), + } +end + +function alias(...) + return { + ["type"] = "alias", + ["path"] = table.concat({ ... }, "/") + } +end + +function rewrite(n, ...) + return { + ["type"] = "rewrite", + ["path"] = table.concat({ ... }, "/"), + ["remove"] = n + } +end + + +translate = i18n.translate + +-- This function does not actually translate the given argument but +-- is used by build/i18n-scan.pl to find translatable entries. +function _(text) + return text +end diff --git a/ipk-source/luci-lua-runtime_aarch64_cortex-a53/root/usr/lib/lua/luci/i18n.lua b/ipk-source/luci-lua-runtime_aarch64_cortex-a53/root/usr/lib/lua/luci/i18n.lua new file mode 100644 index 0000000..323912b --- /dev/null +++ b/ipk-source/luci-lua-runtime_aarch64_cortex-a53/root/usr/lib/lua/luci/i18n.lua @@ -0,0 +1,55 @@ +-- Copyright 2008 Steven Barth +-- Licensed to the public under the Apache License 2.0. + +local tparser = require "luci.template.parser" +local util = require "luci.util" +local tostring = tostring + +module "luci.i18n" + +i18ndir = util.libpath() .. "/i18n/" +context = util.threadlocal() +default = "en" + + +function setlanguage(lang) + local code, subcode = lang:match("^([A-Za-z][A-Za-z])[%-_]([A-Za-z][A-Za-z])$") + if not (code and subcode) then + subcode = lang:match("^([A-Za-z][A-Za-z])$") + if not subcode then + return nil + end + end + + context.parent = code and code:lower() + context.lang = context.parent and context.parent.."-"..subcode:lower() or subcode:lower() + + if tparser.load_catalog(context.lang, i18ndir) and + tparser.change_catalog(context.lang) + then + return context.lang + + elseif context.parent then + if tparser.load_catalog(context.parent, i18ndir) and + tparser.change_catalog(context.parent) + then + return context.parent + end + end + + return nil +end + +function translate(key) + return tparser.translate(key) or key +end + +function translatef(key, ...) + return tostring(translate(key)):format(...) +end + +function dump() + local rv = {} + tparser.get_translations(function(k, v) rv[k] = v end) + return rv +end diff --git a/ipk-source/luci-lua-runtime_aarch64_cortex-a53/root/usr/lib/lua/luci/model/uci.lua b/ipk-source/luci-lua-runtime_aarch64_cortex-a53/root/usr/lib/lua/luci/model/uci.lua new file mode 100644 index 0000000..816f6f2 --- /dev/null +++ b/ipk-source/luci-lua-runtime_aarch64_cortex-a53/root/usr/lib/lua/luci/model/uci.lua @@ -0,0 +1,508 @@ +-- Copyright 2008 Steven Barth +-- Licensed to the public under the Apache License 2.0. + +local os = require "os" +local util = require "luci.util" +local table = require "table" + + +local setmetatable, rawget, rawset = setmetatable, rawget, rawset +local require, getmetatable, assert = require, getmetatable, assert +local error, pairs, ipairs, select = error, pairs, ipairs, select +local type, tostring, tonumber, unpack = type, tostring, tonumber, unpack + +-- The typical workflow for UCI is: Get a cursor instance from the +-- cursor factory, modify data (via Cursor.add, Cursor.delete, etc.), +-- save the changes to the staging area via Cursor.save and finally +-- Cursor.commit the data to the actual config files. +-- LuCI then needs to Cursor.apply the changes so daemons etc. are +-- reloaded. +module "luci.model.uci" + +local ERRSTR = { + "Invalid command", + "Invalid argument", + "Method not found", + "Entry not found", + "No data", + "Permission denied", + "Timeout", + "Not supported", + "Unknown error", + "Connection failed" +} + +local session_id = nil + +local function call(cmd, args) + if type(args) == "table" and session_id then + args.ubus_rpc_session = session_id + end + return util.ubus("uci", cmd, args) +end + + +function cursor() + return _M +end + +function cursor_state() + return _M +end + +function substate(self) + return self +end + + +function get_confdir(self) + return "/etc/config" +end + +function get_savedir(self) + return "/tmp/.uci" +end + +function get_session_id(self) + return session_id +end + +function set_confdir(self, directory) + return false +end + +function set_savedir(self, directory) + return false +end + +function set_session_id(self, id) + session_id = id + return true +end + + +function load(self, config) + return true +end + +function save(self, config) + return true +end + +function unload(self, config) + return true +end + + +function changes(self, config) + local rv, err = call("changes", { config = config }) + + if type(rv) == "table" and type(rv.changes) == "table" then + return rv.changes + elseif err then + return nil, ERRSTR[err] + else + return { } + end +end + + +function revert(self, config) + local _, err = call("revert", { config = config }) + return (err == nil), ERRSTR[err] +end + +function commit(self, config) + local _, err = call("commit", { config = config }) + return (err == nil), ERRSTR[err] +end + +function apply(self, rollback) + local _, err + + if rollback then + local sys = require "luci.sys" + local conf = require "luci.config" + local timeout = tonumber(conf and conf.apply and conf.apply.rollback or 90) or 0 + + _, err = call("apply", { + timeout = (timeout > 90) and timeout or 90, + rollback = true + }) + + if not err then + local now = os.time() + local token = sys.uniqueid(16) + + util.ubus("session", "set", { + ubus_rpc_session = "00000000000000000000000000000000", + values = { + rollback = { + token = token, + session = session_id, + timeout = now + timeout + } + } + }) + + return token + end + else + _, err = call("changes", {}) + + if not err then + if type(_) == "table" and type(_.changes) == "table" then + local k, v + for k, v in pairs(_.changes) do + _, err = call("commit", { config = k }) + if err then + break + end + end + end + end + + if not err then + _, err = call("apply", { rollback = false }) + end + end + + return (err == nil), ERRSTR[err] +end + +function confirm(self, token) + local is_pending, time_remaining, rollback_sid, rollback_token = self:rollback_pending() + + if is_pending then + if token ~= rollback_token then + return false, "Permission denied" + end + + local _, err = util.ubus("uci", "confirm", { + ubus_rpc_session = rollback_sid + }) + + if not err then + util.ubus("session", "set", { + ubus_rpc_session = "00000000000000000000000000000000", + values = { rollback = {} } + }) + end + + return (err == nil), ERRSTR[err] + end + + return false, "No data" +end + +function rollback(self) + local is_pending, time_remaining, rollback_sid = self:rollback_pending() + + if is_pending then + local _, err = util.ubus("uci", "rollback", { + ubus_rpc_session = rollback_sid + }) + + if not err then + util.ubus("session", "set", { + ubus_rpc_session = "00000000000000000000000000000000", + values = { rollback = {} } + }) + end + + return (err == nil), ERRSTR[err] + end + + return false, "No data" +end + +function rollback_pending(self) + local rv, err = util.ubus("session", "get", { + ubus_rpc_session = "00000000000000000000000000000000", + keys = { "rollback" } + }) + + local now = os.time() + + if type(rv) == "table" and + type(rv.values) == "table" and + type(rv.values.rollback) == "table" and + type(rv.values.rollback.token) == "string" and + type(rv.values.rollback.session) == "string" and + type(rv.values.rollback.timeout) == "number" and + rv.values.rollback.timeout > now + then + return true, + rv.values.rollback.timeout - now, + rv.values.rollback.session, + rv.values.rollback.token + end + + return false, ERRSTR[err] +end + + +function foreach(self, config, stype, callback) + if type(callback) == "function" then + local rv, err = call("get", { + config = config, + type = stype + }) + + if type(rv) == "table" and type(rv.values) == "table" then + local sections = { } + local res = false + local index = 1 + + local _, section + for _, section in pairs(rv.values) do + section[".index"] = section[".index"] or index + sections[index] = section + index = index + 1 + end + + table.sort(sections, function(a, b) + return a[".index"] < b[".index"] + end) + + for _, section in ipairs(sections) do + local continue = callback(section) + res = true + if continue == false then + break + end + end + return res + else + return false, ERRSTR[err] or "No data" + end + else + return false, "Invalid argument" + end +end + +local function _get(self, operation, config, section, option) + if section == nil then + return nil + elseif type(option) == "string" and option:byte(1) ~= 46 then + local rv, err = call(operation, { + config = config, + section = section, + option = option + }) + + if type(rv) == "table" then + return rv.value or nil + elseif err then + return false, ERRSTR[err] + else + return nil + end + elseif option == nil then + local values = self:get_all(config, section) + if values then + return values[".type"], values[".name"] + else + return nil + end + else + return false, "Invalid argument" + end +end + +function get(self, ...) + return _get(self, "get", ...) +end + +function get_state(self, ...) + return _get(self, "state", ...) +end + +function get_all(self, config, section) + local rv, err = call("get", { + config = config, + section = section + }) + + if type(rv) == "table" and type(rv.values) == "table" then + return rv.values + elseif err then + return false, ERRSTR[err] + else + return nil + end +end + +function get_bool(self, ...) + local val = self:get(...) + return (val == "1" or val == "true" or val == "yes" or val == "on") +end + +function get_first(self, config, stype, option, default) + local rv = default + + self:foreach(config, stype, function(s) + local val = not option and s[".name"] or s[option] + + if type(default) == "number" then + val = tonumber(val) + elseif type(default) == "boolean" then + val = (val == "1" or val == "true" or + val == "yes" or val == "on") + end + + if val ~= nil then + rv = val + return false + end + end) + + return rv +end + +function get_list(self, config, section, option) + if config and section and option then + local val = self:get(config, section, option) + return (type(val) == "table" and val or { val }) + end + return { } +end + + +function section(self, config, stype, name, values) + local rv, err = call("add", { + config = config, + type = stype, + name = name, + values = values + }) + + if type(rv) == "table" then + return rv.section + elseif err then + return false, ERRSTR[err] + else + return nil + end +end + + +function add(self, config, stype) + return self:section(config, stype) +end + +function set(self, config, section, option, ...) + if select('#', ...) == 0 then + local sname, err = self:section(config, option, section) + return (not not sname), err + else + local _, err = call("set", { + config = config, + section = section, + values = { [option] = select(1, ...) } + }) + return (err == nil), ERRSTR[err] + end +end + +function set_list(self, config, section, option, value) + if section == nil or option == nil then + return false + elseif value == nil or (type(value) == "table" and #value == 0) then + return self:delete(config, section, option) + elseif type(value) == "table" then + return self:set(config, section, option, value) + else + return self:set(config, section, option, { value }) + end +end + +function tset(self, config, section, values) + local _, err = call("set", { + config = config, + section = section, + values = values + }) + return (err == nil), ERRSTR[err] +end + +function reorder(self, config, section, index) + local sections + + if type(section) == "string" and type(index) == "number" then + local pos = 0 + + sections = { } + + self:foreach(config, nil, function(s) + if pos == index then + pos = pos + 1 + end + + if s[".name"] ~= section then + pos = pos + 1 + sections[pos] = s[".name"] + else + sections[index + 1] = section + end + end) + elseif type(section) == "table" then + sections = section + else + return false, "Invalid argument" + end + + local _, err = call("order", { + config = config, + sections = sections + }) + + return (err == nil), ERRSTR[err] +end + + +function delete(self, config, section, option) + local _, err = call("delete", { + config = config, + section = section, + option = option + }) + return (err == nil), ERRSTR[err] +end + +function delete_all(self, config, stype, comparator) + local _, err + if type(comparator) == "table" then + _, err = call("delete", { + config = config, + type = stype, + match = comparator + }) + elseif type(comparator) == "function" then + local rv = call("get", { + config = config, + type = stype + }) + + if type(rv) == "table" and type(rv.values) == "table" then + local sname, section + for sname, section in pairs(rv.values) do + if comparator(section) then + _, err = call("delete", { + config = config, + section = sname + }) + end + end + end + elseif comparator == nil then + _, err = call("delete", { + config = config, + type = stype + }) + else + return false, "Invalid argument" + end + + return (err == nil), ERRSTR[err] +end diff --git a/ipk-source/luci-lua-runtime_aarch64_cortex-a53/root/usr/lib/lua/luci/store.lua b/ipk-source/luci-lua-runtime_aarch64_cortex-a53/root/usr/lib/lua/luci/store.lua new file mode 100644 index 0000000..a735981 --- /dev/null +++ b/ipk-source/luci-lua-runtime_aarch64_cortex-a53/root/usr/lib/lua/luci/store.lua @@ -0,0 +1,6 @@ +-- Copyright 2009 Steven Barth +-- Copyright 2009 Jo-Philipp Wich +-- Licensed to the public under the Apache License 2.0. + +local util = require "luci.util" +module("luci.store", util.threadlocal) diff --git a/ipk-source/luci-lua-runtime_aarch64_cortex-a53/root/usr/lib/lua/luci/sys.lua b/ipk-source/luci-lua-runtime_aarch64_cortex-a53/root/usr/lib/lua/luci/sys.lua new file mode 100644 index 0000000..e6eb762 --- /dev/null +++ b/ipk-source/luci-lua-runtime_aarch64_cortex-a53/root/usr/lib/lua/luci/sys.lua @@ -0,0 +1,615 @@ +-- Copyright 2008 Steven Barth +-- Licensed to the public under the Apache License 2.0. + +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, unpack = + tonumber, ipairs, pairs, pcall, type, next, setmetatable, require, select, unpack + + +module "luci.sys" + +function call(...) + return os.execute(...) / 256 +end + +exec = luci.util.exec + +-- 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. +getenv = nixio.getenv + +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 + +function httpget(url, stream, target) + if not target then + local source = stream and io.popen or luci.util.exec + return source("wget -qO- %s" % luci.util.shellquote(url)) + else + return os.execute("wget -qO %s %s" % + {luci.util.shellquote(target), luci.util.shellquote(url)}) + end +end + +function reboot() + return os.execute("reboot >/dev/null 2>&1") +end + +function syslog() + return luci.util.exec("logread") +end + +function dmesg() + return luci.util.exec("dmesg") +end + +function uniqueid(bytes) + local rand = fs.readfile("/dev/urandom", bytes) + return rand and nixio.bin.hexlify(rand) +end + +function uptime() + return nixio.sysinfo().uptime +end + + +net = {} + +local function _nethints(what, callback) + local _, k, e, mac, ip, name, duid, iaid + local cur = uci.cursor() + local ifn = { } + local hosts = { } + local lookup = { } + + 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 + + luci.ip.neighbors(nil, function(neigh) + if neigh.mac and neigh.family == 4 then + _add(what, neigh.mac:string(), neigh.dest:string(), nil, nil) + elseif neigh.mac and neigh.family == 6 then + _add(what, neigh.mac:string(), nil, neigh.dest:string(), nil) + end + end) + + if fs.access("/etc/ethers") then + for e in io.lines("/etc/ethers") do + mac, name = e:match("^([a-fA-F0-9:-]+)%s+(%S+)") + mac = luci.ip.checkmac(mac) + if mac and name then + if luci.ip.checkip4(name) then + _add(what, mac, name, nil, nil) + else + _add(what, mac, nil, nil, name) + end + end + end + end + + cur:foreach("dhcp", "dnsmasq", + function(s) + if s.leasefile and fs.access(s.leasefile) then + for e in io.lines(s.leasefile) do + mac, ip, name = e:match("^%d+ (%S+) (%S+) (%S+)") + mac = luci.ip.checkmac(mac) + if mac and ip then + _add(what, mac, ip, nil, name ~= "*" and name) + end + end + end + end + ) + + cur:foreach("dhcp", "odhcpd", + function(s) + if type(s.leasefile) == "string" and fs.access(s.leasefile) then + for e in io.lines(s.leasefile) do + duid, iaid, name, _, ip = e:match("^# %S+ (%S+) (%S+) (%S+) (-?%d+) %S+ %S+ ([0-9a-f:.]+)/[0-9]+") + mac = net.duid_to_mac(duid) + if mac then + if ip and iaid == "ipv4" then + _add(what, mac, ip, nil, name ~= "*" and name) + elseif ip then + _add(what, mac, nil, ip, name ~= "*" and name) + end + end + end + end + end + ) + + cur:foreach("dhcp", "host", + function(s) + for mac in luci.util.imatch(s.mac) do + mac = luci.ip.checkmac(mac) + if mac then + _add(what, mac, s.ip, nil, s.name) + end + 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 pairs(hosts) do + lookup[#lookup+1] = (what > 1) and e[what] or (e[2] or e[3]) + end + + if #lookup > 0 then + lookup = luci.util.ubus("network.rrdns", "lookup", { + addrs = lookup, + timeout = 250, + limit = 1000 + }) or { } + end + + for _, e in luci.util.kspairs(hosts) do + callback(e[1], e[2], e[3], lookup[e[2]] or lookup[e[3]] or e[4]) + end +end + +-- 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 v4 + if name and name ~= mac then + callback(mac, name or v4) + end + end) + else + local rv = { } + _nethints(1, function(mac, v4, v6, name) + name = name or v4 + if name and name ~= mac then + rv[#rv+1] = { mac, name or v4 } + end + end) + return rv + end +end + +-- 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 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 mac + if name and name ~= v4 then + rv[#rv+1] = { v4, name } + end + end) + return rv + end +end + +-- 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 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 mac + if name and name ~= v6 then + rv[#rv+1] = { v6, name } + end + end) + return rv + end +end + +function net.host_hints(callback) + if callback then + _nethints(1, function(mac, v4, v6, name) + if mac and mac ~= "00:00:00:00:00:00" and (v4 or v6 or name) then + callback(mac, v4, v6, name) + end + end) + else + local rv = { } + _nethints(1, function(mac, v4, v6, name) + if mac and mac ~= "00:00:00:00:00:00" and (v4 or v6 or name) then + local e = { } + if v4 then e.ipv4 = v4 end + if v6 then e.ipv6 = v6 end + if name then e.name = name end + rv[mac] = e + end + end) + return rv + end +end + +function net.conntrack(callback) + local ok, nfct = pcall(io.lines, "/proc/net/nf_conntrack") + if not ok or not nfct then + return nil + end + + local line, connt = nil, (not callback) and { } + for line in nfct do + local fam, l3, l4, rest = + line:match("^(ipv[46]) +(%d+) +%S+ +(%d+) +(.+)$") + + local timeout, tuples = rest:match("^(%d+) +(.+)$") + + if not tuples then + tuples = rest + end + + if fam and l3 and l4 and not tuples:match("^TIME_WAIT ") then + l4 = nixio.getprotobynumber(l4) + + local entry = { + bytes = 0, + packets = 0, + layer3 = fam, + layer4 = l4 and l4.name or "unknown", + timeout = tonumber(timeout, 10) + } + + local key, val + for key, val in tuples:gmatch("(%w+)=(%S+)") do + if key == "bytes" or key == "packets" then + entry[key] = entry[key] + tonumber(val, 10) + elseif key == "src" or key == "dst" then + if entry[key] == nil then + entry[key] = luci.ip.new(val):string() + end + elseif key == "sport" or key == "dport" then + if entry[key] == nil then + entry[key] = val + end + elseif val then + entry[key] = val + end + end + + if callback then + callback(entry) + else + connt[#connt+1] = entry + end + end + end + + return callback and true or connt +end + +function net.devices() + local devs = {} + local seen = {} + for k, v in ipairs(nixio.getifaddrs()) do + if v.name and not seen[v.name] then + seen[v.name] = true + devs[#devs+1] = v.name + end + end + return devs +end + +function net.duid_to_mac(duid) + local b1, b2, b3, b4, b5, b6 + + if type(duid) == "string" then + -- DUID-LLT / Ethernet + if #duid == 28 then + b1, b2, b3, b4, b5, b6 = duid:match("^00010001(%x%x)(%x%x)(%x%x)(%x%x)(%x%x)(%x%x)%x%x%x%x%x%x%x%x$") + + -- DUID-LL / Ethernet + elseif #duid == 20 then + b1, b2, b3, b4, b5, b6 = duid:match("^00030001(%x%x)(%x%x)(%x%x)(%x%x)(%x%x)(%x%x)$") + + -- DUID-LL / Ethernet (Without Header) + elseif #duid == 12 then + b1, b2, b3, b4, b5, b6 = duid:match("^(%x%x)(%x%x)(%x%x)(%x%x)(%x%x)(%x%x)$") + end + end + + return b1 and luci.ip.checkmac(table.concat({ b1, b2, b3, b4, b5, b6 }, ":")) +end + +process = {} + +function process.info(key) + local s = {uid = nixio.getuid(), gid = nixio.getgid()} + return not key and s or s[key] +end + +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][ 2 then + fd:close() + end +end + +function process.exec(command, stdout, stderr, nowait) + local out_r, out_w, err_r, err_w + if stdout then out_r, out_w = nixio.pipe() end + if stderr then err_r, err_w = nixio.pipe() end + + local pid = nixio.fork() + if pid == 0 then + nixio.chdir("/") + + local null = nixio.open("/dev/null", "w+") + if null then + nixio.dup(out_w or null, nixio.stdout) + nixio.dup(err_w or null, nixio.stderr) + nixio.dup(null, nixio.stdin) + xclose(out_w) + xclose(out_r) + xclose(err_w) + xclose(err_r) + xclose(null) + end + + nixio.exec(unpack(command)) + os.exit(-1) + end + + local _, pfds, rv = nil, {}, { code = -1, pid = pid } + + xclose(out_w) + xclose(err_w) + + if out_r then + pfds[#pfds+1] = { + fd = out_r, + cb = type(stdout) == "function" and stdout, + name = "stdout", + events = nixio.poll_flags("in", "err", "hup") + } + end + + if err_r then + pfds[#pfds+1] = { + fd = err_r, + cb = type(stderr) == "function" and stderr, + name = "stderr", + events = nixio.poll_flags("in", "err", "hup") + } + end + + while #pfds > 0 do + local nfds, err = nixio.poll(pfds, -1) + if not nfds and err ~= nixio.const.EINTR then + break + end + + local i + for i = #pfds, 1, -1 do + local rfd = pfds[i] + if rfd.revents > 0 then + local chunk, err = rfd.fd:read(4096) + if chunk and #chunk > 0 then + if rfd.cb then + rfd.cb(chunk) + else + rfd.buf = rfd.buf or {} + rfd.buf[#rfd.buf + 1] = chunk + end + else + table.remove(pfds, i) + if rfd.buf then + rv[rfd.name] = table.concat(rfd.buf, "") + end + rfd.fd:close() + end + end + end + end + + if not nowait then + _, _, rv.code = nixio.waitpid(pid) + end + + return rv +end + + +user = {} + +-- { "uid", "gid", "name", "passwd", "dir", "shell", "gecos" } +user.getuser = nixio.getpw + +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 then + return nil, pwe + else + return pwh, pwe + end +end + +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 + +function user.setpasswd(username, password) + return os.execute("(echo %s; sleep 1; echo %s) | passwd %s >/dev/null 2>&1" %{ + luci.util.shellquote(password), + luci.util.shellquote(password), + luci.util.shellquote(username) + }) +end + + +wifi = {} + +function wifi.getiwinfo(ifname) + local ntm = require "luci.model.network" + + ntm.init() + + local wnet = ntm:get_wifinet(ifname) + if wnet and wnet.iwinfo then + return wnet.iwinfo + end + + local wdev = ntm:get_wifidev(ifname) + if wdev and wdev.iwinfo then + return wdev.iwinfo + end + + return { ifname = ifname } +end + + +init = {} +init.dir = "/etc/init.d/" + +function init.names() + local names = { } + for name in fs.glob(init.dir.."*") do + names[#names+1] = fs.basename(name) + end + return names +end + +function init.index(name) + name = fs.basename(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) + name = fs.basename(name) + if fs.access(init.dir..name) then + return call("env -i %s%s %s >/dev/null" %{ init.dir, name, action }) + end +end + +function init.enabled(name) + return (init_action("enabled", name) == 0) +end + +function init.enable(name) + return (init_action("enable", name) == 0) +end + +function init.disable(name) + return (init_action("disable", name) == 0) +end + +function init.start(name) + return (init_action("start", name) == 0) +end + +function init.stop(name) + return (init_action("stop", name) == 0) +end + +function init.restart(name) + return (init_action("restart", name) == 0) +end + +function init.reload(name) + return (init_action("reload", name) == 0) +end diff --git a/ipk-source/luci-lua-runtime_aarch64_cortex-a53/root/usr/lib/lua/luci/sys/zoneinfo.lua b/ipk-source/luci-lua-runtime_aarch64_cortex-a53/root/usr/lib/lua/luci/sys/zoneinfo.lua new file mode 100644 index 0000000..aa054a2 --- /dev/null +++ b/ipk-source/luci-lua-runtime_aarch64_cortex-a53/root/usr/lib/lua/luci/sys/zoneinfo.lua @@ -0,0 +1,19 @@ +-- Licensed to the public under the Apache 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/ipk-source/luci-lua-runtime_aarch64_cortex-a53/root/usr/lib/lua/luci/sys/zoneinfo/tzdata.lua b/ipk-source/luci-lua-runtime_aarch64_cortex-a53/root/usr/lib/lua/luci/sys/zoneinfo/tzdata.lua new file mode 100644 index 0000000..3ef2f4c --- /dev/null +++ b/ipk-source/luci-lua-runtime_aarch64_cortex-a53/root/usr/lib/lua/luci/sys/zoneinfo/tzdata.lua @@ -0,0 +1,455 @@ +-- Licensed to the public under the Apache 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/Cairo', 'EET-2' }, + { 'Africa/Casablanca', '<+01>-1' }, + { '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', '<+01>-1' }, + { 'Africa/Freetown', 'GMT0' }, + { 'Africa/Gaborone', 'CAT-2' }, + { 'Africa/Harare', 'CAT-2' }, + { 'Africa/Johannesburg', 'SAST-2' }, + { 'Africa/Juba', 'CAT-2' }, + { 'Africa/Kampala', 'EAT-3' }, + { 'Africa/Khartoum', 'CAT-2' }, + { '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', 'CAT-2' }, + { 'America/Adak', 'HST10HDT,M3.2.0,M11.1.0' }, + { 'America/Anchorage', 'AKST9AKDT,M3.2.0,M11.1.0' }, + { 'America/Anguilla', 'AST4' }, + { 'America/Antigua', 'AST4' }, + { 'America/Araguaina', '<-03>3' }, + { 'America/Argentina/Buenos Aires', '<-03>3' }, + { 'America/Argentina/Catamarca', '<-03>3' }, + { 'America/Argentina/Cordoba', '<-03>3' }, + { 'America/Argentina/Jujuy', '<-03>3' }, + { 'America/Argentina/La Rioja', '<-03>3' }, + { 'America/Argentina/Mendoza', '<-03>3' }, + { 'America/Argentina/Rio Gallegos', '<-03>3' }, + { 'America/Argentina/Salta', '<-03>3' }, + { 'America/Argentina/San Juan', '<-03>3' }, + { 'America/Argentina/San Luis', '<-03>3' }, + { 'America/Argentina/Tucuman', '<-03>3' }, + { 'America/Argentina/Ushuaia', '<-03>3' }, + { 'America/Aruba', 'AST4' }, + { 'America/Asuncion', '<-04>4<-03>,M10.1.0/0,M3.4.0/0' }, + { 'America/Atikokan', 'EST5' }, + { 'America/Bahia', '<-03>3' }, + { 'America/Bahia Banderas', 'CST6CDT,M4.1.0,M10.5.0' }, + { 'America/Barbados', 'AST4' }, + { 'America/Belem', '<-03>3' }, + { 'America/Belize', 'CST6' }, + { 'America/Blanc-Sablon', 'AST4' }, + { 'America/Boa Vista', '<-04>4' }, + { 'America/Bogota', '<-05>5' }, + { 'America/Boise', 'MST7MDT,M3.2.0,M11.1.0' }, + { 'America/Cambridge Bay', 'MST7MDT,M3.2.0,M11.1.0' }, + { 'America/Campo Grande', '<-04>4' }, + { 'America/Cancun', 'EST5' }, + { 'America/Caracas', '<-04>4' }, + { 'America/Cayenne', '<-03>3' }, + { '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/Creston', 'MST7' }, + { 'America/Cuiaba', '<-04>4' }, + { 'America/Curacao', 'AST4' }, + { 'America/Danmarkshavn', 'GMT0' }, + { 'America/Dawson', 'MST7' }, + { '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', '<-05>5' }, + { 'America/El Salvador', 'CST6' }, + { 'America/Fort Nelson', 'MST7' }, + { 'America/Fortaleza', '<-03>3' }, + { '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', '<-05>5' }, + { 'America/Guyana', '<-04>4' }, + { 'America/Halifax', 'AST4ADT,M3.2.0,M11.1.0' }, + { 'America/Havana', 'CST5CDT,M3.2.0/0,M11.1.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', '<-04>4' }, + { 'America/Lima', '<-05>5' }, + { 'America/Los Angeles', 'PST8PDT,M3.2.0,M11.1.0' }, + { 'America/Lower Princes', 'AST4' }, + { 'America/Maceio', '<-03>3' }, + { 'America/Managua', 'CST6' }, + { 'America/Manaus', '<-04>4' }, + { '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', 'AKST9AKDT,M3.2.0,M11.1.0' }, + { 'America/Mexico City', 'CST6CDT,M4.1.0,M10.5.0' }, + { 'America/Miquelon', '<-03>3<-02>,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', '<-03>3' }, + { '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', '<-02>2' }, + { '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/Nuuk', '<-03>3<-02>,M3.5.0/-2,M10.5.0/-1' }, + { 'America/Ojinaga', 'MST7MDT,M3.2.0,M11.1.0' }, + { 'America/Panama', 'EST5' }, + { 'America/Pangnirtung', 'EST5EDT,M3.2.0,M11.1.0' }, + { 'America/Paramaribo', '<-03>3' }, + { 'America/Phoenix', 'MST7' }, + { 'America/Port of Spain', 'AST4' }, + { 'America/Port-au-Prince', 'EST5EDT,M3.2.0,M11.1.0' }, + { 'America/Porto Velho', '<-04>4' }, + { 'America/Puerto Rico', 'AST4' }, + { 'America/Punta Arenas', '<-03>3' }, + { 'America/Rainy River', 'CST6CDT,M3.2.0,M11.1.0' }, + { 'America/Rankin Inlet', 'CST6CDT,M3.2.0,M11.1.0' }, + { 'America/Recife', '<-03>3' }, + { 'America/Regina', 'CST6' }, + { 'America/Resolute', 'CST6CDT,M3.2.0,M11.1.0' }, + { 'America/Rio Branco', '<-05>5' }, + { 'America/Santarem', '<-03>3' }, + { 'America/Santiago', '<-04>4<-03>,M9.1.6/24,M4.1.6/24' }, + { 'America/Santo Domingo', 'AST4' }, + { 'America/Sao Paulo', '<-03>3' }, + { 'America/Scoresbysund', '<-01>1<+00>,M3.5.0/0,M10.5.0/1' }, + { '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', 'MST7' }, + { 'America/Winnipeg', 'CST6CDT,M3.2.0,M11.1.0' }, + { 'America/Yakutat', 'AKST9AKDT,M3.2.0,M11.1.0' }, + { 'America/Yellowknife', 'MST7MDT,M3.2.0,M11.1.0' }, + { 'Antarctica/Casey', '<+11>-11' }, + { 'Antarctica/Davis', '<+07>-7' }, + { 'Antarctica/DumontDUrville', '<+10>-10' }, + { 'Antarctica/Macquarie', 'AEST-10AEDT,M10.1.0,M4.1.0/3' }, + { 'Antarctica/Mawson', '<+05>-5' }, + { 'Antarctica/McMurdo', 'NZST-12NZDT,M9.5.0,M4.1.0/3' }, + { 'Antarctica/Palmer', '<-03>3' }, + { 'Antarctica/Rothera', '<-03>3' }, + { 'Antarctica/Syowa', '<+03>-3' }, + { 'Antarctica/Troll', '<+00>0<+02>-2,M3.5.0/1,M10.5.0/3' }, + { 'Antarctica/Vostok', '<+06>-6' }, + { 'Arctic/Longyearbyen', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Asia/Aden', '<+03>-3' }, + { 'Asia/Almaty', '<+06>-6' }, + { 'Asia/Amman', '<+03>-3' }, + { 'Asia/Anadyr', '<+12>-12' }, + { 'Asia/Aqtau', '<+05>-5' }, + { 'Asia/Aqtobe', '<+05>-5' }, + { 'Asia/Ashgabat', '<+05>-5' }, + { 'Asia/Atyrau', '<+05>-5' }, + { 'Asia/Baghdad', '<+03>-3' }, + { 'Asia/Bahrain', '<+03>-3' }, + { 'Asia/Baku', '<+04>-4' }, + { 'Asia/Bangkok', '<+07>-7' }, + { 'Asia/Barnaul', '<+07>-7' }, + { 'Asia/Beirut', 'EET-2EEST,M3.5.0/0,M10.5.0/0' }, + { 'Asia/Bishkek', '<+06>-6' }, + { 'Asia/Brunei', '<+08>-8' }, + { 'Asia/Chita', '<+09>-9' }, + { 'Asia/Choibalsan', '<+08>-8' }, + { 'Asia/Colombo', '<+0530>-5:30' }, + { 'Asia/Damascus', '<+03>-3' }, + { 'Asia/Dhaka', '<+06>-6' }, + { 'Asia/Dili', '<+09>-9' }, + { 'Asia/Dubai', '<+04>-4' }, + { 'Asia/Dushanbe', '<+05>-5' }, + { 'Asia/Famagusta', 'EET-2EEST,M3.5.0/3,M10.5.0/4' }, + { 'Asia/Gaza', 'EET-2EEST,M3.4.4/50,M10.4.4/50' }, + { 'Asia/Hebron', 'EET-2EEST,M3.4.4/50,M10.4.4/50' }, + { 'Asia/Ho Chi Minh', '<+07>-7' }, + { 'Asia/Hong Kong', 'HKT-8' }, + { 'Asia/Hovd', '<+07>-7' }, + { 'Asia/Irkutsk', '<+08>-8' }, + { 'Asia/Jakarta', 'WIB-7' }, + { 'Asia/Jayapura', 'WIT-9' }, + { 'Asia/Jerusalem', 'IST-2IDT,M3.4.4/26,M10.5.0' }, + { 'Asia/Kabul', '<+0430>-4:30' }, + { 'Asia/Kamchatka', '<+12>-12' }, + { 'Asia/Karachi', 'PKT-5' }, + { 'Asia/Kathmandu', '<+0545>-5:45' }, + { 'Asia/Khandyga', '<+09>-9' }, + { 'Asia/Kolkata', 'IST-5:30' }, + { 'Asia/Krasnoyarsk', '<+07>-7' }, + { 'Asia/Kuala Lumpur', '<+08>-8' }, + { 'Asia/Kuching', '<+08>-8' }, + { 'Asia/Kuwait', '<+03>-3' }, + { 'Asia/Macau', 'CST-8' }, + { 'Asia/Magadan', '<+11>-11' }, + { 'Asia/Makassar', 'WITA-8' }, + { 'Asia/Manila', 'PST-8' }, + { 'Asia/Muscat', '<+04>-4' }, + { 'Asia/Nicosia', 'EET-2EEST,M3.5.0/3,M10.5.0/4' }, + { 'Asia/Novokuznetsk', '<+07>-7' }, + { 'Asia/Novosibirsk', '<+07>-7' }, + { 'Asia/Omsk', '<+06>-6' }, + { 'Asia/Oral', '<+05>-5' }, + { 'Asia/Phnom Penh', '<+07>-7' }, + { 'Asia/Pontianak', 'WIB-7' }, + { 'Asia/Pyongyang', 'KST-9' }, + { 'Asia/Qatar', '<+03>-3' }, + { 'Asia/Qostanay', '<+06>-6' }, + { 'Asia/Qyzylorda', '<+05>-5' }, + { 'Asia/Riyadh', '<+03>-3' }, + { 'Asia/Sakhalin', '<+11>-11' }, + { 'Asia/Samarkand', '<+05>-5' }, + { 'Asia/Seoul', 'KST-9' }, + { 'Asia/Shanghai', 'CST-8' }, + { 'Asia/Singapore', '<+08>-8' }, + { 'Asia/Srednekolymsk', '<+11>-11' }, + { 'Asia/Taipei', 'CST-8' }, + { 'Asia/Tashkent', '<+05>-5' }, + { 'Asia/Tbilisi', '<+04>-4' }, + { 'Asia/Tehran', '<+0330>-3:30' }, + { 'Asia/Thimphu', '<+06>-6' }, + { 'Asia/Tokyo', 'JST-9' }, + { 'Asia/Tomsk', '<+07>-7' }, + { 'Asia/Ulaanbaatar', '<+08>-8' }, + { 'Asia/Urumqi', '<+06>-6' }, + { 'Asia/Ust-Nera', '<+10>-10' }, + { 'Asia/Vientiane', '<+07>-7' }, + { 'Asia/Vladivostok', '<+10>-10' }, + { 'Asia/Yakutsk', '<+09>-9' }, + { 'Asia/Yangon', '<+0630>-6:30' }, + { 'Asia/Yekaterinburg', '<+05>-5' }, + { 'Asia/Yerevan', '<+04>-4' }, + { 'Atlantic/Azores', '<-01>1<+00>,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', '<-01>1' }, + { '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', '<-02>2' }, + { 'Atlantic/St Helena', 'GMT0' }, + { 'Atlantic/Stanley', '<-03>3' }, + { 'Australia/Adelaide', 'ACST-9:30ACDT,M10.1.0,M4.1.0/3' }, + { 'Australia/Brisbane', 'AEST-10' }, + { 'Australia/Broken Hill', 'ACST-9:30ACDT,M10.1.0,M4.1.0/3' }, + { 'Australia/Darwin', 'ACST-9:30' }, + { 'Australia/Eucla', '<+0845>-8:45' }, + { 'Australia/Hobart', 'AEST-10AEDT,M10.1.0,M4.1.0/3' }, + { 'Australia/Lindeman', 'AEST-10' }, + { 'Australia/Lord Howe', '<+1030>-10:30<+11>-11,M10.1.0,M4.1.0' }, + { 'Australia/Melbourne', 'AEST-10AEDT,M10.1.0,M4.1.0/3' }, + { 'Australia/Perth', 'AWST-8' }, + { 'Australia/Sydney', 'AEST-10AEDT,M10.1.0,M4.1.0/3' }, + { 'Etc/GMT', 'GMT0' }, + { 'Etc/GMT+1', '<-01>1' }, + { 'Etc/GMT+10', '<-10>10' }, + { 'Etc/GMT+11', '<-11>11' }, + { 'Etc/GMT+12', '<-12>12' }, + { 'Etc/GMT+2', '<-02>2' }, + { 'Etc/GMT+3', '<-03>3' }, + { 'Etc/GMT+4', '<-04>4' }, + { 'Etc/GMT+5', '<-05>5' }, + { 'Etc/GMT+6', '<-06>6' }, + { 'Etc/GMT+7', '<-07>7' }, + { 'Etc/GMT+8', '<-08>8' }, + { 'Etc/GMT+9', '<-09>9' }, + { 'Etc/GMT-1', '<+01>-1' }, + { 'Etc/GMT-10', '<+10>-10' }, + { 'Etc/GMT-11', '<+11>-11' }, + { 'Etc/GMT-12', '<+12>-12' }, + { 'Etc/GMT-13', '<+13>-13' }, + { 'Etc/GMT-14', '<+14>-14' }, + { 'Etc/GMT-2', '<+02>-2' }, + { 'Etc/GMT-3', '<+03>-3' }, + { 'Etc/GMT-4', '<+04>-4' }, + { 'Etc/GMT-5', '<+05>-5' }, + { 'Etc/GMT-6', '<+06>-6' }, + { 'Etc/GMT-7', '<+07>-7' }, + { 'Etc/GMT-8', '<+08>-8' }, + { 'Etc/GMT-9', '<+09>-9' }, + { 'Europe/Amsterdam', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Andorra', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Astrakhan', '<+04>-4' }, + { '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/Busingen', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Chisinau', 'EET-2EEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Copenhagen', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Dublin', 'IST-1GMT0,M10.5.0,M3.5.0/1' }, + { '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', '<+03>-3' }, + { 'Europe/Jersey', 'GMT0BST,M3.5.0/1,M10.5.0' }, + { 'Europe/Kaliningrad', 'EET-2' }, + { 'Europe/Kirov', '<+03>-3' }, + { 'Europe/Kyiv', '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', '<+03>-3' }, + { 'Europe/Monaco', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Moscow', 'MSK-3' }, + { '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', '<+04>-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/Saratov', '<+04>-4' }, + { 'Europe/Simferopol', 'MSK-3' }, + { '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/Ulyanovsk', '<+04>-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', '<+03>-3' }, + { 'Europe/Warsaw', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Zagreb', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Europe/Zurich', 'CET-1CEST,M3.5.0,M10.5.0/3' }, + { 'Indian/Antananarivo', 'EAT-3' }, + { 'Indian/Chagos', '<+06>-6' }, + { 'Indian/Christmas', '<+07>-7' }, + { 'Indian/Cocos', '<+0630>-6:30' }, + { 'Indian/Comoro', 'EAT-3' }, + { 'Indian/Kerguelen', '<+05>-5' }, + { 'Indian/Mahe', '<+04>-4' }, + { 'Indian/Maldives', '<+05>-5' }, + { 'Indian/Mauritius', '<+04>-4' }, + { 'Indian/Mayotte', 'EAT-3' }, + { 'Indian/Reunion', '<+04>-4' }, + { 'Pacific/Apia', '<+13>-13' }, + { 'Pacific/Auckland', 'NZST-12NZDT,M9.5.0,M4.1.0/3' }, + { 'Pacific/Bougainville', '<+11>-11' }, + { 'Pacific/Chatham', '<+1245>-12:45<+1345>,M9.5.0/2:45,M4.1.0/3:45' }, + { 'Pacific/Chuuk', '<+10>-10' }, + { 'Pacific/Easter', '<-06>6<-05>,M9.1.6/22,M4.1.6/22' }, + { 'Pacific/Efate', '<+11>-11' }, + { 'Pacific/Fakaofo', '<+13>-13' }, + { 'Pacific/Fiji', '<+12>-12<+13>,M11.2.0,M1.2.3/99' }, + { 'Pacific/Funafuti', '<+12>-12' }, + { 'Pacific/Galapagos', '<-06>6' }, + { 'Pacific/Gambier', '<-09>9' }, + { 'Pacific/Guadalcanal', '<+11>-11' }, + { 'Pacific/Guam', 'ChST-10' }, + { 'Pacific/Honolulu', 'HST10' }, + { 'Pacific/Kanton', '<+13>-13' }, + { 'Pacific/Kiritimati', '<+14>-14' }, + { 'Pacific/Kosrae', '<+11>-11' }, + { 'Pacific/Kwajalein', '<+12>-12' }, + { 'Pacific/Majuro', '<+12>-12' }, + { 'Pacific/Marquesas', '<-0930>9:30' }, + { 'Pacific/Midway', 'SST11' }, + { 'Pacific/Nauru', '<+12>-12' }, + { 'Pacific/Niue', '<-11>11' }, + { 'Pacific/Norfolk', '<+11>-11<+12>,M10.1.0,M4.1.0/3' }, + { 'Pacific/Noumea', '<+11>-11' }, + { 'Pacific/Pago Pago', 'SST11' }, + { 'Pacific/Palau', '<+09>-9' }, + { 'Pacific/Pitcairn', '<-08>8' }, + { 'Pacific/Pohnpei', '<+11>-11' }, + { 'Pacific/Port Moresby', '<+10>-10' }, + { 'Pacific/Rarotonga', '<-10>10' }, + { 'Pacific/Saipan', 'ChST-10' }, + { 'Pacific/Tahiti', '<-10>10' }, + { 'Pacific/Tarawa', '<+12>-12' }, + { 'Pacific/Tongatapu', '<+13>-13' }, + { 'Pacific/Wake', '<+12>-12' }, + { 'Pacific/Wallis', '<+12>-12' }, +} diff --git a/ipk-source/luci-lua-runtime_aarch64_cortex-a53/root/usr/lib/lua/luci/sys/zoneinfo/tzoffset.lua b/ipk-source/luci-lua-runtime_aarch64_cortex-a53/root/usr/lib/lua/luci/sys/zoneinfo/tzoffset.lua new file mode 100644 index 0000000..caee1d2 --- /dev/null +++ b/ipk-source/luci-lua-runtime_aarch64_cortex-a53/root/usr/lib/lua/luci/sys/zoneinfo/tzoffset.lua @@ -0,0 +1,46 @@ +-- Licensed to the public under the Apache License 2.0. + +module "luci.sys.zoneinfo.tzoffset" + +OFFSET = { + gmt = 0, -- GMT + eat = 10800, -- EAT + cet = 3600, -- CET + wat = 3600, -- WAT + cat = 7200, -- CAT + eet = 7200, -- EET + sast = 7200, -- SAST + hst = -36000, -- HST + hdt = -32400, -- HDT + akst = -32400, -- AKST + akdt = -28800, -- AKDT + ast = -14400, -- AST + est = -18000, -- EST + cst = -21600, -- CST + cdt = -18000, -- CDT + mst = -25200, -- MST + mdt = -21600, -- MDT + pst = -28800, -- PST + pdt = -25200, -- PDT + nst = -12600, -- NST + ndt = -9000, -- NDT + aest = 36000, -- AEST + aedt = 39600, -- AEDT + nzst = 43200, -- NZST + nzdt = 46800, -- NZDT + hkt = 28800, -- HKT + wib = 25200, -- WIB + wit = 32400, -- WIT + ist = 7200, -- IST + idt = 10800, -- IDT + pkt = 18000, -- PKT + wita = 28800, -- WITA + kst = 32400, -- KST + jst = 32400, -- JST + wet = 0, -- WET + acst = 34200, -- ACST + acdt = 37800, -- ACDT + awst = 28800, -- AWST + msk = 10800, -- MSK + sst = -39600, -- SST +} diff --git a/ipk-source/luci-lua-runtime_aarch64_cortex-a53/root/usr/lib/lua/luci/template.lua b/ipk-source/luci-lua-runtime_aarch64_cortex-a53/root/usr/lib/lua/luci/template.lua new file mode 100644 index 0000000..b6b9af0 --- /dev/null +++ b/ipk-source/luci-lua-runtime_aarch64_cortex-a53/root/usr/lib/lua/luci/template.lua @@ -0,0 +1,184 @@ +-- Copyright 2008 Steven Barth +-- Licensed to the public under the Apache License 2.0. + +local util = require "luci.util" +local config = require "luci.config" +local tparser = require "luci.template.parser" + +local tostring, pairs, loadstring = tostring, pairs, loadstring +local setmetatable, loadfile = setmetatable, loadfile +local getfenv, setfenv, rawget = getfenv, setfenv, rawget +local assert, type, error = assert, type, error +local table, string, unpack = table, string, unpack + + +--- +--- bootstrap +--- +local _G = _G +local L = _G.L + +local http = _G.L.http + +local disp = require "luci.dispatcher" +local i18n = require "luci.i18n" +local xml = require "luci.xml" +local fs = require "nixio.fs" + + +--- LuCI template library. +module "luci.template" + +config.template = config.template or {} +viewdir = config.template.viewdir or util.libpath() .. "/view" + + +-- Define the namespace for template modules +context = {} --util.threadlocal() + +--- Render a certain template. +-- @param name Template name +-- @param scope Scope to assign to template (optional) +function render(name, scope) + return Template(name):render(scope or getfenv(2)) +end + +--- Render a template from a string. +-- @param template Template string +-- @param scope Scope to assign to template (optional) +function render_string(template, scope) + return Template(nil, template):render(scope or getfenv(2)) +end + + +-- Template class +Template = util.class() + +-- Shared template cache to store templates in to avoid unnecessary reloading +Template.cache = setmetatable({}, {__mode = "v"}) + + + +local function _ifattr(cond, key, val, noescape) + if cond then + local env = getfenv(3) + local scope = (type(env.self) == "table") and env.self + if type(val) == "table" then + if not next(val) then + return '' + else + val = util.serialize_json(val) + end + end + + val = tostring(val or + (type(env[key]) ~= "function" and env[key]) or + (scope and type(scope[key]) ~= "function" and scope[key]) or "") + + if noescape ~= true then + val = xml.pcdata(val) + end + + return string.format(' %s="%s"', tostring(key), val) + else + return '' + end +end + +context.viewns = setmetatable({ + include = function(name) + if fs.access(viewdir .. "/" .. name .. ".htm") then + Template(name):render(getfenv(2)) + else + L.include(name, getfenv(2)) + end + end; + translate = i18n.translate; + translatef = i18n.translatef; + export = function(k, v) if context.viewns[k] == nil then context.viewns[k] = v end end; + striptags = xml.striptags; + pcdata = xml.pcdata; + ifattr = function(...) return _ifattr(...) end; + attr = function(...) return _ifattr(true, ...) end; + url = disp.build_url; +}, {__index=function(tbl, key) + if key == "controller" then + return disp.build_url() + elseif key == "REQUEST_URI" then + return disp.build_url(unpack(disp.context.requestpath)) + elseif key == "FULL_REQUEST_URI" then + local url = { http:getenv("SCRIPT_NAME") or "", http:getenv("PATH_INFO") } + local query = http:getenv("QUERY_STRING") + if query and #query > 0 then + url[#url+1] = "?" + url[#url+1] = query + end + return table.concat(url, "") + elseif key == "token" then + return disp.context.authtoken + elseif key == "theme" then + return L.media and fs.basename(L.media) or tostring(L) + elseif key == "resource" then + return L.config.main.resourcebase + else + return rawget(tbl, key) or _G[key] or L[key] + end +end}) + + +-- Constructor - Reads and compiles the template on-demand +function Template.__init__(self, name, template) + if name then + self.template = self.cache[name] + self.name = name + else + self.name = "[string]" + end + + -- Create a new namespace for this template + self.viewns = context.viewns + + -- If we have a cached template, skip compiling and loading + if not self.template then + + -- Compile template + local err + local sourcefile + + if name then + sourcefile = viewdir .. "/" .. name .. ".htm" + self.template, _, err = tparser.parse(sourcefile) + else + sourcefile = "[string]" + self.template, _, err = tparser.parse_string(template) + end + + -- If we have no valid template throw error, otherwise cache the template + if not self.template then + error("Failed to load template '" .. self.name .. "'.\n" .. + "Error while parsing template '" .. sourcefile .. "':\n" .. + (err or "Unknown syntax error")) + elseif name then + self.cache[name] = self.template + end + end +end + + +-- Renders a template +function Template.render(self, scope) + scope = scope or getfenv(2) + + -- Put our predefined objects in the scope of the template + setfenv(self.template, setmetatable({}, {__index = + function(tbl, key) + return rawget(tbl, key) or self.viewns[key] or scope[key] + end})) + + -- Now finally render the thing + local stat, err = util.copcall(self.template) + if not stat then + error("Failed to execute template '" .. self.name .. "'.\n" .. + "A runtime error occurred: " .. tostring(err or "(nil)")) + end +end diff --git a/ipk-source/luci-lua-runtime_aarch64_cortex-a53/root/usr/lib/lua/luci/template/parser.so b/ipk-source/luci-lua-runtime_aarch64_cortex-a53/root/usr/lib/lua/luci/template/parser.so new file mode 100755 index 0000000..c96a60d Binary files /dev/null and b/ipk-source/luci-lua-runtime_aarch64_cortex-a53/root/usr/lib/lua/luci/template/parser.so differ diff --git a/ipk-source/luci-lua-runtime_aarch64_cortex-a53/root/usr/lib/lua/luci/ucodebridge.lua b/ipk-source/luci-lua-runtime_aarch64_cortex-a53/root/usr/lib/lua/luci/ucodebridge.lua new file mode 100644 index 0000000..d36b974 --- /dev/null +++ b/ipk-source/luci-lua-runtime_aarch64_cortex-a53/root/usr/lib/lua/luci/ucodebridge.lua @@ -0,0 +1,54 @@ +-- Copyright 2022 Jo-Philipp Wich +-- Licensed to the public under the Apache License 2.0. + +local coroutine, assert, error, type, require = coroutine, assert, error, type, require +local tmpl = require "luci.template" +local util = require "luci.util" +local http = require "luci.http" +local sys = require "luci.sys" +local ltn12 = require "luci.ltn12" + + +--- LuCI ucode bridge library. +module "luci.ucodebridge" + +local function run(fn, ...) + local co = coroutine.create(fn) + local ok, ret + + while coroutine.status(co) ~= "dead" do + ok, ret = coroutine.resume(co, ...) + + if not ok then + error(ret) + end + end + + return ret +end + +function compile(path) + run(function(path) + return tmpl.Template(path) + end, path) +end + +function render(path, scope) + run(tmpl.render, path, scope) +end + +function call(modname, method, ...) + return run(function(module, method, ...) + local mod = require(modname) + local func = mod[method] + + assert(func ~= nil, + 'Cannot resolve function "' .. method .. '". Is it misspelled or local?') + + assert(type(func) == "function", + 'The symbol "' .. method .. '" does not refer to a function but data ' .. + 'of type "' .. type(func) .. '".') + + return func(...) + end, modname, method, ...) +end diff --git a/ipk-source/luci-lua-runtime_aarch64_cortex-a53/root/usr/lib/lua/luci/version.lua b/ipk-source/luci-lua-runtime_aarch64_cortex-a53/root/usr/lib/lua/luci/version.lua new file mode 100644 index 0000000..f0b73d1 --- /dev/null +++ b/ipk-source/luci-lua-runtime_aarch64_cortex-a53/root/usr/lib/lua/luci/version.lua @@ -0,0 +1,20 @@ +local pcall, dofile, _G = pcall, dofile, _G + +module "luci.version" + +if pcall(dofile, "/etc/openwrt_release") and _G.DISTRIB_DESCRIPTION then + distname = "" + distversion = _G.DISTRIB_DESCRIPTION + if _G.DISTRIB_REVISION then + distrevision = _G.DISTRIB_REVISION + if not distversion:find(distrevision,1,true) then + distversion = distversion .. " " .. distrevision + end + end +else + distname = "OpenWrt" + distversion = "Development Snapshot" +end + +luciname = "LuCI openwrt-24.10 branch" +luciversion = "25.034.70690~7b0663a" diff --git a/ipk-source/luci-lua-runtime_aarch64_cortex-a53/root/usr/lib/lua/luci/view/admin_status/luaindex.htm b/ipk-source/luci-lua-runtime_aarch64_cortex-a53/root/usr/lib/lua/luci/view/admin_status/luaindex.htm new file mode 100644 index 0000000..ef664ed --- /dev/null +++ b/ipk-source/luci-lua-runtime_aarch64_cortex-a53/root/usr/lib/lua/luci/view/admin_status/luaindex.htm @@ -0,0 +1,18 @@ +<%- + local util = require "luci.util" + local fs = require "nixio.fs" + + local incdir = util.libpath() .. "/view/admin_status/index/" + if fs.access(incdir) then + local _, inc + local includes = {} + for inc in fs.dir(incdir) do + if inc:match("%.htm$") then + includes[#includes + 1] = inc:gsub("%.htm$", "") + end + end + for _, inc in luci.util.vspairs(includes) do + include("admin_status/index/" .. inc) + end + end +-%> diff --git a/ipk-source/luci-lua-runtime_aarch64_cortex-a53/root/usr/lib/lua/luci/view/empty_node_placeholder.htm b/ipk-source/luci-lua-runtime_aarch64_cortex-a53/root/usr/lib/lua/luci/view/empty_node_placeholder.htm new file mode 100644 index 0000000..b7e276b --- /dev/null +++ b/ipk-source/luci-lua-runtime_aarch64_cortex-a53/root/usr/lib/lua/luci/view/empty_node_placeholder.htm @@ -0,0 +1,11 @@ +<%# + Copyright 2010 Jo-Philipp Wich + Copyright 2018 Daniel F. Dickinson + Licensed to the public under the Apache License 2.0. +-%> + +<%+header%> + +

Component not present.

+ +<%+footer%> diff --git a/ipk-source/luci-lua-runtime_aarch64_cortex-a53/root/usr/lib/lua/luci/view/indexer.htm b/ipk-source/luci-lua-runtime_aarch64_cortex-a53/root/usr/lib/lua/luci/view/indexer.htm new file mode 100644 index 0000000..28fc3de --- /dev/null +++ b/ipk-source/luci-lua-runtime_aarch64_cortex-a53/root/usr/lib/lua/luci/view/indexer.htm @@ -0,0 +1,7 @@ +<%# + Copyright 2008 Steven Barth + Copyright 2008 Jo-Philipp Wich + Licensed to the public under the Apache License 2.0. +-%> + +<% include("themes/" .. theme .. "/indexer") %> \ No newline at end of file diff --git a/ipk-source/luci-lua-runtime_aarch64_cortex-a53/root/usr/lib/lua/luci/xml.lua b/ipk-source/luci-lua-runtime_aarch64_cortex-a53/root/usr/lib/lua/luci/xml.lua new file mode 100644 index 0000000..30b3721 --- /dev/null +++ b/ipk-source/luci-lua-runtime_aarch64_cortex-a53/root/usr/lib/lua/luci/xml.lua @@ -0,0 +1,26 @@ +-- Copyright 2008 Steven Barth +-- Licensed to the public under the Apache License 2.0. + +local tparser = require "luci.template.parser" +local string = require "string" + +local tostring = tostring + +module "luci.xml" + +-- +-- String and data manipulation routines +-- + +function pcdata(value) + return value and tparser.pcdata(tostring(value)) +end + +function striptags(value) + return value and tparser.striptags(tostring(value)) +end + + +-- also register functions above in the central string class for convenience +string.pcdata = pcdata +string.striptags = striptags diff --git a/ipk-source/luci-theme-argon/CONTROL/control b/ipk-source/luci-theme-argon/CONTROL/control new file mode 100644 index 0000000..7fb86a4 --- /dev/null +++ b/ipk-source/luci-theme-argon/CONTROL/control @@ -0,0 +1,12 @@ +Package: luci-theme-argon +Version: 2.3.2-r20250207 +Depends: libc, curl, jsonfilter, luci-lua-runtime +Source: feeds/base/downloads/luci-theme-argon +SourceName: luci-theme-argon +Section: luci +SourceDateEpoch: 1739087731 +URL: https://github.com/openwrt/luci +Maintainer: OpenWrt LuCI community +Architecture: all +Installed-Size: 768000 +Description: Argon Theme diff --git a/ipk-source/luci-theme-argon/CONTROL/postinst b/ipk-source/luci-theme-argon/CONTROL/postinst new file mode 100755 index 0000000..3bba77c --- /dev/null +++ b/ipk-source/luci-theme-argon/CONTROL/postinst @@ -0,0 +1,5 @@ +#!/bin/sh +[ "${IPKG_NO_SCRIPT}" = "1" ] && exit 0 +[ -s ${IPKG_INSTROOT}/lib/functions.sh ] || exit 0 +. ${IPKG_INSTROOT}/lib/functions.sh +default_postinst $0 $@ diff --git a/ipk-source/luci-theme-argon/CONTROL/postinst-pkg b/ipk-source/luci-theme-argon/CONTROL/postinst-pkg new file mode 100755 index 0000000..2e52d45 --- /dev/null +++ b/ipk-source/luci-theme-argon/CONTROL/postinst-pkg @@ -0,0 +1,5 @@ +[ -n "${IPKG_INSTROOT}" ] || { rm -f /tmp/luci-indexcache.* + rm -rf /tmp/luci-modulecache/ + killall -HUP rpcd 2>/dev/null + exit 0 +} diff --git a/ipk-source/luci-theme-argon/CONTROL/prerm b/ipk-source/luci-theme-argon/CONTROL/prerm new file mode 100755 index 0000000..12d06ec --- /dev/null +++ b/ipk-source/luci-theme-argon/CONTROL/prerm @@ -0,0 +1,4 @@ +#!/bin/sh +[ -s ${IPKG_INSTROOT}/lib/functions.sh ] || exit 0 +. ${IPKG_INSTROOT}/lib/functions.sh +default_prerm $0 $@ diff --git a/ipk-source/luci-theme-argon/build-ipk b/ipk-source/luci-theme-argon/build-ipk new file mode 100755 index 0000000..eb83cf6 --- /dev/null +++ b/ipk-source/luci-theme-argon/build-ipk @@ -0,0 +1,74 @@ +#!/bin/sh + +# Script for building OpenWRT .ipk packages using tar by iamromulan +# Works with SDXPPINN OpenWRT - iamromulan +# This script accepts an optional path to the directory containing the `CONTROL` and `root` directories. +# Usage: ./build-ipk.sh [path] +# If no path is provided, the script will look in the current directory for `CONTROL` and `root` directories. +# This will spit out an ipk in the current directory + +# Check if the script is run as root. If not, rerun with sudo. +if [ "$(id -u)" -ne 0 ]; then + echo "Script is not running as root. Re-executing with sudo..." + exec sudo "$0" "$@" +fi + +# Set the default build path to the current directory +build_path="." + +# Check if a path is provided as the first argument +if [ "$1" ]; then + build_path="$1" +fi + +# Check if the required directories are present in the specified path +if [ ! -d "${build_path}/CONTROL" ] || [ ! -d "${build_path}/root" ]; then + echo "Error: CONTROL and root directories must be present in the specified path (${build_path})." + exit 1 +fi + +# Extract values from the CONTROL/control file in the specified path +pkgname=$(grep -i '^Package:' "${build_path}/CONTROL/control" | awk '{print $2}') +version=$(grep -i '^Version:' "${build_path}/CONTROL/control" | awk '{print $2}') +architecture=$(grep -i '^Architecture:' "${build_path}/CONTROL/control" | awk '{print $2}') + +# Check if values are extracted correctly +if [ -z "$pkgname" ] || [ -z "$version" ] || [ -z "$architecture" ]; then + echo "Error: Failed to extract Package, Version, or Architecture from ${build_path}/CONTROL/control." + exit 1 +fi + +# Set the final IPK name based on the extracted values +ipkname="${pkgname}_${version}_${architecture}.ipk" + +# Ensure all CONTROL scripts are executable +echo "Setting permissions for CONTROL scripts..." +chmod +x "${build_path}/CONTROL"/* + +# Set ownership for CONTROL and root files +echo "Setting ownership for all package files..." +chown -R root:root "${build_path}/CONTROL"/* +chown -R root:root "${build_path}/root"/* + +# Create control.tar.gz from the CONTROL directory +echo "Creating control.tar.gz..." +tar -czvf control.tar.gz -C "${build_path}/CONTROL" . + +# Create data.tar.gz from the root directory +echo "Creating data.tar.gz..." +tar -czvf data.tar.gz -C "${build_path}/root" . + +# Create debian-binary file (must contain exactly "2.0" without a newline) +echo -n "2.0" > debian-binary +chown -R root:root debian-binary + +# Combine the components into the final .ipk file using tar +echo "Packaging ${ipkname}..." +tar -czvf "$ipkname" debian-binary control.tar.gz data.tar.gz + +# Clean up intermediate files +echo "Cleaning up temporary files..." +rm -f control.tar.gz data.tar.gz debian-binary + +echo "IPK package ${ipkname} created successfully using tar." + diff --git a/ipk-source/luci-theme-argon/root/etc/uci-defaults/30_luci-theme-argon b/ipk-source/luci-theme-argon/root/etc/uci-defaults/30_luci-theme-argon new file mode 100644 index 0000000..6820d25 --- /dev/null +++ b/ipk-source/luci-theme-argon/root/etc/uci-defaults/30_luci-theme-argon @@ -0,0 +1,12 @@ +#!/bin/sh + +if [ "$PKG_UPGRADE" != 1 ]; then + uci get luci.themes.Argon >/dev/null 2>&1 || \ + uci batch <<-EOF + set luci.themes.Argon=/luci-static/argon + set luci.main.mediaurlbase=/luci-static/argon + commit luci + EOF +fi + +exit 0 diff --git a/ipk-source/luci-theme-argon/root/usr/lib/lua/luci/view/themes/argon/footer.htm b/ipk-source/luci-theme-argon/root/usr/lib/lua/luci/view/themes/argon/footer.htm new file mode 100644 index 0000000..6b3d3fe --- /dev/null +++ b/ipk-source/luci-theme-argon/root/usr/lib/lua/luci/view/themes/argon/footer.htm @@ -0,0 +1,46 @@ +<%# + Argon is a clean HTML5 theme for LuCI. It is based on luci-theme-material Argon Template + + luci-theme-argon + Copyright 2020 Jerrykuku + + Have a bug? Please create an issue here on GitHub! + https://github.com/jerrykuku/luci-theme-argon/issues + + luci-theme-material: + Copyright 2015 Lutty Yang + + Agron Theme + https://demos.creative-tim.com/argon-dashboard/index.html + + Licensed to the public under the Apache License 2.0 +-%> + +<% local ver = require "luci.version" %> + + + + + + + + diff --git a/ipk-source/luci-theme-argon/root/usr/lib/lua/luci/view/themes/argon/footer_login.htm b/ipk-source/luci-theme-argon/root/usr/lib/lua/luci/view/themes/argon/footer_login.htm new file mode 100644 index 0000000..e7092ac --- /dev/null +++ b/ipk-source/luci-theme-argon/root/usr/lib/lua/luci/view/themes/argon/footer_login.htm @@ -0,0 +1,44 @@ +<%# + Argon is a clean HTML5 theme for LuCI. It is based on luci-theme-material Argon Template + + luci-theme-argon + Copyright 2020 Jerrykuku + + Have a bug? Please create an issue here on GitHub! + https://github.com/jerrykuku/luci-theme-argon/issues + + luci-theme-material: + Copyright 2015 Lutty Yang + + Agron Theme + https://demos.creative-tim.com/argon-dashboard/index.html + + Licensed to the public under the Apache License 2.0 +-%> + +<% local ver = require "luci.version" %> + + + + + + + diff --git a/ipk-source/luci-theme-argon/root/usr/lib/lua/luci/view/themes/argon/header.htm b/ipk-source/luci-theme-argon/root/usr/lib/lua/luci/view/themes/argon/header.htm new file mode 100644 index 0000000..3d3511e --- /dev/null +++ b/ipk-source/luci-theme-argon/root/usr/lib/lua/luci/view/themes/argon/header.htm @@ -0,0 +1,180 @@ +<%# + Argon is a clean HTML5 theme for LuCI. It is based on luci-theme-material Argon Template + + luci-theme-argon + Copyright 2020 Jerrykuku + + Have a bug? Please create an issue here on GitHub! + https://github.com/jerrykuku/luci-theme-argon/issues + + luci-theme-material: + Copyright 2015 Lutty Yang + + Argon Theme + https://demos.creative-tim.com/argon-dashboard/index.html + + Licensed to the public under the Apache License 2.0 +-%> + +<% + local sys = require "luci.sys" + local util = require "luci.util" + local http = require "luci.http" + local disp = require "luci.dispatcher" + local ver = require "luci.version" + + local boardinfo = util.ubus("system", "board") + + local node = disp.context.dispatched + + local fs = require "nixio.fs" + local nutil = require "nixio.util" + local uci = require 'luci.model.uci'.cursor() + + -- send as HTML5 + http.prepare_content("text/html") + + math.randomseed(os.time()) + + -- Custom settings + local mode = 'normal' + local dark_css = fs.readfile('/www/luci-static/argon/css/dark.css') + local bar_color = '#5e72e4' + local primary, dark_primary, blur_radius, blur_radius_dark, blur_opacity + if fs.access('/etc/config/argon') then + primary = uci:get_first('argon', 'global', 'primary') + dark_primary = uci:get_first('argon', 'global', 'dark_primary') + blur_radius = uci:get_first('argon', 'global', 'blur') + blur_radius_dark = uci:get_first('argon', 'global', 'blur_dark') + blur_opacity = uci:get_first('argon', 'global', 'transparency') + blur_opacity_dark = uci:get_first('argon', 'global', 'transparency_dark') + mode = uci:get_first('argon', 'global', 'mode') + bar_color = mode == 'dark' and dark_primary or primary + end + + -- Brand name + local brand_name = boardinfo.hostname or "?" +-%> + + + + + + + <%=striptags( (boardinfo.hostname or "?") .. ( (node and node.title) and ' - ' .. translate(node.title) or '')) %> + - LuCI + + + + + + + + + + + - LuCI"> + - LuCI"> + + + + + + + + + + + + + + + <% if node and node.css then %> + + <% end -%> + <% if css then %> + + <% end -%> + + + + + + + +"> + +
+ +
+
+
+
+ +
+
+
+
+
+
+
+ <%- if luci.sys.process.info("uid") == 0 and luci.sys.user.getuser("root") and not luci.sys.user.getpasswd("root") then -%> +
+

<%:No password set!%>

+

<%:There is no password set on this router. Please configure a root password to protect the web interface.%> +

+ <% if disp.lookup("admin/system/admin") then %> + + <% end %> +
+ <%- end -%> + + + + diff --git a/ipk-source/luci-theme-argon/root/usr/lib/lua/luci/view/themes/argon/header_login.htm b/ipk-source/luci-theme-argon/root/usr/lib/lua/luci/view/themes/argon/header_login.htm new file mode 100644 index 0000000..6fb30e5 --- /dev/null +++ b/ipk-source/luci-theme-argon/root/usr/lib/lua/luci/view/themes/argon/header_login.htm @@ -0,0 +1,119 @@ +<%# + Argon is a clean HTML5 theme for LuCI. It is based on luci-theme-material Argon Template + + luci-theme-argon + Copyright 2020 Jerrykuku + + Have a bug? Please create an issue here on GitHub! + https://github.com/jerrykuku/luci-theme-argon/issues + + luci-theme-material: + Copyright 2015 Lutty Yang + + Argon Theme + https://demos.creative-tim.com/argon-dashboard/index.html + + Licensed to the public under the Apache License 2.0 +-%> + +<% + local sys = require "luci.sys" + local util = require "luci.util" + local http = require "luci.http" + local disp = require "luci.dispatcher" + local ver = require "luci.version" + + local boardinfo = util.ubus("system", "board") + + local node = disp.context.dispatched + + local fs = require "nixio.fs" + local nutil = require "nixio.util" + local uci = require 'luci.model.uci'.cursor() + + -- send as HTML5 + http.prepare_content("text/html") + + math.randomseed(tonumber(tostring(os.time()):reverse():sub(1, 9))) + + -- Custom settings + local mode = 'normal' + local dark_css = fs.readfile('/www/luci-static/argon/css/dark.css') + local bar_color = '#5e72e4' + local primary, dark_primary, blur_radius, blur_radius_dark, blur_opacity + if fs.access('/etc/config/argon') then + primary = uci:get_first('argon', 'global', 'primary') + dark_primary = uci:get_first('argon', 'global', 'dark_primary') + blur_radius = uci:get_first('argon', 'global', 'blur') + blur_radius_dark = uci:get_first('argon', 'global', 'blur_dark') + blur_opacity = uci:get_first('argon', 'global', 'transparency') + blur_opacity_dark = uci:get_first('argon', 'global', 'transparency_dark') + mode = uci:get_first('argon', 'global', 'mode') + bar_color = mode == 'dark' and dark_primary or primary + end +-%> + + + + + + + <%=striptags( (boardinfo.hostname or "?") .. ( (node and node.title) and ' - ' .. translate(node.title) or '')) %> + - LuCI + + + + + + + + + + + - LuCI"> + - LuCI"> + + + + + + + + + + + + + + + <% if node and node.css then %> + + <% end -%> + <% if css then %> + + <% end -%> + + + + + diff --git a/ipk-source/luci-theme-argon/root/usr/lib/lua/luci/view/themes/argon/out_header_login.htm b/ipk-source/luci-theme-argon/root/usr/lib/lua/luci/view/themes/argon/out_header_login.htm new file mode 100644 index 0000000..35e73ec --- /dev/null +++ b/ipk-source/luci-theme-argon/root/usr/lib/lua/luci/view/themes/argon/out_header_login.htm @@ -0,0 +1,14 @@ +<%# + Copyright 2008 Steven Barth + Copyright 2008-2019 Jo-Philipp Wich + Licensed to the public under the Apache License 2.0. +-%> + +<% + local ver = require "luci.version" + + if not luci.dispatcher.context.template_header_sent then + include("themes/" .. theme .. "/header_login") + luci.dispatcher.context.template_header_sent = true + end +%> diff --git a/ipk-source/luci-theme-argon/root/usr/lib/lua/luci/view/themes/argon/sysauth.htm b/ipk-source/luci-theme-argon/root/usr/lib/lua/luci/view/themes/argon/sysauth.htm new file mode 100644 index 0000000..1fb399b --- /dev/null +++ b/ipk-source/luci-theme-argon/root/usr/lib/lua/luci/view/themes/argon/sysauth.htm @@ -0,0 +1,163 @@ +<%# + Argon is a clean HTML5 theme for LuCI. It is based on luci-theme-bootstrap and MUI and Argon Template + + luci-theme-argon + Copyright 2020 Jerryk + + Have a bug? Please create an issue here on GitHub! + https://github.com/jerrykuku/luci-theme-argon/issues + + luci-theme-bootstrap: + Copyright 2008 Steven Barth + Copyright 2008-2016 Jo-Philipp Wich + Copyright 2012 David Menting + + MUI: + https://github.com/muicss/mui + + Argon Theme + https://demos.creative-tim.com/argon-dashboard/index.html + + Licensed to the public under the Apache License 2.0 +-%> + +<%+themes/argon/out_header_login%> +<% + local util = require "luci.util" + local fs = require "nixio.fs" + local nutil = require "nixio.util" + local json = require "luci.jsonc" + local sys = require "luci.sys" + local uci = require 'luci.model.uci'.cursor() + + -- Fetch Local Background Media + + local function glob(...) + local iter, code, msg = fs.glob(...) + if iter then + return nutil.consume(iter) + else + return nil, code, msg + end + end + + + local imageTypes = " jpg png gif webp " + local videoTypes = " mp4 webm " + local allTypes = imageTypes .. videoTypes + local function fetchMedia(path, themeDir) + local backgroundTable = {} + local backgroundCount = 0 + for i, f in ipairs(glob(path)) do + attr = fs.stat(f) + if attr then + local ext = fs.basename(f):match(".+%.(%w+)$") + if ext ~= nil then + ext = ext:lower() + end + if ext ~= nil and string.match(allTypes, " "..ext.." ") ~= nil then + local bg = {} + bg.type = ext + bg.url = themeDir .. fs.basename(f) + table.insert(backgroundTable, bg) + backgroundCount = backgroundCount + 1 + end + end + end + return backgroundTable, backgroundCount + end + local function selectBackground(themeDir) + local bgUrl = media .. "/img/bg1.jpg" + local backgroundType = "Image" + local mimeType = "" + + if fs.access("/etc/config/argon") then + local online_wallpaper = uci:get_first('argon', 'global', 'online_wallpaper') or (uci:get_first('argon', 'global', 'bing_background') == '1' and 'bing') + if (online_wallpaper and online_wallpaper ~= "none") then + local picurl = sys.exec("/usr/libexec/argon/online_wallpaper") + if (picurl and picurl ~= '') then + return picurl, "Image", "" + end + end + end + + local backgroundTable, backgroundCount = fetchMedia("/www" .. themeDir .. "*", themeDir) + if ( backgroundCount > 0 ) then + local currentBg = backgroundTable[math.random(1, backgroundCount)] + bgUrl = currentBg.url + if (string.match(videoTypes, " "..currentBg.type.." ") ~= nil) then + backgroundType = "Video" + mimeType = "video/" .. currentBg.type + end + end + + return bgUrl, backgroundType, mimeType + end + + local boardinfo = util.ubus("system", "board") + local themeDir = media .. "/background/" + local bgUrl, backgroundType, mimeType = selectBackground(themeDir) +%> + +