From 0b87d429f843512ee401f747a621aec8ae315462 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 23 Sep 2026 11:01:39 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9B=84=20Sync=202026-09-23=2011:01:39?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- airconnect/Makefile | 2 +- geth/Makefile | 4 +- luci-app-fwlive/Makefile | 2 +- .../resources/view/status/fwlive.js | 85 ++++++++++++++++--- .../root/usr/libexec/fwlive-adaptive-cap.sh | 8 +- .../root/usr/libexec/fwlive-log-filter.sh | 6 +- .../resources/view/dashboard/css/custom.css | 10 ++- .../view/dashboard/include/30_wifi.js | 6 +- virtualdog/Makefile | 4 +- 9 files changed, 96 insertions(+), 31 deletions(-) diff --git a/airconnect/Makefile b/airconnect/Makefile index 4591ca3d4..1603d7f9c 100644 --- a/airconnect/Makefile +++ b/airconnect/Makefile @@ -7,7 +7,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=airconnect -PKG_VERSION:=1.12.1 +PKG_VERSION:=1.12.2 PKG_RELEASE=1 PKG_SOURCE:=AirConnect-$(PKG_VERSION).zip diff --git a/geth/Makefile b/geth/Makefile index fc59ba9dd..08d20b7ea 100644 --- a/geth/Makefile +++ b/geth/Makefile @@ -8,8 +8,8 @@ include $(TOPDIR)/rules.mk PKG_NAME:=go-ethereum -PKG_VERSION:=1.17.5 -PKG_RELEASE:=9 +PKG_VERSION:=1.17.6 +PKG_RELEASE:=10 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://codeload.github.com/ethereum/go-ethereum/tar.gz/v${PKG_VERSION}? diff --git a/luci-app-fwlive/Makefile b/luci-app-fwlive/Makefile index 34ac8205f..126bb4de7 100644 --- a/luci-app-fwlive/Makefile +++ b/luci-app-fwlive/Makefile @@ -12,7 +12,7 @@ LUCI_DEPENDS:=+luci-base +logd +jsonfilter LUCI_PKGARCH:=all PKG_VERSION:=0.1.45 -PKG_RELEASE:=32 +PKG_RELEASE:=33 # Reproducible build: honor SOURCE_DATE_EPOCH from the build environment (set by docker-sdk.sh / CI). ifdef SOURCE_DATE_EPOCH diff --git a/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js b/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js index aca0004d8..cee5052f4 100644 --- a/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js +++ b/luci-app-fwlive/htdocs/luci-static/resources/view/status/fwlive.js @@ -97,6 +97,17 @@ function optionNodes(pairs) { return opts; } +function isIpv4Address(addr) { + if (addr.indexOf('.') === -1) return false; + + const octets = addr.split('.'); + if (octets.length !== 4) return false; + for (let i = 0; i < octets.length; i++) { + if (!/^\d{1,3}$/.test(octets[i]) || Number(octets[i]) > 255) return false; + } + return true; +} + return view.extend({ rowLimit: constants.DEFAULT_ROW_LIMIT, fetchMode: constants.DEFAULT_FETCH_MODE, @@ -132,6 +143,7 @@ return view.extend({ summaryRowsShown: false, summaryData: null, resolveLoadShed: false, + resolveShedUntil: 0, filterInputTimer: null, messageLayout: 'wrap', /* Session-new IDs from the last applied batch; this is not buffer growth. */ @@ -209,13 +221,13 @@ return view.extend({ const entries = location.hash.substring(1).split('&'); const result = []; for (let i = 0; i < entries.length; i++) { - const kv = entries[i].split('='); - if (kv.length !== 2) continue; + const separator = entries[i].indexOf('='); + if (separator === -1) continue; let key; let val; try { - key = decodeURIComponent(kv[0]); - val = decodeURIComponent(kv[1]); + key = decodeURIComponent(entries[i].substring(0, separator)); + val = decodeURIComponent(entries[i].substring(separator + 1)); } catch (_e) { continue; } @@ -395,10 +407,22 @@ return view.extend({ return constants.DEFAULT_ROW_TINT; }, + readRowTintPalette() { + const v = storedValue('fwlive-row-tint-palette', null); + if (v === 'accessible') return 'accessible'; + if (v === 'classic') return 'classic'; + /* Migrate an enabled legacy mode into the separate palette key. */ + return this.readRowTint() === 'accessible' ? 'accessible' : 'classic'; + }, + saveRowTint() { storeValue('fwlive-row-tint', this.rowTint); }, + saveRowTintPalette() { + storeValue('fwlive-row-tint-palette', this.rowTintPalette); + }, + rowTintPaletteOptions() { return optionNodes([ ['classic', _('Classic (green/red)')], @@ -433,6 +457,7 @@ return view.extend({ commitRowTintChange() { this.saveRowTint(); + this.saveRowTintPalette(); this.tintProbeDone = false; this.applyRowTintMode(); this.updateRowTintUi(); @@ -443,7 +468,10 @@ return view.extend({ const v = ev && ev.target ? ev.target.value : 'classic'; const pal = v === 'accessible' ? 'accessible' : 'classic'; this.rowTintPalette = pal; - if (!this.rowTintEnabled()) return; + if (!this.rowTintEnabled()) { + this.saveRowTintPalette(); + return; + } this.rowTint = pal; this.commitRowTintChange(); }, @@ -545,9 +573,37 @@ return view.extend({ }, isLikelyIp(addr) { - if (!addr) return false; + if (typeof addr !== 'string' || !addr) return false; + if (isIpv4Address(addr)) return true; + if (!addr.includes(':') || !/^[\da-f:.]+$/i.test(addr) || addr.includes(':::')) + return false; - return /^[\da-fA-F:.]+$/.test(addr); + const compression = addr.indexOf('::'); + if (compression !== -1 && addr.indexOf('::', compression + 2) !== -1) return false; + /* A stray leading/trailing colon is not part of a single `::`. */ + if (addr[0] === ':' && addr[1] !== ':') return false; + if (addr[addr.length - 1] === ':' && addr[addr.length - 2] !== ':') return false; + + let groups; + let embeddedIpv4 = false; + if (addr.includes('.')) { + const lastColon = addr.lastIndexOf(':'); + if (lastColon === -1 || !isIpv4Address(addr.substring(lastColon + 1))) return false; + groups = addr.substring(0, lastColon).split(':').filter(Boolean); + embeddedIpv4 = true; + } else { + groups = addr.split(':').filter(Boolean); + } + + if ( + groups.some(function (group) { + return !/^[\da-f]{1,4}$/i.test(group); + }) + ) + return false; + + const groupCount = groups.length + (embeddedIpv4 ? 2 : 0); + return compression === -1 ? groupCount === 8 : groupCount < 8; }, activeColumns() { @@ -1537,6 +1593,7 @@ return view.extend({ } if (wasPaused && !this.tablePaused) { + this.pauseBufferLoading = false; this.fillingBuffer = false; this.followLive = true; /* Merge pause buffer with the first live poll — do not replace. */ @@ -1561,8 +1618,7 @@ return view.extend({ /* Reset flood throttle so Limit changes paint even during ping -A. */ this.ensureRenderScheduler().resetBudget(); const cancelForce = this.ensureRenderScheduler().forceNextRender(); - if (!this.tablePaused) this.renderRows(true); - else this.updateStatus(); + this.renderRows(true); const epoch = this.currentPollEpoch(); this.requestPoll() .then(() => { @@ -1831,8 +1887,7 @@ return view.extend({ this.messageLayout = next; this.saveMessageLayout(); this.updateMessageLayoutUi(); - if (this.tablePaused) this.updateStatus(); - else this.renderRows(true); + this.renderRows(true); }, renderRows(force) { @@ -2011,8 +2066,10 @@ return view.extend({ * cadence state; summary mode can therefore appear while rows are paused * and stays behind the explicit Show rows control. */ if (this.tablePaused) this.updateStatus(); - else if (this.summaryMode) this.renderSummary(); - else this.scheduleRenderRows(); + else if (this.summaryMode) { + this.renderSummary(); + this.updateStatus(); + } else this.scheduleRenderRows(); try { await this.resolveHostnamesForEntries(this.filteredRows()); @@ -2481,7 +2538,7 @@ return view.extend({ this.messageLayout = this.readMessageLayout(); this.showHostnames = this.readShowHostnames(); this.rowTint = this.readRowTint(); - this.rowTintPalette = this.rowTintEnabled() ? this.rowTint : 'classic'; + this.rowTintPalette = this.readRowTintPalette(); this.hostnameCache = new Map(); this.hostnameFailed = new Map(); this.resolveGeneration = 0; diff --git a/luci-app-fwlive/root/usr/libexec/fwlive-adaptive-cap.sh b/luci-app-fwlive/root/usr/libexec/fwlive-adaptive-cap.sh index 9622a802b..3a543adb2 100755 --- a/luci-app-fwlive/root/usr/libexec/fwlive-adaptive-cap.sh +++ b/luci-app-fwlive/root/usr/libexec/fwlive-adaptive-cap.sh @@ -209,9 +209,11 @@ fwlive_adaptive_write_state() { # Refuse to follow a symlinked state path (same discipline as logging.lock). [ -L "$FWLIVE_ADAPTIVE_STATE_FILE" ] && return 0 _tmp="${FWLIVE_ADAPTIVE_STATE_FILE}.tmp.$$" - umask 077 - printf '{"duration_ms":%s,"limit":%s,"bucket":"%s","warm_halved":%s,"shed":%s,"completed_cs":%s}\n' \ - "$_d" "$_l" "$_b" "$_w" "$_s" "$_c" >"$_tmp" 2>/dev/null || { + ( + umask 077 + printf '{"duration_ms":%s,"limit":%s,"bucket":"%s","warm_halved":%s,"shed":%s,"completed_cs":%s}\n' \ + "$_d" "$_l" "$_b" "$_w" "$_s" "$_c" >"$_tmp" 2>/dev/null + ) || { rm -f "$_tmp" return 0 } diff --git a/luci-app-fwlive/root/usr/libexec/fwlive-log-filter.sh b/luci-app-fwlive/root/usr/libexec/fwlive-log-filter.sh index aa82ca830..6e11a3f88 100755 --- a/luci-app-fwlive/root/usr/libexec/fwlive-log-filter.sh +++ b/luci-app-fwlive/root/usr/libexec/fwlive-log-filter.sh @@ -54,7 +54,11 @@ _filter_tmp=$(mktemp "$FILTER_TMP_DIR/fwlive-filter.XXXXXX") || { printf '%s' '{"log":[],"error":"filter_tempfile_failed"}' exit 1 } -trap 'rm -f "$_filter_tmp"' 0 1 2 3 15 +trap 'rm -f "$_filter_tmp"' 0 +trap 'rm -f "$_filter_tmp"; exit 129' 1 +trap 'rm -f "$_filter_tmp"; exit 130' 2 +trap 'rm -f "$_filter_tmp"; exit 131' 3 +trap 'rm -f "$_filter_tmp"; exit 143' 15 if ! jsonfilter -e '@.log[*]' >"$_filter_tmp" 2>/dev/null; then printf '%s' '{"log":[],"error":"filter_failed"}' exit 1 diff --git a/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/css/custom.css b/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/css/custom.css index d780ae310..bf60edba5 100644 --- a/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/css/custom.css +++ b/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/css/custom.css @@ -152,6 +152,8 @@ align-items: center; gap: 20px; margin-block: auto; + /* Override Footstrap's negative SVG container margins to preserve card padding. */ + margin-inline: 0; } .dashboard-donut svg { @@ -474,6 +476,10 @@ color: var(--dashboard-text-muted); } +.dashboard-client-addresses { + overflow-wrap: anywhere; +} + /* ---- Responsive ---- */ @media screen and (max-width: 760px) { @@ -506,7 +512,3 @@ --dashboard-plot-h: 140px; } } - -.dashboard-client-addresses { - overflow-wrap: anywhere; -} diff --git a/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js b/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js index b75ab8314..cd66574bd 100644 --- a/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js +++ b/luci-mod-dashboard/htdocs/luci-static/resources/view/dashboard/include/30_wifi.js @@ -250,11 +250,11 @@ return baseclass.extend({ }, clientAddresses(hint) { - const ipv4 = L.toArray(hint?.ipaddrs || hint?.ipv4); + const ipv4 = L.toArray(hint?.ipaddrs || hint?.ipv4).find(Boolean); const ipv6 = L.toArray(hint?.ip6addrs || hint?.ipv6) - .filter(address => !/^fe[89ab][0-9a-f]:/i.test(address)); + .find(address => address && !/^fe[89ab][0-9a-f]:/i.test(address)); - return Array.from(new Set(ipv4.concat(ipv6).filter(Boolean))); + return [ ipv4, ipv6 ].filter(Boolean); }, renderUpdateData(radios, networks, hosthints) { diff --git a/virtualdog/Makefile b/virtualdog/Makefile index ca59eb8f5..108cd2e9c 100644 --- a/virtualdog/Makefile +++ b/virtualdog/Makefile @@ -7,8 +7,8 @@ include $(TOPDIR)/rules.mk PKG_NAME:=virtualdog -PKG_VERSION:=0.0.4 -PKG_RELEASE:=4 +PKG_VERSION:=0.0.5 +PKG_RELEASE:=5 # Point this at the released binary tarball when you publish builds. PKG_SOURCE:=$(PKG_NAME)-binary-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://github.com/Carseason/openwrt-packages/releases/download/prebuilt/