⛄ Sync 2026-10-22 00:07:59

This commit is contained in:
github-actions[bot] committed 2026-10-22 00:07:59 +08:00
1 parent 31748c050e
commit d047be4ede
22 files changed
+379 -173

No files matched your search

+1 -1
View File
@@ -2,7 +2,7 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=beszel
PKG_VERSION:=0.21.0
PKG_RELEASE:=12
PKG_RELEASE:=13
PKG_SOURCE:=beszel-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://codeload.github.com/henrygd/beszel/tar.gz/v$(PKG_VERSION)?
@@ -1,14 +1,14 @@
From 128555126155413ce32b134435c425ad9bb24501 Mon Sep 17 00:00:00 2001
From 70f6bfc114b419ad1d1d999c4e74906c1ebc3819 Mon Sep 17 00:00:00 2001
From: Jackie Han <jackie.han@gmail.com>
Date: Wed, 14 Oct 2026 07:40:03 +0800
Subject: [PATCH] Refactor collect function to handle wireless devices
Date: Wed, 21 Oct 2026 22:20:40 +0800
Subject: [PATCH] Refactor WiFi collection logic for Linux
---
agent/wifi/wifi_linux.go | 111 ++++++++++++++++++++++++++++++++++++---
1 file changed, 105 insertions(+), 6 deletions(-)
agent/wifi/wifi_linux.go | 164 ++++++++++++++++++++++++++++++++++++---
1 file changed, 152 insertions(+), 12 deletions(-)
diff --git a/agent/wifi/wifi_linux.go b/agent/wifi/wifi_linux.go
index 926d658fe..ea42b1f2b 100644
index 926d658fef..1ba134e69c 100644
--- a/agent/wifi/wifi_linux.go
+++ b/agent/wifi/wifi_linux.go
@@ -5,8 +5,12 @@ package wifi
@@ -24,36 +24,38 @@ index 926d658fe..ea42b1f2b 100644
"time"
"github.com/henrygd/beszel/internal/entities/system"
@@ -99,15 +103,110 @@ func hasWirelessDevice(dir string) bool {
@@ -99,36 +103,172 @@ func hasWirelessDevice(dir string) bool {
}
func collect(ctx context.Context) map[string]system.WiFi {
- if !hasWirelessDevice(wiphyClassDir) {
- return nil
+ results := make(map[string]system.WiFi)
+
+ var client linuxClient
+ if hasWirelessDevice(wiphyClassDir) {
+ if client, err := newNL80211Client(); err == nil {
+ for k, v := range collectLinux(ctx, client) {
+ results[k] = v
+ }
+ client.Close()
+ if c, err := newNL80211Client(); err == nil {
+ client = c
+ defer client.Close()
+ }
}
- client, err := newNL80211Client()
- if err != nil {
+ }
+ return collectLinuxWithAP(ctx, client, runIwinfo)
+}
+
+ if _, err := exec.LookPath("iwinfo"); err == nil {
+ for k, v := range collectOpenWrtAP(ctx) {
+ results[k] = v
+ }
+type iwinfoCommand func(context.Context, ...string) ([]byte, error)
+
+func runIwinfo(ctx context.Context, args ...string) ([]byte, error) {
+ return exec.CommandContext(ctx, "iwinfo", args...).Output()
+}
+
+func collectLinuxWithAP(ctx context.Context, client linuxClient, iwinfo iwinfoCommand) map[string]system.WiFi {
+ results, aps := collectLinux(ctx, client)
+ for k, v := range collectOpenWrtAP(ctx, aps, iwinfo) {
+ results[k] = v
+ }
+
+ if len(results) == 0 {
return nil
}
- defer client.Close()
- return collectLinux(ctx, client)
- client, err := newNL80211Client()
- if err != nil {
+ return results
+}
+
@@ -61,7 +63,7 @@ index 926d658fe..ea42b1f2b 100644
+ iwinfoIfaceRe = regexp.MustCompile(`(?m)^(\S+)[ \t]+ESSID:`)
+ iwinfoModeRe = regexp.MustCompile(`Mode:[ \t]*Master`)
+ iwinfoSSIDRe = regexp.MustCompile(`ESSID:\s*"([^"]+)"`)
+ iwinfoAssocRe = regexp.MustCompile(`(?m)^(?:[0-9a-fA-F]{2}[:-]){5}[0-9a-fA-F]{2}.*?(-?\d+)\s+dBm`)
+ iwinfoAssocRe = regexp.MustCompile(`(?m)^(?:[0-9a-fA-F]{2}[:-]){5}[0-9a-fA-F]{2}[ \t]+(-?\d+)[ \t]+dBm`)
+)
+
+type iwinfoBlock struct {
@@ -112,25 +114,49 @@ index 926d658fe..ea42b1f2b 100644
+ return math.Round(float64(sum) / float64(count)), true
+}
+
+func collectOpenWrtAP(ctx context.Context) map[string]system.WiFi {
+// A nil aps requests discovery for drivers without a usable nl80211 inventory.
+// An empty, non-nil aps means enumeration succeeded and found no APs.
+func collectOpenWrtAP(ctx context.Context, aps []string, iwinfo iwinfoCommand) map[string]system.WiFi {
+ if ctx.Err() != nil || (aps != nil && len(aps) == 0) {
return nil
}
- defer client.Close()
- return collectLinux(ctx, client)
+ results := make(map[string]system.WiFi)
+
+ out, err := exec.CommandContext(ctx, "iwinfo").Output()
+ if err != nil && len(out) == 0 {
+ return results
+ var blocks []iwinfoBlock
+ if aps == nil {
+ out, err := iwinfo(ctx)
+ if err != nil && len(out) == 0 {
+ return results
+ }
+ blocks = splitIwinfoBlocks(string(out))
+ } else {
+ for _, name := range aps {
+ blocks = append(blocks, iwinfoBlock{name: name})
+ }
+ }
+
+ for _, b := range splitIwinfoBlocks(string(out)) {
+ for _, b := range blocks {
+ if ctx.Err() != nil {
+ return results
+ }
+ if aps != nil {
+ out, err := iwinfo(ctx, b.name, "info")
+ if err != nil {
+ continue
+ }
+ b.text = string(out)
+ }
+ ssid, isAP := parseIwinfoInfo(b.text)
+ if !isAP {
+ continue
+ }
+
+ reading := system.WiFi{SSID: validSSID(ssid)}
+ if assocOut, err := exec.CommandContext(ctx, "iwinfo", b.name, "assoclist").Output(); err == nil {
+ reading := system.WiFi{SSID: validSSID(ssid), AP: true}
+ if ctx.Err() != nil {
+ return results
+ }
+ if assocOut, err := iwinfo(ctx, b.name, "assoclist"); err == nil {
+ if avg, ok := parseAssocRSSI(string(assocOut)); ok {
+ reading.Signal = &avg
+ }
@@ -140,4 +166,52 @@ index 926d658fe..ea42b1f2b 100644
+ return results
}
func collectLinux(ctx context.Context, client linuxClient) map[string]system.WiFi {
-func collectLinux(ctx context.Context, client linuxClient) map[string]system.WiFi {
+// collectLinux returns station readings and AP names from a single interface
+// query. A nil AP list signals that iwinfo discovery may be needed.
+func collectLinux(ctx context.Context, client linuxClient) (map[string]system.WiFi, []string) {
result := make(map[string]system.WiFi)
- if ctx.Err() != nil {
- return result
+ if ctx.Err() != nil || client == nil {
+ return result, nil
}
if deadline, ok := ctx.Deadline(); ok {
if client.SetDeadline(deadline) != nil {
- return result
+ return result, nil
}
}
interfaces, err := client.Interfaces()
if err != nil {
- return result
+ return result, nil
}
+ var aps []string
for _, iface := range interfaces {
if ctx.Err() != nil {
break
}
- if iface == nil || iface.Type != native.InterfaceTypeStation || iface.Name == "" {
+ if iface == nil || iface.Name == "" {
+ continue
+ }
+ // Only an inventory with at least one named interface is usable.
+ // Empty dumps can also come from unsupported proprietary drivers.
+ if aps == nil {
+ aps = make([]string, 0)
+ }
+ if iface.Type == native.InterfaceTypeAP {
+ aps = append(aps, iface.Name)
+ }
+ if iface.Type != native.InterfaceTypeStation {
continue
}
// GET_SCAN reads the kernel's BSS cache, without triggering a scan.
@@ -151,5 +291,5 @@ func collectLinux(ctx context.Context, client linuxClient) map[string]system.WiF
}
result[iface.Name] = reading
}
- return result
+ return result, aps
}
@@ -0,0 +1,33 @@
From 79f5586adcfce5015dbce7d77eb4e7e76daed913 Mon Sep 17 00:00:00 2001
From: Jackie Han <jackie.han@gmail.com>
Date: Wed, 21 Oct 2026 23:01:05 +0800
Subject: [PATCH] Enhance WiFi struct documentation
Updated WiFi struct documentation to clarify its purpose and behavior regarding access points and associated clients.
---
internal/entities/system/system.go | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/internal/entities/system/system.go b/internal/entities/system/system.go
index b6b6168f0..b24735e83 100644
--- a/internal/entities/system/system.go
+++ b/internal/entities/system/system.go
@@ -11,12 +11,15 @@ import (
"github.com/henrygd/beszel/internal/entities/systemd"
)
-// WiFi describes a currently connected station interface. Keys in WiFi maps are
-// OS interface identities, not SSIDs. Signal is native dBm only; nil means the
-// OS confirmed association but could not supply RSSI (never convert quality %).
+// WiFi describes a currently connected station interface, or an access point
+// when AP is set. Keys in WiFi maps are OS interface identities, not SSIDs.
+// Signal is native dBm only; nil means the OS confirmed association but could
+// not supply RSSI (never convert quality %). For an AP, Signal is the average
+// RSSI of associated clients, and nil means no client reported one.
type WiFi struct {
SSID string `json:"s,omitempty" cbor:"0,keyasint,omitempty"`
Signal *float64 `json:"r,omitempty" cbor:"1,keyasint,omitempty"`
+ AP bool `json:"a,omitzero" cbor:"2,keyasint,omitempty"`
}
type Stats struct {
+2 -2
View File
@@ -5,8 +5,8 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=cloudflared-next
PKG_VERSION:=2026.10.2
PKG_RELEASE:=5
PKG_VERSION:=2026.10.3
PKG_RELEASE:=6
# Architecture mapping for pre-built binaries
ifeq ($(ARCH),x86_64)
+6 -3
View File
@@ -5,8 +5,8 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=gately
PKG_VERSION:=0.5.4
PKG_RELEASE:=4
PKG_VERSION:=0.5.5.1
PKG_RELEASE:=5
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://codeload.github.com/wangwanjie/gately/tar.gz/v$(PKG_VERSION)?
@@ -20,11 +20,14 @@ PKG_BUILD_DEPENDS:=golang/host node/host node-pnpm/host
PKG_BUILD_PARALLEL:=1
PKG_BUILD_FLAGS:=no-mips16
BUILD_DATE:=$(shell date -u -d "@$(SOURCE_DATE_EPOCH)" +"%Y-%m-%dT%H:%M:%SZ" 2>/dev/null || date -u +"%Y-%m-%dT%H:%M:%SZ")
GO_PKG:=github.com/wangwanjie/gately
GO_PKG_BUILD_PKG:=$(GO_PKG)/cmd/gately
GO_PKG_LDFLAGS_X:=\
$(GO_PKG)/internal/version.Version=v$(PKG_VERSION) \
$(GO_PKG)/internal/version.Commit=$(PKG_VERSION)
$(GO_PKG)/internal/version.Commit=$(PKG_VERSION) \
$(GO_PKG)/internal/version.BuildDate=$(BUILD_DATE)
include $(INCLUDE_DIR)/package.mk
include $(TOPDIR)/feeds/packages/lang/golang/golang-package.mk
+2 -2
View File
@@ -8,8 +8,8 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=go-ethereum
PKG_VERSION:=1.17.8
PKG_RELEASE:=12
PKG_VERSION:=1.17.9
PKG_RELEASE:=13
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://codeload.github.com/ethereum/go-ethereum/tar.gz/v${PKG_VERSION}?
+2 -2
View File
@@ -5,8 +5,8 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=gost
PKG_VERSION:=3.3.0
PKG_RELEASE:=5
PKG_VERSION:=3.3.1
PKG_RELEASE:=6
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://codeload.github.com/go-gost/gost/tar.gz/v$(PKG_VERSION)?
+1 -1
View File
@@ -8,7 +8,7 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-passwall
PKG_VERSION:=26.10.16
PKG_RELEASE:=343
PKG_RELEASE:=344
PKG_PO_VERSION:=$(PKG_VERSION)
PKG_CONFIG_DEPENDS:= \
+41 -2
View File
@@ -277,6 +277,16 @@ function md5_string(str)
return md5
end
-- 校验文件 SHA256
function verify_sha256(file, digest)
if type(digest) ~= "string" then return false end
local expected = digest:match("^sha256:(%x+)$")
if not expected or #expected ~= 64 then return false end
local code, output = exec_call("sha256sum " .. util.shellquote(file))
local actual = output:match("^(%x+)%s")
return code == 0 and actual ~= nil and actual:lower() == expected:lower()
end
--提取URL中的域名和端口(no ip)
function get_domain_port_from_url(url)
local scheme, domain, port = string.match(url, "^(https?)://([%w%.%-]+):?(%d*)")
@@ -298,9 +308,14 @@ function resolve_domain(domain, dns)
address = (address or dns):gsub("^%[(.-)%]$", "%1")
port = port or "53"
local server = datatypes.ip6addr(address) and ("[" .. address .. "]") or address
local dns_servers = {server .. ":" .. port, address .. "#" .. port, "223.5.5.5"}
local version = sys.exec("LC_ALL=C busybox nslookup -v 2>&1"):match("BusyBox v(%d+%.%d+%.%d+)")
if version and compare_versions(version, "<", "1.35.0") then
dns_servers[1], dns_servers[2] = dns_servers[2], dns_servers[1]
end
local rc, result
for _, dns_server in ipairs({server .. ":" .. port, address .. "#" .. port, "223.5.5.5"}) do
rc, result = exec_call_as_gid("LC_ALL=C nslookup " .. util.shellquote(domain) .. " " .. util.shellquote(dns_server), DIRECT_GID)
for _, dns_server in ipairs(dns_servers) do
rc, result = exec_call_as_gid("LC_ALL=C busybox nslookup " .. util.shellquote(domain) .. " " .. util.shellquote(dns_server), DIRECT_GID)
local ips, seen, answer = {}, {}, false
for line in result:gmatch("[^\r\n]+") do
if line:match("^%s*Name:") then answer = true end
@@ -1212,6 +1227,17 @@ local function check_path(app_name)
}
end
local function cache_update_digests(app_name, assets)
local digests = {}
for _, asset in ipairs(assets) do
if asset.browser_download_url and type(asset.digest) == "string" then
digests[asset.browser_download_url] = asset.digest
end
end
fs.mkdirr(CACHE_PATH)
fs.writefile(CACHE_PATH .. "/update_" .. app_name .. ".json", jsonc.stringify(digests))
end
function to_check(arch, app_name)
local result = check_path(app_name)
if result.code ~= 0 then
@@ -1276,6 +1302,7 @@ function to_check(arch, app_name)
}
end
cache_update_digests(app_name, {asset})
return {
code = 0,
has_update = has_update,
@@ -1296,6 +1323,12 @@ function to_download(app_name, url, size, task_id, keep_files)
return {code = 1, error = i18n.translate("Download url is required.")}
end
local digests = jsonc.parse(fs.readfile(CACHE_PATH .. "/update_" .. app_name .. ".json") or "{}")
local digest = type(digests) == "table" and digests[url]
if type(digest) ~= "string" then
return {code = 1, error = i18n.translate("File verification failed.")}
end
if not keep_files then remove("/tmp/" .. app_name .. "_download.*") end
local tmp_file
@@ -1334,6 +1367,11 @@ function to_download(app_name, url, size, task_id, keep_files)
}
end
if not verify_sha256(tmp_file, digest) then
exec("/bin/rm", {"-f", tmp_file})
return {code = 1, error = i18n.translate("File verification failed.")}
end
return {code = 0, file = tmp_file, zip = com[app_name].zipped }
end
@@ -1541,6 +1579,7 @@ function to_check_self()
if not main or not i18n_package then
return {code = 1, error = i18n.translate("Get remote version info failed.")}
end
cache_update_digests(appname, {main, i18n_package})
return {
code = 0, has_update = has_update, local_version = local_version,
remote_version = remote_version, html_url = release.html_url,
@@ -86,7 +86,7 @@ local com = self.com
var app = btn.getAttribute('data-update-app');
var detailId = app === appname ? appname + '-check_btn' : '_' + app + '-check_btn';
var ckeckDetailElm = document.getElementById(detailId + '-detail');
if (app === appname && !checking) errorMessage = errorMessage ? updateFailedText : unknownErrorText;
if (app === appname && !checking && !errorMessage) errorMessage = unknownErrorText;
if (errorMessage && ckeckDetailElm) {
ckeckDetailElm.textContent = errorMessage
}
+3
View File
@@ -1547,6 +1547,9 @@ msgstr "请指定下载地址。"
msgid "File download failed or timed out: %s"
msgstr "文件下载失败或超时:%s"
msgid "File verification failed."
msgstr "文件校验失败"
msgid "File path required."
msgstr "请指定文件路径。"
@@ -565,31 +565,25 @@ local function fetch_geofile(geo_name, geo_type, url)
local sha_url = url:gsub((down_filename:gsub("(%W)", "%%%1")), down_filename .. ".sha256sum")
local sha_path = tmp_path .. ".sha256sum"
local function verify_sha256(sha_file)
return sys.call("sha256sum -c " .. sha_file .. " > /dev/null 2>&1") == 0
end
local digest
local sha_verify = select(1, curl(sha_url, sha_path)) == 0
if sha_verify then
local f = io.open(sha_path, "r")
if f then
local content = f:read("*l")
f:close()
if content then
content = content:gsub("(%x+)%s+.+", "%1 " .. tmp_path)
f = io.open(sha_path, "w")
if f then
f:write(content)
f:close()
end
local hash = content and content:match("^(%x+)%s")
if hash and #hash == 64 then
digest = "sha256:" .. hash
end
end
if fs.access(asset_path) then
sys.call(string.format("cp -f %s %s", asset_path, tmp_path))
if verify_sha256(sha_path) then
log(geo_type .. " 版本一致,无需更新。")
return 0
end
if not digest then
log(geo_type .. " SHA256 校验信息无效,更新失败。")
return 1
end
if fs.access(asset_path) and api.verify_sha256(asset_path, digest) then
log(geo_type .. " 版本一致,无需更新。")
return 0
end
end
@@ -605,7 +599,7 @@ local function fetch_geofile(geo_name, geo_type, url)
end
if sret_tmp == 0 then
if sha_verify then
if verify_sha256(sha_path) then
if api.verify_sha256(tmp_path, digest) then
sys.call(string.format("mkdir -p %s && mv -f %s %s", backup_path, asset_path, backup_path))
sys.call(string.format("mkdir -p %s && mv -f %s %s", asset_location, tmp_path, asset_path))
reboot = 1
+1 -1
View File
@@ -7,7 +7,7 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-passwall2
PKG_VERSION:=26.10.20
PKG_RELEASE:=148
PKG_RELEASE:=149
PKG_PO_VERSION:=$(PKG_VERSION)
PKG_CONFIG_DEPENDS:= \
+43 -2
View File
@@ -307,6 +307,16 @@ function md5_string(str)
return md5
end
-- Verify the SHA256 hash of a file.
function verify_sha256(file, digest)
if type(digest) ~= "string" then return false end
local expected = digest:match("^sha256:(%x+)$")
if not expected or #expected ~= 64 then return false end
local code, output = exec_call("sha256sum " .. util.shellquote(file))
local actual = output:match("^(%x+)%s")
return code == 0 and actual ~= nil and actual:lower() == expected:lower()
end
-- Extract the domain name and port from the URL (no IP address).
function get_domain_port_from_url(url)
local scheme, domain, port = string.match(url, "^(https?)://([%w%.%-]+):?(%d*)")
@@ -328,9 +338,14 @@ function resolve_domain(domain, dns)
address = (address or dns):gsub("^%[(.-)%]$", "%1")
port = port or "53"
local server = datatypes.ip6addr(address) and ("[" .. address .. "]") or address
local dns_servers = {server .. ":" .. port, address .. "#" .. port, "223.5.5.5"}
local version = sys.exec("LC_ALL=C busybox nslookup -v 2>&1"):match("BusyBox v(%d+%.%d+%.%d+)")
if version and compare_versions(version, "<", "1.35.0") then
dns_servers[1], dns_servers[2] = dns_servers[2], dns_servers[1]
end
local rc, result
for _, dns_server in ipairs({server .. ":" .. port, address .. "#" .. port, "223.5.5.5"}) do
rc, result = exec_call_as_gid("LC_ALL=C nslookup " .. util.shellquote(domain) .. " " .. util.shellquote(dns_server), DIRECT_GID)
for _, dns_server in ipairs(dns_servers) do
rc, result = exec_call_as_gid("LC_ALL=C busybox nslookup " .. util.shellquote(domain) .. " " .. util.shellquote(dns_server), DIRECT_GID)
local ips, seen, answer = {}, {}, false
for line in result:gmatch("[^\r\n]+") do
if line:match("^%s*Name:") then answer = true end
@@ -1224,6 +1239,17 @@ local function check_path(app_name)
}
end
local function cache_update_digests(app_name, assets)
local digests = {}
for _, asset in ipairs(assets) do
if asset.browser_download_url and type(asset.digest) == "string" then
digests[asset.browser_download_url] = asset.digest
end
end
fs.mkdirr(CACHE_PATH)
fs.writefile(CACHE_PATH .. "/update_" .. app_name .. ".json", jsonc.stringify(digests))
end
function to_check(arch, app_name)
local result = check_path(app_name)
if result.code ~= 0 then
@@ -1288,6 +1314,7 @@ function to_check(arch, app_name)
}
end
cache_update_digests(app_name, {asset})
return {
code = 0,
has_update = has_update,
@@ -1308,6 +1335,12 @@ function to_download(app_name, url, size, task_id, keep_files)
return {code = 1, error = i18n.translate("Download url is required.")}
end
local digests = jsonc.parse(fs.readfile(CACHE_PATH .. "/update_" .. app_name .. ".json") or "{}")
local digest = type(digests) == "table" and digests[url]
if type(digest) ~= "string" then
return {code = 1, error = i18n.translate("File verification failed.")}
end
if not keep_files then sys.call("/bin/rm -f /tmp/".. app_name .."_download.*") end
local tmp_file
@@ -1346,6 +1379,11 @@ function to_download(app_name, url, size, task_id, keep_files)
}
end
if not verify_sha256(tmp_file, digest) then
exec("/bin/rm", {"-f", tmp_file})
return {code = 1, error = i18n.translate("File verification failed.")}
end
return {code = 0, file = tmp_file, zip = com[app_name].zipped }
end
@@ -1586,6 +1624,9 @@ function to_check_self()
selected[#selected + 1] = found[code]
end
if not main then return {code = 1, error = i18n.translate("Get remote version info failed.")} end
local assets = {main}
for _, asset in ipairs(selected) do assets[#assets + 1] = asset end
cache_update_digests(appname, assets)
return {
code = 0, has_update = compare_versions(local_version, "<", remote_version),
local_version = local_version, remote_version = remote_version, html_url = release.html_url,
@@ -86,7 +86,7 @@ local com = self.com
var app = btn.getAttribute('data-update-app');
var detailId = app === appname ? appname + '-check_btn' : '_' + app + '-check_btn';
var ckeckDetailElm = document.getElementById(detailId + '-detail');
if (app === appname && !checking) errorMessage = errorMessage ? updateFailedText : unknownErrorText;
if (app === appname && !checking && !errorMessage) errorMessage = unknownErrorText;
if (errorMessage && ckeckDetailElm) {
ckeckDetailElm.textContent = errorMessage
}
+6
View File
@@ -1549,6 +1549,9 @@ msgstr "URL دانلود الزامی است."
msgid "File download failed or timed out: %s"
msgstr "دانلود فایل ناموفق بود یا زمان آن تمام شد: %s"
msgid "File verification failed."
msgstr "تأیید فایل ناموفق بود."
msgid "File path required."
msgstr "مسیر فایل الزامی است."
@@ -2285,6 +2288,9 @@ msgstr "شروع به‌روزرسانی قوانین..."
msgid "Download file size verification error. Original file size: %sB. Downloaded file size: %sB."
msgstr "خطای تأیید اندازه فایل دانلود شده. اندازه فایل اصلی: %sB. اندازه فایل دانلود شده: %sB."
msgid "%s SHA256 verification information is invalid. Update failed."
msgstr "اطلاعات تأیید SHA256 برای %s نامعتبر است. به‌روزرسانی ناموفق بود."
msgid "Downloaded file is empty or an error occurred while reading it."
msgstr "فایل دانلود شده خالی است یا خطایی هنگام خواندن آن رخ داده است."
+6
View File
@@ -1550,6 +1550,9 @@ msgstr "Необходимо указать URL для загрузки."
msgid "File download failed or timed out: %s"
msgstr "Ошибка загрузки файла или тайм-аут: %s"
msgid "File verification failed."
msgstr "Ошибка проверки файла."
msgid "File path required."
msgstr "Необходимо указать путь к файлу."
@@ -2286,6 +2289,9 @@ msgstr "Начало обновления правил..."
msgid "Download file size verification error. Original file size: %sB. Downloaded file size: %sB."
msgstr "Ошибка проверки размера файла. Исходный размер: %sB, загруженный: %sB."
msgid "%s SHA256 verification information is invalid. Update failed."
msgstr "Недопустимые данные проверки SHA256 для %s. Обновление не выполнено."
msgid "Downloaded file is empty or an error occurred while reading it."
msgstr "Загруженный файл пуст или произошла ошибка при чтении."
+6
View File
@@ -1541,6 +1541,9 @@ msgstr "请指定下载地址。"
msgid "File download failed or timed out: %s"
msgstr "文件下载失败或超时:%s"
msgid "File verification failed."
msgstr "文件校验失败"
msgid "File path required."
msgstr "请指定文件路径。"
@@ -2271,6 +2274,9 @@ msgstr "开始更新规则..."
msgid "Download file size verification error. Original file size: %sB. Downloaded file size: %sB."
msgstr "下载文件大小校验出错,原始文件大小 %sB,下载文件大小:%sB。"
msgid "%s SHA256 verification information is invalid. Update failed."
msgstr "%s SHA256 校验信息无效,更新失败。"
msgid "Downloaded file is empty or an error occurred while reading it."
msgstr "下载的文件为空或读取文件时发生错误。"
+6
View File
@@ -1541,6 +1541,9 @@ msgstr "請指定下載地址。"
msgid "File download failed or timed out: %s"
msgstr "文件下載失敗或超時:%s"
msgid "File verification failed."
msgstr "檔案校驗失敗"
msgid "File path required."
msgstr "請指定文件路径。"
@@ -2277,6 +2280,9 @@ msgstr "開始更新規則..."
msgid "Download file size verification error. Original file size: %sB. Downloaded file size: %sB."
msgstr "下載檔案大小校驗出錯,原始檔案大小 %sB,下載檔案大小:%sB。"
msgid "%s SHA256 verification information is invalid. Update failed."
msgstr "%s SHA256 校驗資訊無效,更新失敗。"
msgid "Downloaded file is empty or an error occurred while reading it."
msgstr "下載的文件為空或讀取文件時發生錯誤。"
@@ -116,31 +116,25 @@ local function fetch_geofile(geo_name, geo_type, url)
local sha_url = url:gsub((down_filename:gsub("(%W)", "%%%1")), down_filename .. ".sha256sum")
local sha_path = tmp_path .. ".sha256sum"
local function verify_sha256(sha_file)
return sys.call("sha256sum -c " .. sha_file .. " > /dev/null 2>&1") == 0
end
local digest
local sha_verify, _ = curl(sha_url, sha_path) == 200
if sha_verify then
local f = io.open(sha_path, "r")
if f then
local content = f:read("*l")
f:close()
if content then
content = content:gsub("(%x+)%s+.+", "%1 " .. tmp_path)
f = io.open(sha_path, "w")
if f then
f:write(content)
f:close()
end
local hash = content and content:match("^(%x+)%s")
if hash and #hash == 64 then
digest = "sha256:" .. hash
end
end
if fs.access(asset_path) then
sys.call(string.format("cp -f %s %s", asset_path, tmp_path))
if verify_sha256(sha_path) then
log(1, api.i18n.translatef("%s version is the same and does not need to be updated.", geo_type))
return 0
end
if not digest then
log(1, api.i18n.translatef("%s SHA256 verification information is invalid. Update failed.", geo_type))
return 1
end
if fs.access(asset_path) and api.verify_sha256(asset_path, digest) then
log(1, api.i18n.translatef("%s version is the same and does not need to be updated.", geo_type))
return 0
end
end
@@ -156,7 +150,7 @@ local function fetch_geofile(geo_name, geo_type, url)
end
if sret_tmp == 200 then
if sha_verify then
if verify_sha256(sha_path) then
if api.verify_sha256(tmp_path, digest) then
sys.call(string.format("mkdir -p %s && mv -f %s %s", backup_path, asset_path, backup_path))
sys.call(string.format("mkdir -p %s && mv -f %s %s", asset_location, tmp_path, asset_path))
reboot = 1
+84 -83
View File
@@ -1,64 +1,60 @@
# SPDX-License-Identifier: GPL-3.0-or-later
#
# Copyright (c) 2018-2023 Nick Peng (pymumu@gmail.com)
# Copyright (c) 2018-2026 Nick Peng (pymumu@gmail.com)
# This is free software, licensed under the GNU General Public License v3.
#
include $(TOPDIR)/rules.mk
PKG_NAME:=smartdns
PKG_VERSION:=48.4
PKG_RELEASE:=8
PKG_RELEASE:=9
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://codeload.github.com/pymumu/smartdns/tar.gz/Release$(PKG_VERSION)?
PKG_SOURCE_VERSION:=21c940edc65520849ba03544c5cf8d9cf326e680
PKG_SOURCE:=$(PKG_NAME)-$(PKG_SOURCE_VERSION).tar.gz
PKG_SOURCE_URL:=https://codeload.github.com/pymumu/smartdns/tar.gz
PKG_SOURCE_URL_FILE:=$(PKG_SOURCE_VERSION)
PKG_HASH:=skip
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-Release$(PKG_VERSION)
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_SOURCE_VERSION)
SMARTDNS_WEBUI_SOURCE_VERSION:=1c06fee693434ec7c71f06010d3f87416baba9f0
SMARTDNS_WEBUI_SOURCE:=$(PKG_NAME)-webui-$(SMARTDNS_WEBUI_SOURCE_VERSION).tar.gz
SMARTDNS_WEBUI_SOURCE_URL:=https://codeload.github.com/pymumu/smartdns-webui/tar.gz
SMARTDNS_WEBUI_SOURCE_URL_FILE:=$(SMARTDNS_WEBUI_SOURCE_VERSION)
SMARTDNS_WEBUI_HASH:=7a698dd4826750869429e83d91ce99a4e474d0809588a7f4124ef86875be9b1f
PKG_MAINTAINER:=Nick Peng <pymumu@gmail.com>
PKG_LICENSE:=GPL-3.0-or-later
PKG_LICENSE_FILES:=LICENSE
PKG_CPE_ID:=cpe:/a:pymumu:smartdns
PKG_CONFIG_DEPENDS:=CONFIG_PACKAGE_smartdns-ui
PKG_BUILD_DEPENDS:=PACKAGE_smartdns-ui:node/host PACKAGE_smartdns-ui:rust-bindgen/host
PKG_BUILD_PARALLEL:=1
RUST_PKG_FEATURES:=build-release
RUST_PKG_LOCKED:=0
# node compile is slow, so do not use it, download node manually.
# PACKAGE_smartdns-ui:node/host
PKG_BUILD_DEPENDS:=PACKAGE_smartdns-ui:rust/host
include $(INCLUDE_DIR)/package.mk
include $(TOPDIR)/feeds/packages/lang/rust/rust-package.mk
include $(INCLUDE_DIR)/package.mk
MAKE_VARS += VER=$(PKG_VERSION)
MAKE_PATH:=src
MAKE_VARS+= VER=$(PKG_VERSION) WITH_ZLIB=0
define Package/smartdns/Default
define Package/smartdns/default
SECTION:=net
CATEGORY:=Network
SUBMENU:=IP Addresses and Names
TITLE:=smartdns
URL:=https://www.github.com/pymumu/smartdns/
endef
define Package/smartdns
$(call Package/smartdns/Default)
TITLE+= server
DEPENDS:=+i386:libatomic +libopenssl
$(Package/smartdns/default)
TITLE:=smartdns server
DEPENDS:=+libpthread +libopenssl +libatomic +zlib
endef
define Package/smartdns/description
SmartDNS is a local DNS server which accepts DNS query requests from local network clients,
gets DNS query results from multiple upstream DNS servers concurrently, and returns the fastest IP to clients.
Unlike dnsmasq's all-servers, smartdns returns the fastest IP, and encrypt DNS queries with DoT or DoH.
endef
define Package/smartdns-ui
$(call Package/smartdns/Default)
TITLE+= dashboard
DEPENDS:=+smartdns $(RUST_ARCH_DEPENDS) @!i386
endef
define Package/smartdns-ui/description
A dashboard ui for smartdns server.
Unlike dnsmasq's all-servers, smartdns returns the fastest IP, and encrypt DNS queries with DoT or DoH.
endef
define Package/smartdns/conffiles
@@ -70,73 +66,78 @@ define Package/smartdns/conffiles
/etc/smartdns/domain-forwarding.list
endef
define Download/smartdns-webui
PROTO:=git
URL:=https://github.com/pymumu/smartdns-webui.git
SOURCE_DATE:=2026-07-29
SOURCE_VERSION:=1c06fee693434ec7c71f06010d3f87416baba9f0
MIRROR_HASH:=1b718d1288f6ddbdd80e3a948dda1693fd7bc8079fdb65be121f64f23ce53849
SUBDIR:=smartdns-webui-$$$$(subst -,.,$$$$(SOURCE_DATE))~$$$$(call version_abbrev,$$$$(SOURCE_VERSION))
FILE:=$$(SUBDIR).tar.zst
endef
define Build/Prepare
$(call Build/Prepare/Default)
ifneq ($(CONFIG_PACKAGE_smartdns-ui),)
$(eval $(call Download,smartdns-webui))
$(eval $(Download/smartdns-webui))
mkdir -p $(PKG_BUILD_DIR)/smartdns-webui
zstdcat $(DL_DIR)/$(FILE) | tar -C $(PKG_BUILD_DIR)/smartdns-webui $(TAR_OPTIONS) --strip-components=1
endif
endef
define Build/Compile
$(call Build/Compile/Default)
ifneq ($(CONFIG_PACKAGE_smartdns-ui),)
( \
pushd $(PKG_BUILD_DIR) ; \
pushd smartdns-webui ; \
npm install ; \
npm run build ; \
popd ; \
pushd plugin/smartdns-ui ; \
$(CARGO_PKG_CONFIG_VARS) \
MAKEFLAGS="$(PKG_JOBS)" \
WITH_ZLIB=0 \
TARGET_CFLAGS="$(filter-out -O%,$(TARGET_CFLAGS)) $(RUSTC_CFLAGS)" \
BINDGEN_EXTRA_CLANG_ARGS="--sysroot=$(TOOLCHAIN_ROOT_DIR)" \
cargo build -v --profile $(CARGO_PKG_PROFILE) \
$(if $(strip $(RUST_PKG_FEATURES)),--features "$(strip $(RUST_PKG_FEATURES))") \
$(if $(filter --jobserver%,$(PKG_JOBS)),,-j1) \
$(CARGO_PKG_ARGS) ; \
popd ; \
popd ; \
)
endif
endef
define Package/smartdns/install
$(INSTALL_DIR) $(1)/usr/sbin $(1)/etc/config $(1)/etc/init.d
$(INSTALL_DIR) $(1)/usr/sbin $(1)/etc/config $(1)/etc/init.d
$(INSTALL_DIR) $(1)/etc/smartdns $(1)/etc/smartdns/domain-set $(1)/etc/smartdns/conf.d/
$(INSTALL_DIR) $(1)/etc/smartdns/ip-set $(1)/etc/smartdns/download
$(INSTALL_BIN) $(PKG_BUILD_DIR)/src/smartdns $(1)/usr/sbin/smartdns
$(INSTALL_BIN) $(PKG_BUILD_DIR)/package/openwrt/files/etc/init.d/smartdns $(1)/etc/init.d/smartdns
$(INSTALL_CONF) $(PKG_BUILD_DIR)/package/openwrt/address.conf $(1)/etc/smartdns/address.conf
$(INSTALL_CONF) $(PKG_BUILD_DIR)/package/openwrt/blacklist-ip.conf $(1)/etc/smartdns/blacklist-ip.conf
$(INSTALL_CONF) $(PKG_BUILD_DIR)/package/openwrt/custom.conf $(1)/etc/smartdns/custom.conf
$(INSTALL_CONF) $(PKG_BUILD_DIR)/package/openwrt/domain-block.list $(1)/etc/smartdns/domain-block.list
$(INSTALL_CONF) $(PKG_BUILD_DIR)/package/openwrt/domain-forwarding.list $(1)/etc/smartdns/domain-forwarding.list
$(INSTALL_CONF) $(PKG_BUILD_DIR)/package/openwrt/files/etc/config/smartdns $(1)/etc/config/smartdns
endef
define Package/smartdns-ui
$(Package/smartdns/default)
TITLE:=smartdns dashboard
DEPENDS:=+smartdns $(RUST_ARCH_DEPENDS)
endef
define Package/smartdns-ui/description
A dashboard ui for smartdns server.
endef
define Package/smartdns-ui/conffiles
/etc/config/smartdns
endef
define Package/smartdns-ui/install
$(INSTALL_DIR) $(1)/usr/lib
$(INSTALL_DIR) $(1)/usr/share/smartdns
$(CP) $(PKG_BUILD_DIR)/plugin/smartdns-ui/target/$(RUSTC_TARGET_ARCH)/$(CARGO_PKG_PROFILE)/libsmartdns_ui.so $(1)/usr/lib/smartdns_ui.so
$(CP) $(PKG_BUILD_DIR)/smartdns-webui/out $(1)/usr/share/smartdns/wwwroot
$(INSTALL_DIR) $(1)/etc/smartdns/conf.d/
$(INSTALL_DIR) $(1)/usr/share/smartdns/wwwroot
$(INSTALL_BIN) $(PKG_BUILD_DIR)/plugin/smartdns-ui/target/smartdns_ui.so $(1)/usr/lib/smartdns_ui.so
$(CP) $(PKG_BUILD_DIR)/smartdns-webui/out/* $(1)/usr/share/smartdns/wwwroot
endef
define Build/Compile/smartdns-webui
which npm || (echo "npm not found, please install npm first" && exit 1)
npm install --prefix $(PKG_BUILD_DIR)/smartdns-webui/
npm run build --prefix $(PKG_BUILD_DIR)/smartdns-webui/
endef
define Build/Compile/smartdns-ui
cargo install --force --locked bindgen-cli
CARGO_BUILD_ARGS="$(if $(strip $(RUST_PKG_FEATURES)),--features "$(strip $(RUST_PKG_FEATURES))") --profile $(CARGO_PKG_PROFILE)"
+$(CARGO_PKG_VARS) CARGO_BUILD_ARGS="$(CARGO_BUILD_ARGS)" CC=$(TARGET_CC) \
PATH="$$(PATH):$(CARGO_HOME)/bin" \
AWS_LC_SYS_CFLAGS="-O0" \
make -C $(PKG_BUILD_DIR)/plugin/smartdns-ui
endef
define Download/smartdns-webui
FILE:=$(SMARTDNS_WEBUI_SOURCE)
URL:=$(SMARTDNS_WEBUI_SOURCE_URL)
URL_FILE:=$(SMARTDNS_WEBUI_SOURCE_URL_FILE)
HASH:=skip
endef
$(eval $(call Download,smartdns-webui))
ifdef CONFIG_PACKAGE_smartdns-ui
define Build/Prepare
$(call Build/Prepare/Default)
$(INSTALL_DIR) $(PKG_BUILD_DIR)/smartdns-webui
$(TAR) -C $(PKG_BUILD_DIR)/smartdns-webui --strip-components=1 -xf $(DL_DIR)/$(SMARTDNS_WEBUI_SOURCE)
endef
endif
define Build/Compile
$(call Build/Compile/Default,smartdns)
ifdef CONFIG_PACKAGE_smartdns-ui
$(call Build/Compile/smartdns-ui)
$(call Build/Compile/smartdns-webui)
endif
endef
$(eval $(call BuildPackage,smartdns))
$(eval $(call RustBinPackage,smartdns-ui))
$(eval $(call BuildPackage,smartdns-ui))
+2 -2
View File
@@ -1,8 +1,8 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=Xray-core
PKG_VERSION:=26.10.17
PKG_RELEASE:=26
PKG_VERSION:=26.10.21
PKG_RELEASE:=27
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://codeload.github.com/XTLS/Xray-core/tar.gz/v$(PKG_VERSION)?