Skip to content

luci-app-adblock-fast: update to 1.2.2-r6#8353

Open
stangri wants to merge 1 commit intoopenwrt:masterfrom
stangri:master-luci-app-adblock-fast
Open

luci-app-adblock-fast: update to 1.2.2-r6#8353
stangri wants to merge 1 commit intoopenwrt:masterfrom
stangri:master-luci-app-adblock-fast

Conversation

@stangri
Copy link
Member

@stangri stangri commented Feb 24, 2026

Maintainer: me
Compile tested: x86_64, Dell EMC Edge620, OpenWrt 25.12.0-rc4
Run tested: x86_64, Dell EMC Edge620, OpenWrt 25.12.0-rc4

Description:
Update luci-app-adblock-fast from 1.2.1-r3 to 1.2.2-r6. This rewrites the rpcd backend from a 519-line shell script to a 452-line native ucode module, adds two new RPC methods for cron management, reorganizes the web UI with a dedicated scheduling tab and a collapsible service details section, moves schedule persistence from UCI to crontab, and adds the AGPL-3.0-or-later LICENSE file.


  • 8 files changed, +1,765 / -851 lines (net +914)
  • 1 commit: a18c61aluci-app-adblock-fast: update to 1.2.2-r6

  • +rpcd-mod-ucode — Native ucode rpcd module loader

  • +jsonfilter — No longer needed; ucode handles JSON natively

  • Version bumped from 1.2.1-r3 to 1.2.2-r6

  • URL updated from github.com/stangri/... to github.com/mossdef-org/...


The rpcd script moves from:

/usr/libexec/rpcd/luci.adblock-fast   (519 lines, shell)

to:

/usr/share/rpcd/ucode/luci.adblock-fast (452 lines, ucode)
Aspect Old (Shell) New (ucode)
Language POSIX /bin/sh ucode bytecode
JSON handling json_init/add/dump Native objects
UCI access config_load/get subpr cursor() API
ubus access jsonfilter pipelines connect() API
Business logic Duplicated in script Imports shared lib
Method decl case switch block Declarative schema
Performance Fork/exec per operation In-process calls

The new script imports the shared business logic module directly:

import adb from '/lib/adblock-fast/adblock-fast.uc';

Query methods (getInitStatus, getPlatformSupport, getFileUrlFilesizes, etc.) now delegate to the shared adb library rather than re-implementing the logic.

Retained (7 methods, same interface):

Method Type Purpose
getFileUrlFilesizes Query URL sizes from cfg
getInitList Query Enabled/running
getInitStatus Query Full service state
getPlatformSupport Query Resolver/tool info
setInitAction Action Start/stop/enable
getCronStatus Query Cron diagnostics
syncCron Action Update cron sched

Added (2 new methods):

Method Type Purpose
getCronEntry Query Get raw cron line
setCronEntry Action Set/replace cron line

The cron subsystem now tracks three entry states:

  • active — Enabled and scheduled
  • suspended — Disabled but recoverable
  • disabled — Fully off

getCronStatus returns new diagnostic fields:

  • cron_line_multi — Multiple entries detected
  • cron_line_parse_ok — Expression validity
  • cron_line_state — One of: active, suspended, disabled, multi, unsupported, missing
  • entry — Raw matched cron line

Bumped from 11 to 13, reflecting the new
methods and enhanced getCronStatus response shape.

Two new methods added to the rpcd ACL file
(luci-app-adblock-fast.json):

  • getCronEntry (read section)
  • setCronEntry (write section)

LuciCompat bumped from 11 to 13.

Data fetching refactored:

  • Removed separate getServiceInfo() ubus call
  • initStatus response now provides all data (package compat, errors, warnings) in one call
  • ubus object built from initData properties instead of separate service instance query

New "Service Details" section:

  • Blocking stats, DNS backend info, compressed cache status, force-DNS ports, and donation link moved from inline status text to a separate collapsible detailsDiv
  • Main status area now shows only the essential state label and cache info when stopped

Cron warning logic rewritten:

  • Warnings only displayed when service is both enabled and running
  • New warningCronEntryMismatch warning for suspended or unparseable cron entries
  • Suggests "Resync Cron" action when cronSyncNeeded is detected
  • Pre-existing checks for missing/disabled cron daemon preserved but now gated behind showCronWarnings flag

Cron sync flow rewritten:

  1. Fetches current entry via getCronEntry()
  2. Strips comment markers and suspended/disabled tags from the entry
  3. Writes cleaned entry via setCronEntry()
  4. Reloads page only on success

New exports: getCronEntry, setCronEntry

New helper: parseCronEntry(cronEntry)

  • Parses raw cron line into form field values
  • Detects schedule mode from cron pattern:
    • every_n_hours*/N * * * *
    • every_n_daysM H */N * *
    • monthlyM H D * *
    • weeklyM H * * D
    • dailyM H * * * (default)
  • Returns config object with: auto_update_enabled, auto_update_mode, auto_update_hour, auto_update_minute, auto_update_weekday, auto_update_monthday, auto_update_every_ndays, auto_update_every_nhours
  • Falls back to defaults for unparseable entries

New helper: generateCronEntry(config)

  • Inverse of parseCronEntry
  • Converts form config object back to cron syntax
  • Returns empty string when auto-update disabled
  • Output format: M H DOM * DOW /etc/init.d/adblock-fast dl # adblock-fast-auto

Data loading consolidated:

  • Removed separate getFileUrlFilesizes() and getPlatformSupport() calls
  • Now fetches getInitStatus() + getCronStatus()
  • Sizes and platform data extracted from the unified initStatus response

New "List Updates Schedule" tab:

  • All scheduling options moved from tab_advanced to dedicated tab_schedule
  • Options: auto_update_enabled, auto_update_mode, auto_update_every_ndays, auto_update_every_nhours, auto_update_weekday, auto_update_monthday, auto_update_hour, auto_update_minute
  • Each option's cfgvalue() overridden to read from parsed cron config instead of UCI
  • config_update_enabled remains on tab_advanced

Schedule persistence moved to crontab:

  • Old: scheduling fields saved to UCI config, then syncCron called after uci-applied event to generate cron entry from config
  • New: handleSave() collects form values, calls generateCronEntry(), writes directly via setCronEntry(), then removes scheduling fields from UCI before saving remaining config
  • Result: schedule lives in crontab, survives config resets

handleSaveApply simplified:

  • Old: chained handleSave → listener for uci-appliedsyncCron → page reload
  • New: handleSave()ui.changes.apply()
  • Cron already updated during save, no separate sync step needed

Instance handling fix:

  • dnsmasq_instance and smartdns_instance write overrides now wrap values in arrays
  • Ensures instances stored as UCI lists, not scalar strings

2 new strings added:

  • "List Updates Schedule" — New tab header
  • "Service Details" — New status section header

0 strings removed, 0 strings reworded.

All other changes are source line number updates
from the JavaScript refactoring. Existing
translations remain valid; translators only need
to handle the 2 new entries.


Adds the full AGPL-3.0-or-later license text
(661 lines), matching the PKG_LICENSE field
already declared in the Makefile.


  • rpcdCompat bumped from 11 to 13
  • LuciCompat bumped from 11 to 13
  • Requires rpcd-mod-ucode (replaces jsonfilter)
  • Requires companion adblock-fast package >=1.2.2 (for the shared /lib/adblock-fast/adblock-fast.uc library imported by the rpcd ucode module)
  • All existing RPC methods preserved; 2 new ones added
  • All existing UI functionality preserved; scheduling options reorganized into dedicated tab


if (system(sprintf("mv %s %s", shell_quote(tmp_file), shell_quote(cron_file))) != 0) {
system(sprintf("rm -f %s", shell_quote(tmp_file)));
return false;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

system(sprintf("rm -f %s", shell_quote(tmp_file)));
return false;
}
system(sprintf("chmod 600 %s 2>/dev/null", shell_quote(cron_file)));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


writefile(temp_file, join('\n', out_lines) + '\n');

if (system(sprintf("mv %s %s", shell_quote(temp_file), shell_quote(cron_file))) == 0) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

writefile(temp_file, join('\n', out_lines) + '\n');

if (system(sprintf("mv %s %s", shell_quote(temp_file), shell_quote(cron_file))) == 0) {
system(sprintf("chmod 600 %s 2>/dev/null", shell_quote(cron_file)));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


if (system(sprintf("mv %s %s", shell_quote(temp_file), shell_quote(cron_file))) == 0) {
system(sprintf("chmod 600 %s 2>/dev/null", shell_quote(cron_file)));
system('if [ -x /etc/init.d/cron ] && /etc/init.d/cron enabled >/dev/null 2>&1; then /etc/init.d/cron restart >/dev/null 2>&1; elif pidof crond >/dev/null 2>&1; then killall -HUP crond 2>/dev/null; fi');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

system('if [ -x /etc/init.d/cron ] && /etc/init.d/cron enabled >/dev/null 2>&1; then /etc/init.d/cron restart >/dev/null 2>&1; elif pidof crond >/dev/null 2>&1; then killall -HUP crond 2>/dev/null; fi');
return { result: true };
}
system(sprintf("rm -f %s", shell_quote(temp_file)));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let cmd;
switch (action) {
case 'enable':
cmd = sprintf("/etc/init.d/%s enable && uci set %s.config.enabled=1 && uci commit %s",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just pointing out their availability - the command chaining here seems tidy enough although it generally means a performance hit to invoke the chained external calls.

let temp_file = cron_file + '.tmp';
let found = false, written = false;

system(sprintf("mkdir -p '%s'", replace(cron_file, /\/[^\/]+$/, '')));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return false;
}
system(sprintf("chmod 600 %s 2>/dev/null", shell_quote(cron_file)));
system('[ -x /etc/init.d/cron ] && /etc/init.d/cron reload >/dev/null 2>&1');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like the cron actions can be outsourced to a function, gate them behind necessary checks like an lstat to check for the +x bit, here.

let mday = uci_ctx.get(packageName, 'config', 'auto_update_monthday') || '1';
let ndays = uci_ctx.get(packageName, 'config', 'auto_update_every_ndays') || '3';
let nhours = uci_ctx.get(packageName, 'config', 'auto_update_every_nhours') || '6';

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe just a single https://ucode.mein.io/module-uci.cursor.html#get_all and pick the various properties after.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

var sets globally so you might have variable bleed. let should be fine.

@stangri stangri force-pushed the master-luci-app-adblock-fast branch from 8abcff3 to 06bbf6b Compare February 25, 2026 01:15
@stangri
Copy link
Member Author

stangri commented Feb 25, 2026

@systemcrash appreciate the prompt review, your suggestions and linter errors will be addressed shortly.

@stangri stangri force-pushed the master-luci-app-adblock-fast branch from 06bbf6b to 7b0ee69 Compare February 25, 2026 20:03
}

function uci_has_changes(config) {
return trim(cmd_output(sprintf("uci changes '%s' 2>/dev/null", config))) != '';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Forgot to mention changes is also available in code.

@stangri stangri force-pushed the master-luci-app-adblock-fast branch from 7b0ee69 to dddffb4 Compare February 26, 2026 01:53
Update luci-app-adblock-fast from 1.2.1-r3 to 1.2.2-r6.
This rewrites the rpcd backend from a 519-line shell
script to a 452-line native ucode module, adds two new
RPC methods for cron management, reorganizes the web UI
with a dedicated scheduling tab and a collapsible service
details section, moves schedule persistence from UCI to
crontab, and adds the AGPL-3.0-or-later LICENSE file.

Signed-off-by: Stan Grishin <stangri@melmac.ca>

---

- **8 files changed**, +1,765 / -851 lines (net +914)
- **1 commit**: `a18c61a` —
  `luci-app-adblock-fast: update to 1.2.2-r6`

---

- `+rpcd-mod-ucode` — Native ucode rpcd module loader

- `+jsonfilter` — No longer needed; ucode handles
  JSON natively

- Version bumped from `1.2.1-r3` to `1.2.2-r6`
- URL updated from `github.com/stangri/...` to
  `github.com/mossdef-org/...`

---

The rpcd script moves from:
```
/usr/libexec/rpcd/luci.adblock-fast   (519 lines, shell)
```
to:
```
/usr/share/rpcd/ucode/luci.adblock-fast (452 lines, ucode)
```

| Aspect          | Old (Shell)             | New (ucode)        |
|-----------------|-------------------------|--------------------|
| Language        | POSIX `/bin/sh`         | ucode bytecode     |
| JSON handling   | `json_init/add/dump`    | Native objects     |
| UCI access      | `config_load/get` subpr | `cursor()` API     |
| ubus access     | `jsonfilter` pipelines  | `connect()` API    |
| Business logic  | Duplicated in script    | Imports shared lib |
| Method decl     | `case` switch block     | Declarative schema |
| Performance     | Fork/exec per operation | In-process calls   |

The new script imports the shared business logic module
directly:

```javascript
import adb from '/lib/adblock-fast/adblock-fast.uc';
```

Query methods (`getInitStatus`, `getPlatformSupport`,
`getFileUrlFilesizes`, etc.) now delegate to the shared
`adb` library rather than re-implementing the logic.

**Retained (7 methods, same interface):**

| Method                | Type   | Purpose            |
|-----------------------|--------|--------------------|
| `getFileUrlFilesizes` | Query  | URL sizes from cfg |
| `getInitList`         | Query  | Enabled/running    |
| `getInitStatus`       | Query  | Full service state |
| `getPlatformSupport`  | Query  | Resolver/tool info |
| `setInitAction`       | Action | Start/stop/enable  |
| `getCronStatus`       | Query  | Cron diagnostics   |
| `syncCron`            | Action | Update cron sched  |

**Added (2 new methods):**

| Method         | Type   | Purpose              |
|----------------|--------|----------------------|
| `getCronEntry` | Query  | Get raw cron line    |
| `setCronEntry` | Action | Set/replace cron line|

The cron subsystem now tracks three entry states:
- **`active`** — Enabled and scheduled
- **`suspended`** — Disabled but recoverable
- **`disabled`** — Fully off

`getCronStatus` returns new diagnostic fields:
- `cron_line_multi` — Multiple entries detected
- `cron_line_parse_ok` — Expression validity
- `cron_line_state` — One of: `active`,
  `suspended`, `disabled`, `multi`,
  `unsupported`, `missing`
- `entry` — Raw matched cron line

Bumped from **11** to **13**, reflecting the new
methods and enhanced `getCronStatus` response shape.

Two new methods added to the rpcd ACL file
(`luci-app-adblock-fast.json`):
- `getCronEntry` (read section)
- `setCronEntry` (write section)

---

**LuciCompat** bumped from `11` to `13`.

**Data fetching refactored:**
- Removed separate `getServiceInfo()` ubus call
- `initStatus` response now provides all data
  (package compat, errors, warnings) in one call
- `ubus` object built from `initData` properties
  instead of separate service instance query

**New "Service Details" section:**
- Blocking stats, DNS backend info, compressed
  cache status, force-DNS ports, and donation
  link moved from inline status text to a
  separate collapsible `detailsDiv`
- Main status area now shows only the essential
  state label and cache info when stopped

**Cron warning logic rewritten:**
- Warnings only displayed when service is both
  enabled and running
- New `warningCronEntryMismatch` warning for
  suspended or unparseable cron entries
- Suggests "Resync Cron" action when
  `cronSyncNeeded` is detected
- Pre-existing checks for missing/disabled cron
  daemon preserved but now gated behind
  `showCronWarnings` flag

**Cron sync flow rewritten:**
1. Fetches current entry via `getCronEntry()`
2. Strips comment markers and suspended/disabled
   tags from the entry
3. Writes cleaned entry via `setCronEntry()`
4. Reloads page only on success

**New exports:** `getCronEntry`, `setCronEntry`

**New helper: `parseCronEntry(cronEntry)`**
- Parses raw cron line into form field values
- Detects schedule mode from cron pattern:
  - `every_n_hours` — `*/N * * * *`
  - `every_n_days` — `M H */N * *`
  - `monthly` — `M H D * *`
  - `weekly` — `M H * * D`
  - `daily` — `M H * * *` (default)
- Returns config object with: `auto_update_enabled`,
  `auto_update_mode`, `auto_update_hour`,
  `auto_update_minute`, `auto_update_weekday`,
  `auto_update_monthday`, `auto_update_every_ndays`,
  `auto_update_every_nhours`
- Falls back to defaults for unparseable entries

**New helper: `generateCronEntry(config)`**
- Inverse of `parseCronEntry`
- Converts form config object back to cron syntax
- Returns empty string when auto-update disabled
- Output format:
  `M H DOM * DOW /etc/init.d/adblock-fast dl`
  `# adblock-fast-auto`

**Data loading consolidated:**
- Removed separate `getFileUrlFilesizes()` and
  `getPlatformSupport()` calls
- Now fetches `getInitStatus()` + `getCronStatus()`
- Sizes and platform data extracted from the
  unified `initStatus` response

**New "List Updates Schedule" tab:**
- All scheduling options moved from `tab_advanced`
  to dedicated `tab_schedule`
- Options: `auto_update_enabled`,
  `auto_update_mode`, `auto_update_every_ndays`,
  `auto_update_every_nhours`, `auto_update_weekday`,
  `auto_update_monthday`, `auto_update_hour`,
  `auto_update_minute`
- Each option's `cfgvalue()` overridden to read
  from parsed cron config instead of UCI
- `config_update_enabled` remains on `tab_advanced`

**Schedule persistence moved to crontab:**
- Old: scheduling fields saved to UCI config, then
  `syncCron` called after `uci-applied` event to
  generate cron entry from config
- New: `handleSave()` collects form values, calls
  `generateCronEntry()`, writes directly via
  `setCronEntry()`, then removes scheduling fields
  from UCI before saving remaining config
- Result: schedule lives in crontab, survives
  config resets

**`handleSaveApply` simplified:**
- Old: chained `handleSave` → listener for
  `uci-applied` → `syncCron` → page reload
- New: `handleSave()` → `ui.changes.apply()`
- Cron already updated during save, no separate
  sync step needed

**Instance handling fix:**
- `dnsmasq_instance` and `smartdns_instance` write
  overrides now wrap values in arrays
- Ensures instances stored as UCI lists, not
  scalar strings

---

**2 new strings added:**
- `"List Updates Schedule"` — New tab header
- `"Service Details"` — New status section header

**0 strings removed, 0 strings reworded.**

All other changes are source line number updates
from the JavaScript refactoring. Existing
translations remain valid; translators only need
to handle the 2 new entries.

---

Adds the full AGPL-3.0-or-later license text
(661 lines), matching the `PKG_LICENSE` field
already declared in the Makefile.

---

- `rpcdCompat` bumped from `11` to `13`
- `LuciCompat` bumped from `11` to `13`
- Requires `rpcd-mod-ucode` (replaces `jsonfilter`)
- Requires companion `adblock-fast` package >=1.2.2
  (for the shared `/lib/adblock-fast/adblock-fast.uc`
  library imported by the rpcd ucode module)
- All existing RPC methods preserved; 2 new ones
  added
- All existing UI functionality preserved;
  scheduling options reorganized into dedicated tab

Signed-off-by: Stan Grishin <stangri@melmac.ca>
@stangri stangri force-pushed the master-luci-app-adblock-fast branch from dddffb4 to 6a56df9 Compare February 26, 2026 02:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants