feat(download): switch download buttons to direct source links

The token relay still stood between the button and the file: every click
issued a short-lived token URL, so downloads never reached the real
source address directly.

- Render direct anchors (target=_blank) to the raw source URL in the
  download box and the paid card, with inline extract-code buttons
- Retire the relay: delete Content\Download plus its init wiring, header
  query-var branch and SEO noindex branch, and drop the dead
  download-request flow from cms-download.js (cashier, scan-pay and
  error views stay)
- Keep the dl_token table and the download logs page as read-only
  history; unscheduling of the orphaned cleanup cron is preserved
This commit is contained in:
2026-09-24 19:12:45 +08:00
parent bc97c4ddc3
commit ab495854d5
10 changed files with 118 additions and 841 deletions
@@ -1,120 +0,0 @@
'use strict';
const assert = require('node:assert/strict');
const fs = require('node:fs');
const path = require('node:path');
const test = require('node:test');
const root = path.resolve(__dirname, '..', '..');
const read = (file) => fs.readFileSync(path.join(root, file), 'utf8');
test('download relay configuration is pinned to built-in constants', () => {
const dl = read('src/Content/Download.php');
// The admin settings page is gone; the option must never be read again.
assert.doesNotMatch(dl, /aksrt_download_config/);
// The retired master switch is gone from the runtime.
assert.doesNotMatch(dl, /function is_enabled/);
// Single source of truth: fixed endpoint, per-token uses and TTL.
assert.match(dl, /const ENDPOINT\s*=\s*'download'/);
assert.match(dl, /const MAX_USES\s*=\s*1/);
assert.match(dl, /const TTL_MINUTES\s*=\s*10/);
// Rewrite regex and URL building share the configured alias.
assert.match(dl, /preg_quote\(\$this->config\(\)\['endpoint'\], '\/'\)/);
assert.match(dl, /home_url\('\/' \. \$config\['endpoint'\] \. '\/' \. \$token\)/);
assert.match(dl, /add_action\('init', \[\$this, 'maybe_flush_rewrite'\], 99\)/);
assert.match(dl, /flush_rewrite_rules\(false\)/);
assert.match(dl, /aksrt_dl_rewrite_version/);
// TTL and per-token max uses come from the fixed configuration.
assert.match(dl, /'expires_in'\s+=> \$config\['ttl'\]/);
assert.match(dl, /'max_uses'\s+=> \(int\) \$config\['max_uses'\]/);
});
test('the retired master switch leaves no direct-download branches behind', () => {
const dl = read('src/Content/Download.php');
const box = read('templates/parts/resource-download-box.php');
const pay = read('inc/helpers/aksrt-pay.php');
// No runtime switch and no option reads remain.
assert.doesNotMatch(dl, /function is_enabled/);
assert.doesNotMatch(dl, /aksrt_download_config/);
// Direct mode was only reachable through the removed switch.
assert.doesNotMatch(box, /direct_download/);
assert.doesNotMatch(pay, /direct_download/);
// Relay buttons stay the only download path on both surfaces; the login
// anchor and the paid-card relay button keep their original markup.
assert.match(box, /data-action="<\?php echo esc_attr\(\$btn_action\); \?>/);
assert.match(box, /href="<\?php echo esc_url\(\$btn_href\); \?>/);
assert.match(pay, /data-action="aksrt-download"/);
// Dead standalone-page helper stays removed.
assert.doesNotMatch(pay, /aksrt_is_download_alone_page_enabled/);
});
test('usage is counted only after full delivery, never for probes', () => {
const dl = read('src/Content/Download.php');
// Probe detection covers HEAD requests and speculative prefetches, which
// validate availability but consume nothing.
assert.match(dl, /private function is_probe_request\(\): bool/);
assert.match(dl, /REQUEST_METHOD.*=== 'HEAD'/);
assert.match(dl, /HTTP_SEC_PURPOSE/);
assert.match(dl, /'prefetch'/);
assert.match(dl, /!\$is_probe\) \{\s*\$this->consume_token/);
// Local streaming splits headers from body and aborts stop consumption.
assert.match(dl, /private function send_download_headers\(string \$path\): void/);
assert.match(dl, /private function stream_body\(string \$path\): bool/);
assert.match(dl, /if \(connection_aborted\(\)\) \{/);
assert.match(dl, /return !connection_aborted\(\);/);
// Atomic cap so concurrent finishes can not overshoot max_uses.
assert.match(dl, /SET used_count = used_count \+ 1 WHERE token = %s AND used_count < max_uses/);
// Expired / exhausted links stay a dead end instead of re-issuing silently.
assert.match(dl, /status_header\(410\)/);
assert.match(dl, /请回到资源页重新获取/);
assert.doesNotMatch(dl, /fail_410\(\);\s*issue_token/);
});
test('expired links render a themed flat 410 page that follows the theme color', () => {
const dl = read('src/Content/Download.php');
// Full theme chrome instead of a bare wp_die page.
assert.match(dl, /private function render_expired_page\(\): void/);
assert.match(dl, /get_header\(\)/);
assert.match(dl, /get_footer\(\)/);
// wp_die remains only as the safety net when output already started.
assert.match(dl, /headers_sent\(\)/);
// Flat hero keyed to the runtime theme variables (light + html.dark).
assert.match(dl, /var\(--color-primary-soft/);
assert.match(dl, /var\(--color-primary/);
assert.match(dl, /var\(--key-color/);
assert.match(dl, /var\(--muted-4-color/);
// Theme button system and FA5 icon form only (never "fa fa-").
assert.match(dl, /class="btn-primary"/);
assert.match(dl, /class="btn-outline"/);
assert.match(dl, /fa fas fa-hourglass-end/);
assert.doesNotMatch(dl, /\bfa fa-/);
// The 410 page is a utility rewrite; the header component must never match
// a page type for it (custom rewrites retain the is_home flag).
const slider = read('inc/helpers/homepage/header-components.php');
assert.match(slider, /class_exists\('\\AKSRT\\Content\\Download'\)/);
assert.match(slider, /get_query_var\(\\AKSRT\\Content\\Download::QUERY_VAR\)/);
});
test('token generation retries on primary-key collisions', () => {
const dl = read('src/Content/Download.php');
assert.match(dl, /PRIMARY KEY\(token\) already guarantees uniqueness/);
assert.match(dl, /for \(\$attempt = 0; \$attempt < 3; \$attempt\+\+\)/);
});
@@ -0,0 +1,92 @@
'use strict';
const assert = require('node:assert/strict');
const fs = require('node:fs');
const path = require('node:path');
const test = require('node:test');
const root = path.resolve(__dirname, '..', '..');
const read = (file) => fs.readFileSync(path.join(root, file), 'utf8');
const exists = (file) => fs.existsSync(path.join(root, file));
test('the token relay is fully retired', () => {
// The relay class itself is gone.
assert.equal(exists('src/Content/Download.php'), false);
// No init wiring remains (DownloadState is a different class and stays).
assert.doesNotMatch(read('functions.php'), /Content\\Download'/);
// The orphaned cleanup cron is still unscheduled on theme switch.
assert.match(read('functions.php'), /aksrt_dl_token_cleanup/);
// Header query-var branch and SEO noindex branch are gone with the route.
assert.doesNotMatch(read('inc/helpers/homepage/header-components.php'), /aksrt_dl_token/);
assert.doesNotMatch(read('src/Core/SEOHead.php'), /render_robots/);
assert.doesNotMatch(read('src/Core/SEOHead.php'), /aksrt_dl_token/);
});
test('the download box renders direct anchors with inline extract codes', () => {
const box = read('templates/parts/resource-download-box.php');
// No relay button, captcha surface or low-credit data attributes.
assert.doesNotMatch(box, /data-action="aksrt-download"/);
assert.doesNotMatch(box, /data-captcha/);
assert.doesNotMatch(box, /data-aksrt-download-captcha/);
assert.doesNotMatch(box, /captcha_active/);
assert.doesNotMatch(box, /data-balance|data-cost/);
// Sources without a raw URL are skipped; the button is a direct anchor.
assert.match(box, /if \(\$url === ''\) \{[\s\S]*?continue;/);
assert.match(box, /\$btn_href = \$url;/);
assert.match(box, /\$btn_target = ' target="_blank"'/);
assert.match(box, /\$btn_rel = ' rel="nofollow noopener"'/);
// Extract codes surface inline next to the anchor, no popup involved.
assert.match(box, /if \(\$has_extract\) : \?>/);
assert.match(box, /data-clipboard-text="<\?php echo esc_attr\(\$extract_code\); \?>/);
// The login gate keeps its own anchor.
assert.match(box, /\$btn_href = \$login_url;/);
});
test('the paid card download actions render direct anchors', () => {
const pay = read('inc/helpers/aksrt-pay.php');
assert.doesNotMatch(pay, /data-action="aksrt-download"/);
assert.doesNotMatch(pay, /data-captcha/);
assert.doesNotMatch(pay, /data-aksrt-download-captcha/);
assert.doesNotMatch(pay, /captcha_active/);
// Direct anchor to the raw source URL, empty sources skipped.
assert.match(pay, /if \(\$url === ''\) \{[\s\S]*?continue;/);
assert.match(pay, /<a class="mr10 but ' \. esc_attr\(\$button_class\) \. '" href="' \. esc_url\(\$url\) \. '" target="_blank" rel="nofollow noopener">/);
// The extract-code badge next to the anchor stays.
assert.match(pay, /<span class="badg">' \. esc_html\(\$extract_code\)/);
});
test('cms-download.js only serves the cashier now', () => {
const js = read('assets/js/cms-download.js');
// The download request flow is gone.
assert.doesNotMatch(js, /download\/request/);
assert.doesNotMatch(js, /data-action="aksrt-download"/);
assert.doesNotMatch(js, /renderSuccess|startDownload|performDownloadRequest|requestDownload/);
assert.doesNotMatch(js, /AKSRTCaptcha/);
// Cashier, scan-pay and error views remain.
assert.match(js, /data-aksrt-pay-content/);
assert.match(js, /window\.aksrtOpenCashier = function/);
assert.match(js, /function renderCashier/);
assert.match(js, /function renderScanPay/);
assert.match(js, /function renderError/);
// The script is still enqueued for resource / paid singles.
assert.match(read('src/Core/ScriptsPart1b.php'), /'aksrt-cms-download'/);
});
test('the download logs page reports historical token records', () => {
const page = read('src/Admin/Native/PayDownloadLogs.php');
assert.match(page, /aksrt_dl_token/);
assert.match(page, /不再签发新令牌/);
});