Add coexistence checks to all enqueue methods to prevent loading both React and Grid.js assets simultaneously. Changes: - ReactAdmin.php: Only enqueue React assets when ?react=1 - Init.php: Skip Grid.js when React active on admin pages - Form.php, Coupon.php, Access.php: Restore classic assets when ?react=0 - Customer.php, Product.php, License.php: Add coexistence checks Now the toggle between Classic and React versions works correctly. Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
188 lines
6.3 KiB
JavaScript
188 lines
6.3 KiB
JavaScript
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.Netmask6Impl = void 0;
|
|
exports.ip6bigint = ip6bigint;
|
|
exports.bigint2ip6 = bigint2ip6;
|
|
const netmask4_1 = require("./netmask4");
|
|
const MAX_IPV6 = (1n << 128n) - 1n;
|
|
function ip6bigint(ip) {
|
|
// Strip zone ID (e.g. %eth0)
|
|
const zoneIdx = ip.indexOf('%');
|
|
if (zoneIdx !== -1) {
|
|
ip = ip.substring(0, zoneIdx);
|
|
}
|
|
// Handle mixed IPv4-mapped (e.g. ::ffff:192.168.1.1)
|
|
const lastColon = ip.lastIndexOf(':');
|
|
if (lastColon !== -1 && ip.indexOf('.', lastColon) !== -1) {
|
|
const ipv4Part = ip.substring(lastColon + 1);
|
|
const ipv4Long = (0, netmask4_1.ip2long)(ipv4Part);
|
|
// IPv4 part replaces last 2 groups (32 bits), expand prefix to 6 groups
|
|
const ipv6Prefix = ip.substring(0, lastColon + 1) + '0:0';
|
|
const prefixVal = parseIPv6Pure(ipv6Prefix);
|
|
return (prefixVal & ~0xffffffffn) | BigInt(ipv4Long);
|
|
}
|
|
return parseIPv6Pure(ip);
|
|
}
|
|
function parseIPv6Pure(ip) {
|
|
const doubleColonIdx = ip.indexOf('::');
|
|
let groups;
|
|
if (doubleColonIdx !== -1) {
|
|
const left = ip.substring(0, doubleColonIdx);
|
|
const right = ip.substring(doubleColonIdx + 2);
|
|
const leftGroups = left === '' ? [] : left.split(':');
|
|
const rightGroups = right === '' ? [] : right.split(':');
|
|
const missing = 8 - leftGroups.length - rightGroups.length;
|
|
if (missing < 0) {
|
|
throw new Error('Invalid IPv6: too many groups');
|
|
}
|
|
groups = [...leftGroups, ...Array(missing).fill('0'), ...rightGroups];
|
|
}
|
|
else {
|
|
groups = ip.split(':');
|
|
}
|
|
if (groups.length !== 8) {
|
|
throw new Error('Invalid IPv6: expected 8 groups, got ' + groups.length);
|
|
}
|
|
let result = 0n;
|
|
for (let i = 0; i < 8; i++) {
|
|
const g = groups[i];
|
|
if (g.length === 0 || g.length > 4) {
|
|
throw new Error('Invalid IPv6: bad group "' + g + '"');
|
|
}
|
|
const val = parseInt(g, 16);
|
|
if (isNaN(val) || val < 0 || val > 0xffff) {
|
|
throw new Error('Invalid IPv6: bad group "' + g + '"');
|
|
}
|
|
result = (result << 16n) | BigInt(val);
|
|
}
|
|
return result;
|
|
}
|
|
function bigint2ip6(n) {
|
|
if (n < 0n || n > MAX_IPV6) {
|
|
throw new Error('Invalid IPv6 address value');
|
|
}
|
|
const groups = [];
|
|
for (let i = 0; i < 8; i++) {
|
|
groups.unshift(Number(n & 0xffffn));
|
|
n >>= 16n;
|
|
}
|
|
// RFC 5952: find longest run of consecutive zero groups
|
|
let bestStart = -1;
|
|
let bestLen = 0;
|
|
let curStart = -1;
|
|
let curLen = 0;
|
|
for (let i = 0; i < 8; i++) {
|
|
if (groups[i] === 0) {
|
|
if (curStart === -1) {
|
|
curStart = i;
|
|
curLen = 1;
|
|
}
|
|
else {
|
|
curLen++;
|
|
}
|
|
}
|
|
else {
|
|
if (curLen > bestLen && curLen >= 2) {
|
|
bestStart = curStart;
|
|
bestLen = curLen;
|
|
}
|
|
curStart = -1;
|
|
curLen = 0;
|
|
}
|
|
}
|
|
if (curLen > bestLen && curLen >= 2) {
|
|
bestStart = curStart;
|
|
bestLen = curLen;
|
|
}
|
|
if (bestStart !== -1 && bestStart + bestLen === 8 && bestStart > 0) {
|
|
const before = groups.slice(0, bestStart).map(g => g.toString(16));
|
|
return before.join(':') + '::';
|
|
}
|
|
else if (bestStart === 0) {
|
|
const after = groups.slice(bestLen).map(g => g.toString(16));
|
|
return '::' + after.join(':');
|
|
}
|
|
else if (bestStart > 0) {
|
|
const before = groups.slice(0, bestStart).map(g => g.toString(16));
|
|
const after = groups.slice(bestStart + bestLen).map(g => g.toString(16));
|
|
return before.join(':') + '::' + after.join(':');
|
|
}
|
|
else {
|
|
return groups.map(g => g.toString(16)).join(':');
|
|
}
|
|
}
|
|
class Netmask6Impl {
|
|
constructor(net, mask) {
|
|
if (typeof net !== 'string') {
|
|
throw new Error("Missing `net' parameter");
|
|
}
|
|
let prefixLen = mask;
|
|
if (prefixLen === undefined || prefixLen === null) {
|
|
const slashIdx = net.indexOf('/');
|
|
if (slashIdx !== -1) {
|
|
prefixLen = parseInt(net.substring(slashIdx + 1), 10);
|
|
net = net.substring(0, slashIdx);
|
|
}
|
|
else {
|
|
prefixLen = 128;
|
|
}
|
|
}
|
|
if (isNaN(prefixLen) || prefixLen < 0 || prefixLen > 128) {
|
|
throw new Error('Invalid mask for IPv6: ' + prefixLen);
|
|
}
|
|
this.bitmask = prefixLen;
|
|
if (this.bitmask === 0) {
|
|
this.maskBigint = 0n;
|
|
}
|
|
else {
|
|
this.maskBigint = (MAX_IPV6 >> BigInt(128 - this.bitmask)) << BigInt(128 - this.bitmask);
|
|
}
|
|
try {
|
|
this.netBigint = ip6bigint(net) & this.maskBigint;
|
|
}
|
|
catch (error) {
|
|
throw new Error('Invalid IPv6 net address: ' + net);
|
|
}
|
|
this.size = Number(1n << BigInt(128 - this.bitmask));
|
|
this.base = bigint2ip6(this.netBigint);
|
|
this.mask = bigint2ip6(this.maskBigint);
|
|
this.hostmask = bigint2ip6(~this.maskBigint & MAX_IPV6);
|
|
this.first = this.base;
|
|
this.last = bigint2ip6(this.netBigint + (1n << BigInt(128 - this.bitmask)) - 1n);
|
|
this.broadcast = undefined;
|
|
}
|
|
contains(ip) {
|
|
if (typeof ip === 'string') {
|
|
if (ip.indexOf('/') > 0) {
|
|
ip = new Netmask6Impl(ip);
|
|
}
|
|
}
|
|
if (ip instanceof Netmask6Impl) {
|
|
return this.contains(ip.base) && this.contains(ip.last);
|
|
}
|
|
else {
|
|
const addr = ip6bigint(ip);
|
|
return (addr & this.maskBigint) === this.netBigint;
|
|
}
|
|
}
|
|
next(count = 1) {
|
|
const sizeBig = 1n << BigInt(128 - this.bitmask);
|
|
return new Netmask6Impl(bigint2ip6(this.netBigint + sizeBig * BigInt(count)), this.bitmask);
|
|
}
|
|
forEach(fn) {
|
|
let addr = this.netBigint;
|
|
const sizeBig = 1n << BigInt(128 - this.bitmask);
|
|
const lastAddr = this.netBigint + sizeBig - 1n;
|
|
let index = 0;
|
|
while (addr <= lastAddr) {
|
|
fn(bigint2ip6(addr), Number(addr), index);
|
|
index++;
|
|
addr++;
|
|
}
|
|
}
|
|
toString() {
|
|
return this.base + '/' + this.bitmask;
|
|
}
|
|
}
|
|
exports.Netmask6Impl = Netmask6Impl;
|