Spaces:
Running
Running
Apps pro.js: offline Pro keys (Ed25519) + direct checkout map (Workers cap fix, 17 Oct 2026)
Browse files- billsprig/pro.js +45 -2
- fitcheck/pro.js +45 -2
- hazelsprig/pro.js +45 -2
- honeyfold/pro.js +45 -2
- hoursprig/pro.js +45 -2
- menumoor/pro.js +45 -2
- pactsprig/pro.js +45 -2
- pitchsprig/pro.js +45 -2
- platesprig/pro.js +45 -2
- profit-margin-calculator/pro.js +45 -2
- quotesprig/pro.js +45 -2
- rentsprig/pro.js +45 -2
- rotasprig/pro.js +45 -2
- salary-to-hourly-calculator/pro.js +45 -2
- sigsprig/pro.js +45 -2
- stampsprig/pro.js +75 -8
- tagwren/pro.js +45 -2
- utm-builder/pro.js +45 -2
billsprig/pro.js
CHANGED
|
@@ -15,7 +15,7 @@
|
|
| 15 |
if (!C.id) return;
|
| 16 |
var DATA = "https://data.cybermaxtools.com";
|
| 17 |
var KEY = "cmx-pro:" + C.id;
|
| 18 |
-
var SID = /^(cs_(live|test)_[A-Za-z0-9]{10,200}|[A-Z0-9]{8}-[A-Z0-9]{8}-[A-Z0-9]{8}-[A-Z0-9]{8})$/i; // Stripe order code or Gumroad licence key
|
| 19 |
var RECHECK = 3 * 864e5;
|
| 20 |
var listeners = [];
|
| 21 |
|
|
@@ -24,7 +24,30 @@
|
|
| 24 |
var mem = get();
|
| 25 |
function isPro() { return !!(mem && mem.code); }
|
| 26 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 27 |
function check(code) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 28 |
return fetch(DATA + "/unlock/" + encodeURIComponent(C.id) + "?json=1&session_id=" + encodeURIComponent(code))
|
| 29 |
.then(function (r) { return r.json(); })
|
| 30 |
.then(function (j) { return j && typeof j.pro === "boolean" ? j.pro : null; })
|
|
@@ -154,7 +177,7 @@
|
|
| 154 |
|
| 155 |
window.CMXPro = { isPro: isPro, onChange: function (fn) { listeners.push(fn); fn(isPro()); }, upsell: upsell, quota: quota, download: download, toast: toast };
|
| 156 |
|
| 157 |
-
var m = /[#&]cmx-pro=([^&]+)/.exec(location.hash || "");
|
| 158 |
function start() {
|
| 159 |
if (m && SID.test(decodeURIComponent(m[1]))) {
|
| 160 |
var code = decodeURIComponent(m[1]);
|
|
@@ -164,3 +187,23 @@
|
|
| 164 |
}
|
| 165 |
if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", start); else start();
|
| 166 |
})();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 15 |
if (!C.id) return;
|
| 16 |
var DATA = "https://data.cybermaxtools.com";
|
| 17 |
var KEY = "cmx-pro:" + C.id;
|
| 18 |
+
var SID = /^(cmxk1\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+|cs_(live|test)_[A-Za-z0-9]{10,200}|[A-Z0-9]{8}-[A-Z0-9]{8}-[A-Z0-9]{8}-[A-Z0-9]{8})$/i; // Stripe order code or Gumroad licence key
|
| 19 |
var RECHECK = 3 * 864e5;
|
| 20 |
var listeners = [];
|
| 21 |
|
|
|
|
| 24 |
var mem = get();
|
| 25 |
function isPro() { return !!(mem && mem.code); }
|
| 26 |
|
| 27 |
+
// Offline Pro keys (17 Oct 2026): "cmxk1.<payload>.<Ed25519 signature>" from data.cybermaxtools.com/unlock is verified
|
| 28 |
+
// here with WebCrypto and the public key below, so unlocking needs no Worker call. Expired, foreign-signed or unverifiable
|
| 29 |
+
// (no Ed25519 in this browser) keys fall back to the online check of the order code inside them, as before.
|
| 30 |
+
var CMX_PUB = "u0FDxbu0d9B9Sz5-yLT6AuL5IagyTlFcbBgEDqZxWtk";
|
| 31 |
+
function b64d(s) { s = s.replace(/-/g, "+").replace(/_/g, "/"); while (s.length % 4) s += "="; var b = atob(s), u = new Uint8Array(b.length); for (var i = 0; i < b.length; i++) u[i] = b.charCodeAt(i); return u; }
|
| 32 |
+
function cmxVerify(k) {
|
| 33 |
+
var parts = k.split("."), p = null;
|
| 34 |
+
try { p = JSON.parse(new TextDecoder().decode(b64d(parts[1]))); } catch (e) { return Promise.resolve({ p: null, ok: false }); }
|
| 35 |
+
if (!(window.crypto && crypto.subtle)) return Promise.resolve({ p: p, ok: null });
|
| 36 |
+
return crypto.subtle.importKey("raw", b64d(CMX_PUB), { name: "Ed25519" }, false, ["verify"])
|
| 37 |
+
.then(function (key) { return crypto.subtle.verify({ name: "Ed25519" }, key, b64d(parts[2]), new TextEncoder().encode(parts[0] + "." + parts[1])); })
|
| 38 |
+
.then(function (ok) { return { p: p, ok: !!ok }; }, function () { return { p: p, ok: null }; });
|
| 39 |
+
}
|
| 40 |
function check(code) {
|
| 41 |
+
if (!/^cmxk1\./.test(code)) return checkOnline(code);
|
| 42 |
+
return cmxVerify(code).then(function (r) {
|
| 43 |
+
var p = r.p;
|
| 44 |
+
if (!p || p.a !== C.id) return false;
|
| 45 |
+
if (r.ok && (!p.x || p.x * 1000 > Date.now())) return true;
|
| 46 |
+
return p.c ? checkOnline(p.c) : false;
|
| 47 |
+
});
|
| 48 |
+
}
|
| 49 |
+
|
| 50 |
+
function checkOnline(code) {
|
| 51 |
return fetch(DATA + "/unlock/" + encodeURIComponent(C.id) + "?json=1&session_id=" + encodeURIComponent(code))
|
| 52 |
.then(function (r) { return r.json(); })
|
| 53 |
.then(function (j) { return j && typeof j.pro === "boolean" ? j.pro : null; })
|
|
|
|
| 177 |
|
| 178 |
window.CMXPro = { isPro: isPro, onChange: function (fn) { listeners.push(fn); fn(isPro()); }, upsell: upsell, quota: quota, download: download, toast: toast };
|
| 179 |
|
| 180 |
+
var m = /[#&]cmx-key=([^&]+)/.exec(location.hash || "") || /[#&]cmx-pro=([^&]+)/.exec(location.hash || "");
|
| 181 |
function start() {
|
| 182 |
if (m && SID.test(decodeURIComponent(m[1]))) {
|
| 183 |
var code = decodeURIComponent(m[1]);
|
|
|
|
| 187 |
}
|
| 188 |
if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", start); else start();
|
| 189 |
})();
|
| 190 |
+
|
| 191 |
+
/* Direct checkout (17 Oct 2026, Workers cap fix): a click on a data.cybermaxtools.com/buy/<offer> link goes straight to
|
| 192 |
+
the Stripe/Polar checkout (map: https://cybermaxtools.com/store/buy-direct.json, a static file) and the click is counted
|
| 193 |
+
by a background beacon. Without the map the link works as before. */
|
| 194 |
+
(function () {
|
| 195 |
+
var MAP = null, U = "https://cybermaxtools.com/store/buy-direct.json";
|
| 196 |
+
try { MAP = JSON.parse(sessionStorage.getItem("cmx-bd") || "null"); } catch (e) { /* none */ }
|
| 197 |
+
if (!MAP && window.fetch) fetch(U).then(function (r) { return r.json(); }).then(function (j) { MAP = j; try { sessionStorage.setItem("cmx-bd", JSON.stringify(j)); } catch (e) { /* full */ } }).catch(function () {});
|
| 198 |
+
document.addEventListener("click", function (e) {
|
| 199 |
+
var a = e.target && e.target.closest && e.target.closest('a[href*="data.cybermaxtools.com/buy/"]');
|
| 200 |
+
if (!a || !MAP || !MAP.offers) return;
|
| 201 |
+
try {
|
| 202 |
+
var u = new URL(a.href), k = /^\/buy\/([a-z0-9-]+)\/?$/.exec(u.pathname), t = k && MAP.offers[k[1]];
|
| 203 |
+
if (!t) return;
|
| 204 |
+
var s = String(u.searchParams.get("s") || "unknown").toLowerCase().replace(/[^a-z0-9-]/g, "").slice(0, 80) || "unknown";
|
| 205 |
+
a.href = t.split(MAP.ph).join(s);
|
| 206 |
+
if (!navigator.webdriver) navigator.sendBeacon(u.href + (u.search ? "&" : "?") + "b=1");
|
| 207 |
+
} catch (x) { /* keep the counted link */ }
|
| 208 |
+
}, true);
|
| 209 |
+
})();
|
fitcheck/pro.js
CHANGED
|
@@ -11,7 +11,7 @@
|
|
| 11 |
if (!C.id) return;
|
| 12 |
var DATA = "https://data.cybermaxtools.com";
|
| 13 |
var KEY = "cmx-pro:" + C.id;
|
| 14 |
-
var SID = /^(cs_(live|test)_[A-Za-z0-9]{10,200}|[A-Z0-9]{8}-[A-Z0-9]{8}-[A-Z0-9]{8}-[A-Z0-9]{8})$/i; // Stripe order code or Gumroad licence key
|
| 15 |
var listeners = [];
|
| 16 |
|
| 17 |
function get() { try { return JSON.parse(localStorage.getItem(KEY) || "null"); } catch (e) { return null; } }
|
|
@@ -19,7 +19,30 @@
|
|
| 19 |
var mem = get();
|
| 20 |
function isPro() { return !!(mem && mem.code); }
|
| 21 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 22 |
function check(code) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 23 |
return fetch(DATA + "/unlock/" + encodeURIComponent(C.id) + "?json=1&session_id=" + encodeURIComponent(code))
|
| 24 |
.then(function (r) { return r.json(); }).then(function (j) { return !!(j && j.pro); }).catch(function () { return null; });
|
| 25 |
}
|
|
@@ -99,10 +122,30 @@
|
|
| 99 |
|
| 100 |
window.CMXPro = { isPro: isPro, onChange: function (fn) { listeners.push(fn); fn(isPro()); }, download: download, csv: csv, markdown: markdown, rows: rows, toast: toast };
|
| 101 |
|
| 102 |
-
var m = /[#&]cmx-pro=([^&]+)/.exec(location.hash || "");
|
| 103 |
if (m && SID.test(decodeURIComponent(m[1]))) {
|
| 104 |
var code = decodeURIComponent(m[1]);
|
| 105 |
history.replaceState(null, "", location.pathname + location.search);
|
| 106 |
if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", function () { apply(); unlock(code); }); else { apply(); unlock(code); }
|
| 107 |
} else if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", apply); else apply();
|
| 108 |
})();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 11 |
if (!C.id) return;
|
| 12 |
var DATA = "https://data.cybermaxtools.com";
|
| 13 |
var KEY = "cmx-pro:" + C.id;
|
| 14 |
+
var SID = /^(cmxk1\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+|cs_(live|test)_[A-Za-z0-9]{10,200}|[A-Z0-9]{8}-[A-Z0-9]{8}-[A-Z0-9]{8}-[A-Z0-9]{8})$/i; // Stripe order code or Gumroad licence key
|
| 15 |
var listeners = [];
|
| 16 |
|
| 17 |
function get() { try { return JSON.parse(localStorage.getItem(KEY) || "null"); } catch (e) { return null; } }
|
|
|
|
| 19 |
var mem = get();
|
| 20 |
function isPro() { return !!(mem && mem.code); }
|
| 21 |
|
| 22 |
+
// Offline Pro keys (17 Oct 2026): "cmxk1.<payload>.<Ed25519 signature>" from data.cybermaxtools.com/unlock is verified
|
| 23 |
+
// here with WebCrypto and the public key below, so unlocking needs no Worker call. Expired, foreign-signed or unverifiable
|
| 24 |
+
// (no Ed25519 in this browser) keys fall back to the online check of the order code inside them, as before.
|
| 25 |
+
var CMX_PUB = "u0FDxbu0d9B9Sz5-yLT6AuL5IagyTlFcbBgEDqZxWtk";
|
| 26 |
+
function b64d(s) { s = s.replace(/-/g, "+").replace(/_/g, "/"); while (s.length % 4) s += "="; var b = atob(s), u = new Uint8Array(b.length); for (var i = 0; i < b.length; i++) u[i] = b.charCodeAt(i); return u; }
|
| 27 |
+
function cmxVerify(k) {
|
| 28 |
+
var parts = k.split("."), p = null;
|
| 29 |
+
try { p = JSON.parse(new TextDecoder().decode(b64d(parts[1]))); } catch (e) { return Promise.resolve({ p: null, ok: false }); }
|
| 30 |
+
if (!(window.crypto && crypto.subtle)) return Promise.resolve({ p: p, ok: null });
|
| 31 |
+
return crypto.subtle.importKey("raw", b64d(CMX_PUB), { name: "Ed25519" }, false, ["verify"])
|
| 32 |
+
.then(function (key) { return crypto.subtle.verify({ name: "Ed25519" }, key, b64d(parts[2]), new TextEncoder().encode(parts[0] + "." + parts[1])); })
|
| 33 |
+
.then(function (ok) { return { p: p, ok: !!ok }; }, function () { return { p: p, ok: null }; });
|
| 34 |
+
}
|
| 35 |
function check(code) {
|
| 36 |
+
if (!/^cmxk1\./.test(code)) return checkOnline(code);
|
| 37 |
+
return cmxVerify(code).then(function (r) {
|
| 38 |
+
var p = r.p;
|
| 39 |
+
if (!p || p.a !== C.id) return false;
|
| 40 |
+
if (r.ok && (!p.x || p.x * 1000 > Date.now())) return true;
|
| 41 |
+
return p.c ? checkOnline(p.c) : false;
|
| 42 |
+
});
|
| 43 |
+
}
|
| 44 |
+
|
| 45 |
+
function checkOnline(code) {
|
| 46 |
return fetch(DATA + "/unlock/" + encodeURIComponent(C.id) + "?json=1&session_id=" + encodeURIComponent(code))
|
| 47 |
.then(function (r) { return r.json(); }).then(function (j) { return !!(j && j.pro); }).catch(function () { return null; });
|
| 48 |
}
|
|
|
|
| 122 |
|
| 123 |
window.CMXPro = { isPro: isPro, onChange: function (fn) { listeners.push(fn); fn(isPro()); }, download: download, csv: csv, markdown: markdown, rows: rows, toast: toast };
|
| 124 |
|
| 125 |
+
var m = /[#&]cmx-key=([^&]+)/.exec(location.hash || "") || /[#&]cmx-pro=([^&]+)/.exec(location.hash || "");
|
| 126 |
if (m && SID.test(decodeURIComponent(m[1]))) {
|
| 127 |
var code = decodeURIComponent(m[1]);
|
| 128 |
history.replaceState(null, "", location.pathname + location.search);
|
| 129 |
if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", function () { apply(); unlock(code); }); else { apply(); unlock(code); }
|
| 130 |
} else if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", apply); else apply();
|
| 131 |
})();
|
| 132 |
+
|
| 133 |
+
/* Direct checkout (17 Oct 2026, Workers cap fix): a click on a data.cybermaxtools.com/buy/<offer> link goes straight to
|
| 134 |
+
the Stripe/Polar checkout (map: https://cybermaxtools.com/store/buy-direct.json, a static file) and the click is counted
|
| 135 |
+
by a background beacon. Without the map the link works as before. */
|
| 136 |
+
(function () {
|
| 137 |
+
var MAP = null, U = "https://cybermaxtools.com/store/buy-direct.json";
|
| 138 |
+
try { MAP = JSON.parse(sessionStorage.getItem("cmx-bd") || "null"); } catch (e) { /* none */ }
|
| 139 |
+
if (!MAP && window.fetch) fetch(U).then(function (r) { return r.json(); }).then(function (j) { MAP = j; try { sessionStorage.setItem("cmx-bd", JSON.stringify(j)); } catch (e) { /* full */ } }).catch(function () {});
|
| 140 |
+
document.addEventListener("click", function (e) {
|
| 141 |
+
var a = e.target && e.target.closest && e.target.closest('a[href*="data.cybermaxtools.com/buy/"]');
|
| 142 |
+
if (!a || !MAP || !MAP.offers) return;
|
| 143 |
+
try {
|
| 144 |
+
var u = new URL(a.href), k = /^\/buy\/([a-z0-9-]+)\/?$/.exec(u.pathname), t = k && MAP.offers[k[1]];
|
| 145 |
+
if (!t) return;
|
| 146 |
+
var s = String(u.searchParams.get("s") || "unknown").toLowerCase().replace(/[^a-z0-9-]/g, "").slice(0, 80) || "unknown";
|
| 147 |
+
a.href = t.split(MAP.ph).join(s);
|
| 148 |
+
if (!navigator.webdriver) navigator.sendBeacon(u.href + (u.search ? "&" : "?") + "b=1");
|
| 149 |
+
} catch (x) { /* keep the counted link */ }
|
| 150 |
+
}, true);
|
| 151 |
+
})();
|
hazelsprig/pro.js
CHANGED
|
@@ -15,7 +15,7 @@
|
|
| 15 |
if (!C.id) return;
|
| 16 |
var DATA = "https://data.cybermaxtools.com";
|
| 17 |
var KEY = "cmx-pro:" + C.id;
|
| 18 |
-
var SID = /^(cs_(live|test)_[A-Za-z0-9]{10,200}|[A-Z0-9]{8}-[A-Z0-9]{8}-[A-Z0-9]{8}-[A-Z0-9]{8})$/i; // Stripe order code or Gumroad licence key
|
| 19 |
var RECHECK = 3 * 864e5;
|
| 20 |
var listeners = [];
|
| 21 |
|
|
@@ -24,7 +24,30 @@
|
|
| 24 |
var mem = get();
|
| 25 |
function isPro() { return !!(mem && mem.code); }
|
| 26 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 27 |
function check(code) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 28 |
return fetch(DATA + "/unlock/" + encodeURIComponent(C.id) + "?json=1&session_id=" + encodeURIComponent(code))
|
| 29 |
.then(function (r) { return r.json(); })
|
| 30 |
.then(function (j) { return j && typeof j.pro === "boolean" ? j.pro : null; })
|
|
@@ -152,7 +175,7 @@
|
|
| 152 |
|
| 153 |
window.CMXPro = { isPro: isPro, onChange: function (fn) { listeners.push(fn); fn(isPro()); }, upsell: upsell, quota: quota, download: download, toast: toast };
|
| 154 |
|
| 155 |
-
var m = /[#&]cmx-pro=([^&]+)/.exec(location.hash || "");
|
| 156 |
function start() {
|
| 157 |
if (m && SID.test(decodeURIComponent(m[1]))) {
|
| 158 |
var code = decodeURIComponent(m[1]);
|
|
@@ -162,3 +185,23 @@
|
|
| 162 |
}
|
| 163 |
if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", start); else start();
|
| 164 |
})();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 15 |
if (!C.id) return;
|
| 16 |
var DATA = "https://data.cybermaxtools.com";
|
| 17 |
var KEY = "cmx-pro:" + C.id;
|
| 18 |
+
var SID = /^(cmxk1\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+|cs_(live|test)_[A-Za-z0-9]{10,200}|[A-Z0-9]{8}-[A-Z0-9]{8}-[A-Z0-9]{8}-[A-Z0-9]{8})$/i; // Stripe order code or Gumroad licence key
|
| 19 |
var RECHECK = 3 * 864e5;
|
| 20 |
var listeners = [];
|
| 21 |
|
|
|
|
| 24 |
var mem = get();
|
| 25 |
function isPro() { return !!(mem && mem.code); }
|
| 26 |
|
| 27 |
+
// Offline Pro keys (17 Oct 2026): "cmxk1.<payload>.<Ed25519 signature>" from data.cybermaxtools.com/unlock is verified
|
| 28 |
+
// here with WebCrypto and the public key below, so unlocking needs no Worker call. Expired, foreign-signed or unverifiable
|
| 29 |
+
// (no Ed25519 in this browser) keys fall back to the online check of the order code inside them, as before.
|
| 30 |
+
var CMX_PUB = "u0FDxbu0d9B9Sz5-yLT6AuL5IagyTlFcbBgEDqZxWtk";
|
| 31 |
+
function b64d(s) { s = s.replace(/-/g, "+").replace(/_/g, "/"); while (s.length % 4) s += "="; var b = atob(s), u = new Uint8Array(b.length); for (var i = 0; i < b.length; i++) u[i] = b.charCodeAt(i); return u; }
|
| 32 |
+
function cmxVerify(k) {
|
| 33 |
+
var parts = k.split("."), p = null;
|
| 34 |
+
try { p = JSON.parse(new TextDecoder().decode(b64d(parts[1]))); } catch (e) { return Promise.resolve({ p: null, ok: false }); }
|
| 35 |
+
if (!(window.crypto && crypto.subtle)) return Promise.resolve({ p: p, ok: null });
|
| 36 |
+
return crypto.subtle.importKey("raw", b64d(CMX_PUB), { name: "Ed25519" }, false, ["verify"])
|
| 37 |
+
.then(function (key) { return crypto.subtle.verify({ name: "Ed25519" }, key, b64d(parts[2]), new TextEncoder().encode(parts[0] + "." + parts[1])); })
|
| 38 |
+
.then(function (ok) { return { p: p, ok: !!ok }; }, function () { return { p: p, ok: null }; });
|
| 39 |
+
}
|
| 40 |
function check(code) {
|
| 41 |
+
if (!/^cmxk1\./.test(code)) return checkOnline(code);
|
| 42 |
+
return cmxVerify(code).then(function (r) {
|
| 43 |
+
var p = r.p;
|
| 44 |
+
if (!p || p.a !== C.id) return false;
|
| 45 |
+
if (r.ok && (!p.x || p.x * 1000 > Date.now())) return true;
|
| 46 |
+
return p.c ? checkOnline(p.c) : false;
|
| 47 |
+
});
|
| 48 |
+
}
|
| 49 |
+
|
| 50 |
+
function checkOnline(code) {
|
| 51 |
return fetch(DATA + "/unlock/" + encodeURIComponent(C.id) + "?json=1&session_id=" + encodeURIComponent(code))
|
| 52 |
.then(function (r) { return r.json(); })
|
| 53 |
.then(function (j) { return j && typeof j.pro === "boolean" ? j.pro : null; })
|
|
|
|
| 175 |
|
| 176 |
window.CMXPro = { isPro: isPro, onChange: function (fn) { listeners.push(fn); fn(isPro()); }, upsell: upsell, quota: quota, download: download, toast: toast };
|
| 177 |
|
| 178 |
+
var m = /[#&]cmx-key=([^&]+)/.exec(location.hash || "") || /[#&]cmx-pro=([^&]+)/.exec(location.hash || "");
|
| 179 |
function start() {
|
| 180 |
if (m && SID.test(decodeURIComponent(m[1]))) {
|
| 181 |
var code = decodeURIComponent(m[1]);
|
|
|
|
| 185 |
}
|
| 186 |
if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", start); else start();
|
| 187 |
})();
|
| 188 |
+
|
| 189 |
+
/* Direct checkout (17 Oct 2026, Workers cap fix): a click on a data.cybermaxtools.com/buy/<offer> link goes straight to
|
| 190 |
+
the Stripe/Polar checkout (map: https://cybermaxtools.com/store/buy-direct.json, a static file) and the click is counted
|
| 191 |
+
by a background beacon. Without the map the link works as before. */
|
| 192 |
+
(function () {
|
| 193 |
+
var MAP = null, U = "https://cybermaxtools.com/store/buy-direct.json";
|
| 194 |
+
try { MAP = JSON.parse(sessionStorage.getItem("cmx-bd") || "null"); } catch (e) { /* none */ }
|
| 195 |
+
if (!MAP && window.fetch) fetch(U).then(function (r) { return r.json(); }).then(function (j) { MAP = j; try { sessionStorage.setItem("cmx-bd", JSON.stringify(j)); } catch (e) { /* full */ } }).catch(function () {});
|
| 196 |
+
document.addEventListener("click", function (e) {
|
| 197 |
+
var a = e.target && e.target.closest && e.target.closest('a[href*="data.cybermaxtools.com/buy/"]');
|
| 198 |
+
if (!a || !MAP || !MAP.offers) return;
|
| 199 |
+
try {
|
| 200 |
+
var u = new URL(a.href), k = /^\/buy\/([a-z0-9-]+)\/?$/.exec(u.pathname), t = k && MAP.offers[k[1]];
|
| 201 |
+
if (!t) return;
|
| 202 |
+
var s = String(u.searchParams.get("s") || "unknown").toLowerCase().replace(/[^a-z0-9-]/g, "").slice(0, 80) || "unknown";
|
| 203 |
+
a.href = t.split(MAP.ph).join(s);
|
| 204 |
+
if (!navigator.webdriver) navigator.sendBeacon(u.href + (u.search ? "&" : "?") + "b=1");
|
| 205 |
+
} catch (x) { /* keep the counted link */ }
|
| 206 |
+
}, true);
|
| 207 |
+
})();
|
honeyfold/pro.js
CHANGED
|
@@ -11,7 +11,7 @@
|
|
| 11 |
if (!C.id) return;
|
| 12 |
var DATA = "https://data.cybermaxtools.com";
|
| 13 |
var KEY = "cmx-pro:" + C.id;
|
| 14 |
-
var SID = /^(cs_(live|test)_[A-Za-z0-9]{10,200}|[A-Z0-9]{8}-[A-Z0-9]{8}-[A-Z0-9]{8}-[A-Z0-9]{8})$/i; // Stripe order code or Gumroad licence key
|
| 15 |
var listeners = [];
|
| 16 |
|
| 17 |
function get() { try { return JSON.parse(localStorage.getItem(KEY) || "null"); } catch (e) { return null; } }
|
|
@@ -19,7 +19,30 @@
|
|
| 19 |
var mem = get();
|
| 20 |
function isPro() { return !!(mem && mem.code); }
|
| 21 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 22 |
function check(code) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 23 |
return fetch(DATA + "/unlock/" + encodeURIComponent(C.id) + "?json=1&session_id=" + encodeURIComponent(code))
|
| 24 |
.then(function (r) { return r.json(); }).then(function (j) { return !!(j && j.pro); }).catch(function () { return null; });
|
| 25 |
}
|
|
@@ -99,10 +122,30 @@
|
|
| 99 |
|
| 100 |
window.CMXPro = { isPro: isPro, onChange: function (fn) { listeners.push(fn); fn(isPro()); }, download: download, csv: csv, markdown: markdown, rows: rows, toast: toast };
|
| 101 |
|
| 102 |
-
var m = /[#&]cmx-pro=([^&]+)/.exec(location.hash || "");
|
| 103 |
if (m && SID.test(decodeURIComponent(m[1]))) {
|
| 104 |
var code = decodeURIComponent(m[1]);
|
| 105 |
history.replaceState(null, "", location.pathname + location.search);
|
| 106 |
if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", function () { apply(); unlock(code); }); else { apply(); unlock(code); }
|
| 107 |
} else if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", apply); else apply();
|
| 108 |
})();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 11 |
if (!C.id) return;
|
| 12 |
var DATA = "https://data.cybermaxtools.com";
|
| 13 |
var KEY = "cmx-pro:" + C.id;
|
| 14 |
+
var SID = /^(cmxk1\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+|cs_(live|test)_[A-Za-z0-9]{10,200}|[A-Z0-9]{8}-[A-Z0-9]{8}-[A-Z0-9]{8}-[A-Z0-9]{8})$/i; // Stripe order code or Gumroad licence key
|
| 15 |
var listeners = [];
|
| 16 |
|
| 17 |
function get() { try { return JSON.parse(localStorage.getItem(KEY) || "null"); } catch (e) { return null; } }
|
|
|
|
| 19 |
var mem = get();
|
| 20 |
function isPro() { return !!(mem && mem.code); }
|
| 21 |
|
| 22 |
+
// Offline Pro keys (17 Oct 2026): "cmxk1.<payload>.<Ed25519 signature>" from data.cybermaxtools.com/unlock is verified
|
| 23 |
+
// here with WebCrypto and the public key below, so unlocking needs no Worker call. Expired, foreign-signed or unverifiable
|
| 24 |
+
// (no Ed25519 in this browser) keys fall back to the online check of the order code inside them, as before.
|
| 25 |
+
var CMX_PUB = "u0FDxbu0d9B9Sz5-yLT6AuL5IagyTlFcbBgEDqZxWtk";
|
| 26 |
+
function b64d(s) { s = s.replace(/-/g, "+").replace(/_/g, "/"); while (s.length % 4) s += "="; var b = atob(s), u = new Uint8Array(b.length); for (var i = 0; i < b.length; i++) u[i] = b.charCodeAt(i); return u; }
|
| 27 |
+
function cmxVerify(k) {
|
| 28 |
+
var parts = k.split("."), p = null;
|
| 29 |
+
try { p = JSON.parse(new TextDecoder().decode(b64d(parts[1]))); } catch (e) { return Promise.resolve({ p: null, ok: false }); }
|
| 30 |
+
if (!(window.crypto && crypto.subtle)) return Promise.resolve({ p: p, ok: null });
|
| 31 |
+
return crypto.subtle.importKey("raw", b64d(CMX_PUB), { name: "Ed25519" }, false, ["verify"])
|
| 32 |
+
.then(function (key) { return crypto.subtle.verify({ name: "Ed25519" }, key, b64d(parts[2]), new TextEncoder().encode(parts[0] + "." + parts[1])); })
|
| 33 |
+
.then(function (ok) { return { p: p, ok: !!ok }; }, function () { return { p: p, ok: null }; });
|
| 34 |
+
}
|
| 35 |
function check(code) {
|
| 36 |
+
if (!/^cmxk1\./.test(code)) return checkOnline(code);
|
| 37 |
+
return cmxVerify(code).then(function (r) {
|
| 38 |
+
var p = r.p;
|
| 39 |
+
if (!p || p.a !== C.id) return false;
|
| 40 |
+
if (r.ok && (!p.x || p.x * 1000 > Date.now())) return true;
|
| 41 |
+
return p.c ? checkOnline(p.c) : false;
|
| 42 |
+
});
|
| 43 |
+
}
|
| 44 |
+
|
| 45 |
+
function checkOnline(code) {
|
| 46 |
return fetch(DATA + "/unlock/" + encodeURIComponent(C.id) + "?json=1&session_id=" + encodeURIComponent(code))
|
| 47 |
.then(function (r) { return r.json(); }).then(function (j) { return !!(j && j.pro); }).catch(function () { return null; });
|
| 48 |
}
|
|
|
|
| 122 |
|
| 123 |
window.CMXPro = { isPro: isPro, onChange: function (fn) { listeners.push(fn); fn(isPro()); }, download: download, csv: csv, markdown: markdown, rows: rows, toast: toast };
|
| 124 |
|
| 125 |
+
var m = /[#&]cmx-key=([^&]+)/.exec(location.hash || "") || /[#&]cmx-pro=([^&]+)/.exec(location.hash || "");
|
| 126 |
if (m && SID.test(decodeURIComponent(m[1]))) {
|
| 127 |
var code = decodeURIComponent(m[1]);
|
| 128 |
history.replaceState(null, "", location.pathname + location.search);
|
| 129 |
if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", function () { apply(); unlock(code); }); else { apply(); unlock(code); }
|
| 130 |
} else if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", apply); else apply();
|
| 131 |
})();
|
| 132 |
+
|
| 133 |
+
/* Direct checkout (17 Oct 2026, Workers cap fix): a click on a data.cybermaxtools.com/buy/<offer> link goes straight to
|
| 134 |
+
the Stripe/Polar checkout (map: https://cybermaxtools.com/store/buy-direct.json, a static file) and the click is counted
|
| 135 |
+
by a background beacon. Without the map the link works as before. */
|
| 136 |
+
(function () {
|
| 137 |
+
var MAP = null, U = "https://cybermaxtools.com/store/buy-direct.json";
|
| 138 |
+
try { MAP = JSON.parse(sessionStorage.getItem("cmx-bd") || "null"); } catch (e) { /* none */ }
|
| 139 |
+
if (!MAP && window.fetch) fetch(U).then(function (r) { return r.json(); }).then(function (j) { MAP = j; try { sessionStorage.setItem("cmx-bd", JSON.stringify(j)); } catch (e) { /* full */ } }).catch(function () {});
|
| 140 |
+
document.addEventListener("click", function (e) {
|
| 141 |
+
var a = e.target && e.target.closest && e.target.closest('a[href*="data.cybermaxtools.com/buy/"]');
|
| 142 |
+
if (!a || !MAP || !MAP.offers) return;
|
| 143 |
+
try {
|
| 144 |
+
var u = new URL(a.href), k = /^\/buy\/([a-z0-9-]+)\/?$/.exec(u.pathname), t = k && MAP.offers[k[1]];
|
| 145 |
+
if (!t) return;
|
| 146 |
+
var s = String(u.searchParams.get("s") || "unknown").toLowerCase().replace(/[^a-z0-9-]/g, "").slice(0, 80) || "unknown";
|
| 147 |
+
a.href = t.split(MAP.ph).join(s);
|
| 148 |
+
if (!navigator.webdriver) navigator.sendBeacon(u.href + (u.search ? "&" : "?") + "b=1");
|
| 149 |
+
} catch (x) { /* keep the counted link */ }
|
| 150 |
+
}, true);
|
| 151 |
+
})();
|
hoursprig/pro.js
CHANGED
|
@@ -15,7 +15,7 @@
|
|
| 15 |
if (!C.id) return;
|
| 16 |
var DATA = "https://data.cybermaxtools.com";
|
| 17 |
var KEY = "cmx-pro:" + C.id;
|
| 18 |
-
var SID = /^(cs_(live|test)_[A-Za-z0-9]{10,200}|[A-Z0-9]{8}-[A-Z0-9]{8}-[A-Z0-9]{8}-[A-Z0-9]{8})$/i; // Stripe order code or Gumroad licence key
|
| 19 |
var RECHECK = 3 * 864e5;
|
| 20 |
var listeners = [];
|
| 21 |
|
|
@@ -24,7 +24,30 @@
|
|
| 24 |
var mem = get();
|
| 25 |
function isPro() { return !!(mem && mem.code); }
|
| 26 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 27 |
function check(code) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 28 |
return fetch(DATA + "/unlock/" + encodeURIComponent(C.id) + "?json=1&session_id=" + encodeURIComponent(code))
|
| 29 |
.then(function (r) { return r.json(); })
|
| 30 |
.then(function (j) { return j && typeof j.pro === "boolean" ? j.pro : null; })
|
|
@@ -154,7 +177,7 @@
|
|
| 154 |
|
| 155 |
window.CMXPro = { isPro: isPro, onChange: function (fn) { listeners.push(fn); fn(isPro()); }, upsell: upsell, quota: quota, download: download, toast: toast };
|
| 156 |
|
| 157 |
-
var m = /[#&]cmx-pro=([^&]+)/.exec(location.hash || "");
|
| 158 |
function start() {
|
| 159 |
if (m && SID.test(decodeURIComponent(m[1]))) {
|
| 160 |
var code = decodeURIComponent(m[1]);
|
|
@@ -164,3 +187,23 @@
|
|
| 164 |
}
|
| 165 |
if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", start); else start();
|
| 166 |
})();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 15 |
if (!C.id) return;
|
| 16 |
var DATA = "https://data.cybermaxtools.com";
|
| 17 |
var KEY = "cmx-pro:" + C.id;
|
| 18 |
+
var SID = /^(cmxk1\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+|cs_(live|test)_[A-Za-z0-9]{10,200}|[A-Z0-9]{8}-[A-Z0-9]{8}-[A-Z0-9]{8}-[A-Z0-9]{8})$/i; // Stripe order code or Gumroad licence key
|
| 19 |
var RECHECK = 3 * 864e5;
|
| 20 |
var listeners = [];
|
| 21 |
|
|
|
|
| 24 |
var mem = get();
|
| 25 |
function isPro() { return !!(mem && mem.code); }
|
| 26 |
|
| 27 |
+
// Offline Pro keys (17 Oct 2026): "cmxk1.<payload>.<Ed25519 signature>" from data.cybermaxtools.com/unlock is verified
|
| 28 |
+
// here with WebCrypto and the public key below, so unlocking needs no Worker call. Expired, foreign-signed or unverifiable
|
| 29 |
+
// (no Ed25519 in this browser) keys fall back to the online check of the order code inside them, as before.
|
| 30 |
+
var CMX_PUB = "u0FDxbu0d9B9Sz5-yLT6AuL5IagyTlFcbBgEDqZxWtk";
|
| 31 |
+
function b64d(s) { s = s.replace(/-/g, "+").replace(/_/g, "/"); while (s.length % 4) s += "="; var b = atob(s), u = new Uint8Array(b.length); for (var i = 0; i < b.length; i++) u[i] = b.charCodeAt(i); return u; }
|
| 32 |
+
function cmxVerify(k) {
|
| 33 |
+
var parts = k.split("."), p = null;
|
| 34 |
+
try { p = JSON.parse(new TextDecoder().decode(b64d(parts[1]))); } catch (e) { return Promise.resolve({ p: null, ok: false }); }
|
| 35 |
+
if (!(window.crypto && crypto.subtle)) return Promise.resolve({ p: p, ok: null });
|
| 36 |
+
return crypto.subtle.importKey("raw", b64d(CMX_PUB), { name: "Ed25519" }, false, ["verify"])
|
| 37 |
+
.then(function (key) { return crypto.subtle.verify({ name: "Ed25519" }, key, b64d(parts[2]), new TextEncoder().encode(parts[0] + "." + parts[1])); })
|
| 38 |
+
.then(function (ok) { return { p: p, ok: !!ok }; }, function () { return { p: p, ok: null }; });
|
| 39 |
+
}
|
| 40 |
function check(code) {
|
| 41 |
+
if (!/^cmxk1\./.test(code)) return checkOnline(code);
|
| 42 |
+
return cmxVerify(code).then(function (r) {
|
| 43 |
+
var p = r.p;
|
| 44 |
+
if (!p || p.a !== C.id) return false;
|
| 45 |
+
if (r.ok && (!p.x || p.x * 1000 > Date.now())) return true;
|
| 46 |
+
return p.c ? checkOnline(p.c) : false;
|
| 47 |
+
});
|
| 48 |
+
}
|
| 49 |
+
|
| 50 |
+
function checkOnline(code) {
|
| 51 |
return fetch(DATA + "/unlock/" + encodeURIComponent(C.id) + "?json=1&session_id=" + encodeURIComponent(code))
|
| 52 |
.then(function (r) { return r.json(); })
|
| 53 |
.then(function (j) { return j && typeof j.pro === "boolean" ? j.pro : null; })
|
|
|
|
| 177 |
|
| 178 |
window.CMXPro = { isPro: isPro, onChange: function (fn) { listeners.push(fn); fn(isPro()); }, upsell: upsell, quota: quota, download: download, toast: toast };
|
| 179 |
|
| 180 |
+
var m = /[#&]cmx-key=([^&]+)/.exec(location.hash || "") || /[#&]cmx-pro=([^&]+)/.exec(location.hash || "");
|
| 181 |
function start() {
|
| 182 |
if (m && SID.test(decodeURIComponent(m[1]))) {
|
| 183 |
var code = decodeURIComponent(m[1]);
|
|
|
|
| 187 |
}
|
| 188 |
if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", start); else start();
|
| 189 |
})();
|
| 190 |
+
|
| 191 |
+
/* Direct checkout (17 Oct 2026, Workers cap fix): a click on a data.cybermaxtools.com/buy/<offer> link goes straight to
|
| 192 |
+
the Stripe/Polar checkout (map: https://cybermaxtools.com/store/buy-direct.json, a static file) and the click is counted
|
| 193 |
+
by a background beacon. Without the map the link works as before. */
|
| 194 |
+
(function () {
|
| 195 |
+
var MAP = null, U = "https://cybermaxtools.com/store/buy-direct.json";
|
| 196 |
+
try { MAP = JSON.parse(sessionStorage.getItem("cmx-bd") || "null"); } catch (e) { /* none */ }
|
| 197 |
+
if (!MAP && window.fetch) fetch(U).then(function (r) { return r.json(); }).then(function (j) { MAP = j; try { sessionStorage.setItem("cmx-bd", JSON.stringify(j)); } catch (e) { /* full */ } }).catch(function () {});
|
| 198 |
+
document.addEventListener("click", function (e) {
|
| 199 |
+
var a = e.target && e.target.closest && e.target.closest('a[href*="data.cybermaxtools.com/buy/"]');
|
| 200 |
+
if (!a || !MAP || !MAP.offers) return;
|
| 201 |
+
try {
|
| 202 |
+
var u = new URL(a.href), k = /^\/buy\/([a-z0-9-]+)\/?$/.exec(u.pathname), t = k && MAP.offers[k[1]];
|
| 203 |
+
if (!t) return;
|
| 204 |
+
var s = String(u.searchParams.get("s") || "unknown").toLowerCase().replace(/[^a-z0-9-]/g, "").slice(0, 80) || "unknown";
|
| 205 |
+
a.href = t.split(MAP.ph).join(s);
|
| 206 |
+
if (!navigator.webdriver) navigator.sendBeacon(u.href + (u.search ? "&" : "?") + "b=1");
|
| 207 |
+
} catch (x) { /* keep the counted link */ }
|
| 208 |
+
}, true);
|
| 209 |
+
})();
|
menumoor/pro.js
CHANGED
|
@@ -15,7 +15,7 @@
|
|
| 15 |
if (!C.id) return;
|
| 16 |
var DATA = "https://data.cybermaxtools.com";
|
| 17 |
var KEY = "cmx-pro:" + C.id;
|
| 18 |
-
var SID = /^(cs_(live|test)_[A-Za-z0-9]{10,200}|[A-Z0-9]{8}-[A-Z0-9]{8}-[A-Z0-9]{8}-[A-Z0-9]{8})$/i; // Stripe order code or Gumroad licence key
|
| 19 |
var RECHECK = 3 * 864e5;
|
| 20 |
var listeners = [];
|
| 21 |
|
|
@@ -24,7 +24,30 @@
|
|
| 24 |
var mem = get();
|
| 25 |
function isPro() { return !!(mem && mem.code); }
|
| 26 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 27 |
function check(code) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 28 |
return fetch(DATA + "/unlock/" + encodeURIComponent(C.id) + "?json=1&session_id=" + encodeURIComponent(code))
|
| 29 |
.then(function (r) { return r.json(); })
|
| 30 |
.then(function (j) { return j && typeof j.pro === "boolean" ? j.pro : null; })
|
|
@@ -154,7 +177,7 @@
|
|
| 154 |
|
| 155 |
window.CMXPro = { isPro: isPro, onChange: function (fn) { listeners.push(fn); fn(isPro()); }, upsell: upsell, quota: quota, download: download, toast: toast };
|
| 156 |
|
| 157 |
-
var m = /[#&]cmx-pro=([^&]+)/.exec(location.hash || "");
|
| 158 |
function start() {
|
| 159 |
if (m && SID.test(decodeURIComponent(m[1]))) {
|
| 160 |
var code = decodeURIComponent(m[1]);
|
|
@@ -164,3 +187,23 @@
|
|
| 164 |
}
|
| 165 |
if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", start); else start();
|
| 166 |
})();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 15 |
if (!C.id) return;
|
| 16 |
var DATA = "https://data.cybermaxtools.com";
|
| 17 |
var KEY = "cmx-pro:" + C.id;
|
| 18 |
+
var SID = /^(cmxk1\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+|cs_(live|test)_[A-Za-z0-9]{10,200}|[A-Z0-9]{8}-[A-Z0-9]{8}-[A-Z0-9]{8}-[A-Z0-9]{8})$/i; // Stripe order code or Gumroad licence key
|
| 19 |
var RECHECK = 3 * 864e5;
|
| 20 |
var listeners = [];
|
| 21 |
|
|
|
|
| 24 |
var mem = get();
|
| 25 |
function isPro() { return !!(mem && mem.code); }
|
| 26 |
|
| 27 |
+
// Offline Pro keys (17 Oct 2026): "cmxk1.<payload>.<Ed25519 signature>" from data.cybermaxtools.com/unlock is verified
|
| 28 |
+
// here with WebCrypto and the public key below, so unlocking needs no Worker call. Expired, foreign-signed or unverifiable
|
| 29 |
+
// (no Ed25519 in this browser) keys fall back to the online check of the order code inside them, as before.
|
| 30 |
+
var CMX_PUB = "u0FDxbu0d9B9Sz5-yLT6AuL5IagyTlFcbBgEDqZxWtk";
|
| 31 |
+
function b64d(s) { s = s.replace(/-/g, "+").replace(/_/g, "/"); while (s.length % 4) s += "="; var b = atob(s), u = new Uint8Array(b.length); for (var i = 0; i < b.length; i++) u[i] = b.charCodeAt(i); return u; }
|
| 32 |
+
function cmxVerify(k) {
|
| 33 |
+
var parts = k.split("."), p = null;
|
| 34 |
+
try { p = JSON.parse(new TextDecoder().decode(b64d(parts[1]))); } catch (e) { return Promise.resolve({ p: null, ok: false }); }
|
| 35 |
+
if (!(window.crypto && crypto.subtle)) return Promise.resolve({ p: p, ok: null });
|
| 36 |
+
return crypto.subtle.importKey("raw", b64d(CMX_PUB), { name: "Ed25519" }, false, ["verify"])
|
| 37 |
+
.then(function (key) { return crypto.subtle.verify({ name: "Ed25519" }, key, b64d(parts[2]), new TextEncoder().encode(parts[0] + "." + parts[1])); })
|
| 38 |
+
.then(function (ok) { return { p: p, ok: !!ok }; }, function () { return { p: p, ok: null }; });
|
| 39 |
+
}
|
| 40 |
function check(code) {
|
| 41 |
+
if (!/^cmxk1\./.test(code)) return checkOnline(code);
|
| 42 |
+
return cmxVerify(code).then(function (r) {
|
| 43 |
+
var p = r.p;
|
| 44 |
+
if (!p || p.a !== C.id) return false;
|
| 45 |
+
if (r.ok && (!p.x || p.x * 1000 > Date.now())) return true;
|
| 46 |
+
return p.c ? checkOnline(p.c) : false;
|
| 47 |
+
});
|
| 48 |
+
}
|
| 49 |
+
|
| 50 |
+
function checkOnline(code) {
|
| 51 |
return fetch(DATA + "/unlock/" + encodeURIComponent(C.id) + "?json=1&session_id=" + encodeURIComponent(code))
|
| 52 |
.then(function (r) { return r.json(); })
|
| 53 |
.then(function (j) { return j && typeof j.pro === "boolean" ? j.pro : null; })
|
|
|
|
| 177 |
|
| 178 |
window.CMXPro = { isPro: isPro, onChange: function (fn) { listeners.push(fn); fn(isPro()); }, upsell: upsell, quota: quota, download: download, toast: toast };
|
| 179 |
|
| 180 |
+
var m = /[#&]cmx-key=([^&]+)/.exec(location.hash || "") || /[#&]cmx-pro=([^&]+)/.exec(location.hash || "");
|
| 181 |
function start() {
|
| 182 |
if (m && SID.test(decodeURIComponent(m[1]))) {
|
| 183 |
var code = decodeURIComponent(m[1]);
|
|
|
|
| 187 |
}
|
| 188 |
if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", start); else start();
|
| 189 |
})();
|
| 190 |
+
|
| 191 |
+
/* Direct checkout (17 Oct 2026, Workers cap fix): a click on a data.cybermaxtools.com/buy/<offer> link goes straight to
|
| 192 |
+
the Stripe/Polar checkout (map: https://cybermaxtools.com/store/buy-direct.json, a static file) and the click is counted
|
| 193 |
+
by a background beacon. Without the map the link works as before. */
|
| 194 |
+
(function () {
|
| 195 |
+
var MAP = null, U = "https://cybermaxtools.com/store/buy-direct.json";
|
| 196 |
+
try { MAP = JSON.parse(sessionStorage.getItem("cmx-bd") || "null"); } catch (e) { /* none */ }
|
| 197 |
+
if (!MAP && window.fetch) fetch(U).then(function (r) { return r.json(); }).then(function (j) { MAP = j; try { sessionStorage.setItem("cmx-bd", JSON.stringify(j)); } catch (e) { /* full */ } }).catch(function () {});
|
| 198 |
+
document.addEventListener("click", function (e) {
|
| 199 |
+
var a = e.target && e.target.closest && e.target.closest('a[href*="data.cybermaxtools.com/buy/"]');
|
| 200 |
+
if (!a || !MAP || !MAP.offers) return;
|
| 201 |
+
try {
|
| 202 |
+
var u = new URL(a.href), k = /^\/buy\/([a-z0-9-]+)\/?$/.exec(u.pathname), t = k && MAP.offers[k[1]];
|
| 203 |
+
if (!t) return;
|
| 204 |
+
var s = String(u.searchParams.get("s") || "unknown").toLowerCase().replace(/[^a-z0-9-]/g, "").slice(0, 80) || "unknown";
|
| 205 |
+
a.href = t.split(MAP.ph).join(s);
|
| 206 |
+
if (!navigator.webdriver) navigator.sendBeacon(u.href + (u.search ? "&" : "?") + "b=1");
|
| 207 |
+
} catch (x) { /* keep the counted link */ }
|
| 208 |
+
}, true);
|
| 209 |
+
})();
|
pactsprig/pro.js
CHANGED
|
@@ -15,7 +15,7 @@
|
|
| 15 |
if (!C.id) return;
|
| 16 |
var DATA = "https://data.cybermaxtools.com";
|
| 17 |
var KEY = "cmx-pro:" + C.id;
|
| 18 |
-
var SID = /^(cs_(live|test)_[A-Za-z0-9]{10,200}|[A-Z0-9]{8}-[A-Z0-9]{8}-[A-Z0-9]{8}-[A-Z0-9]{8})$/i; // Stripe order code or Gumroad licence key
|
| 19 |
var RECHECK = 3 * 864e5;
|
| 20 |
var listeners = [];
|
| 21 |
|
|
@@ -24,7 +24,30 @@
|
|
| 24 |
var mem = get();
|
| 25 |
function isPro() { return !!(mem && mem.code); }
|
| 26 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 27 |
function check(code) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 28 |
return fetch(DATA + "/unlock/" + encodeURIComponent(C.id) + "?json=1&session_id=" + encodeURIComponent(code))
|
| 29 |
.then(function (r) { return r.json(); })
|
| 30 |
.then(function (j) { return j && typeof j.pro === "boolean" ? j.pro : null; })
|
|
@@ -152,7 +175,7 @@
|
|
| 152 |
|
| 153 |
window.CMXPro = { isPro: isPro, onChange: function (fn) { listeners.push(fn); fn(isPro()); }, upsell: upsell, quota: quota, download: download, toast: toast };
|
| 154 |
|
| 155 |
-
var m = /[#&]cmx-pro=([^&]+)/.exec(location.hash || "");
|
| 156 |
function start() {
|
| 157 |
if (m && SID.test(decodeURIComponent(m[1]))) {
|
| 158 |
var code = decodeURIComponent(m[1]);
|
|
@@ -162,3 +185,23 @@
|
|
| 162 |
}
|
| 163 |
if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", start); else start();
|
| 164 |
})();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 15 |
if (!C.id) return;
|
| 16 |
var DATA = "https://data.cybermaxtools.com";
|
| 17 |
var KEY = "cmx-pro:" + C.id;
|
| 18 |
+
var SID = /^(cmxk1\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+|cs_(live|test)_[A-Za-z0-9]{10,200}|[A-Z0-9]{8}-[A-Z0-9]{8}-[A-Z0-9]{8}-[A-Z0-9]{8})$/i; // Stripe order code or Gumroad licence key
|
| 19 |
var RECHECK = 3 * 864e5;
|
| 20 |
var listeners = [];
|
| 21 |
|
|
|
|
| 24 |
var mem = get();
|
| 25 |
function isPro() { return !!(mem && mem.code); }
|
| 26 |
|
| 27 |
+
// Offline Pro keys (17 Oct 2026): "cmxk1.<payload>.<Ed25519 signature>" from data.cybermaxtools.com/unlock is verified
|
| 28 |
+
// here with WebCrypto and the public key below, so unlocking needs no Worker call. Expired, foreign-signed or unverifiable
|
| 29 |
+
// (no Ed25519 in this browser) keys fall back to the online check of the order code inside them, as before.
|
| 30 |
+
var CMX_PUB = "u0FDxbu0d9B9Sz5-yLT6AuL5IagyTlFcbBgEDqZxWtk";
|
| 31 |
+
function b64d(s) { s = s.replace(/-/g, "+").replace(/_/g, "/"); while (s.length % 4) s += "="; var b = atob(s), u = new Uint8Array(b.length); for (var i = 0; i < b.length; i++) u[i] = b.charCodeAt(i); return u; }
|
| 32 |
+
function cmxVerify(k) {
|
| 33 |
+
var parts = k.split("."), p = null;
|
| 34 |
+
try { p = JSON.parse(new TextDecoder().decode(b64d(parts[1]))); } catch (e) { return Promise.resolve({ p: null, ok: false }); }
|
| 35 |
+
if (!(window.crypto && crypto.subtle)) return Promise.resolve({ p: p, ok: null });
|
| 36 |
+
return crypto.subtle.importKey("raw", b64d(CMX_PUB), { name: "Ed25519" }, false, ["verify"])
|
| 37 |
+
.then(function (key) { return crypto.subtle.verify({ name: "Ed25519" }, key, b64d(parts[2]), new TextEncoder().encode(parts[0] + "." + parts[1])); })
|
| 38 |
+
.then(function (ok) { return { p: p, ok: !!ok }; }, function () { return { p: p, ok: null }; });
|
| 39 |
+
}
|
| 40 |
function check(code) {
|
| 41 |
+
if (!/^cmxk1\./.test(code)) return checkOnline(code);
|
| 42 |
+
return cmxVerify(code).then(function (r) {
|
| 43 |
+
var p = r.p;
|
| 44 |
+
if (!p || p.a !== C.id) return false;
|
| 45 |
+
if (r.ok && (!p.x || p.x * 1000 > Date.now())) return true;
|
| 46 |
+
return p.c ? checkOnline(p.c) : false;
|
| 47 |
+
});
|
| 48 |
+
}
|
| 49 |
+
|
| 50 |
+
function checkOnline(code) {
|
| 51 |
return fetch(DATA + "/unlock/" + encodeURIComponent(C.id) + "?json=1&session_id=" + encodeURIComponent(code))
|
| 52 |
.then(function (r) { return r.json(); })
|
| 53 |
.then(function (j) { return j && typeof j.pro === "boolean" ? j.pro : null; })
|
|
|
|
| 175 |
|
| 176 |
window.CMXPro = { isPro: isPro, onChange: function (fn) { listeners.push(fn); fn(isPro()); }, upsell: upsell, quota: quota, download: download, toast: toast };
|
| 177 |
|
| 178 |
+
var m = /[#&]cmx-key=([^&]+)/.exec(location.hash || "") || /[#&]cmx-pro=([^&]+)/.exec(location.hash || "");
|
| 179 |
function start() {
|
| 180 |
if (m && SID.test(decodeURIComponent(m[1]))) {
|
| 181 |
var code = decodeURIComponent(m[1]);
|
|
|
|
| 185 |
}
|
| 186 |
if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", start); else start();
|
| 187 |
})();
|
| 188 |
+
|
| 189 |
+
/* Direct checkout (17 Oct 2026, Workers cap fix): a click on a data.cybermaxtools.com/buy/<offer> link goes straight to
|
| 190 |
+
the Stripe/Polar checkout (map: https://cybermaxtools.com/store/buy-direct.json, a static file) and the click is counted
|
| 191 |
+
by a background beacon. Without the map the link works as before. */
|
| 192 |
+
(function () {
|
| 193 |
+
var MAP = null, U = "https://cybermaxtools.com/store/buy-direct.json";
|
| 194 |
+
try { MAP = JSON.parse(sessionStorage.getItem("cmx-bd") || "null"); } catch (e) { /* none */ }
|
| 195 |
+
if (!MAP && window.fetch) fetch(U).then(function (r) { return r.json(); }).then(function (j) { MAP = j; try { sessionStorage.setItem("cmx-bd", JSON.stringify(j)); } catch (e) { /* full */ } }).catch(function () {});
|
| 196 |
+
document.addEventListener("click", function (e) {
|
| 197 |
+
var a = e.target && e.target.closest && e.target.closest('a[href*="data.cybermaxtools.com/buy/"]');
|
| 198 |
+
if (!a || !MAP || !MAP.offers) return;
|
| 199 |
+
try {
|
| 200 |
+
var u = new URL(a.href), k = /^\/buy\/([a-z0-9-]+)\/?$/.exec(u.pathname), t = k && MAP.offers[k[1]];
|
| 201 |
+
if (!t) return;
|
| 202 |
+
var s = String(u.searchParams.get("s") || "unknown").toLowerCase().replace(/[^a-z0-9-]/g, "").slice(0, 80) || "unknown";
|
| 203 |
+
a.href = t.split(MAP.ph).join(s);
|
| 204 |
+
if (!navigator.webdriver) navigator.sendBeacon(u.href + (u.search ? "&" : "?") + "b=1");
|
| 205 |
+
} catch (x) { /* keep the counted link */ }
|
| 206 |
+
}, true);
|
| 207 |
+
})();
|
pitchsprig/pro.js
CHANGED
|
@@ -15,7 +15,7 @@
|
|
| 15 |
if (!C.id) return;
|
| 16 |
var DATA = "https://data.cybermaxtools.com";
|
| 17 |
var KEY = "cmx-pro:" + C.id;
|
| 18 |
-
var SID = /^(cs_(live|test)_[A-Za-z0-9]{10,200}|[A-Z0-9]{8}-[A-Z0-9]{8}-[A-Z0-9]{8}-[A-Z0-9]{8})$/i; // Stripe order code or Gumroad licence key
|
| 19 |
var RECHECK = 3 * 864e5;
|
| 20 |
var listeners = [];
|
| 21 |
|
|
@@ -24,7 +24,30 @@
|
|
| 24 |
var mem = get();
|
| 25 |
function isPro() { return !!(mem && mem.code); }
|
| 26 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 27 |
function check(code) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 28 |
return fetch(DATA + "/unlock/" + encodeURIComponent(C.id) + "?json=1&session_id=" + encodeURIComponent(code))
|
| 29 |
.then(function (r) { return r.json(); })
|
| 30 |
.then(function (j) { return j && typeof j.pro === "boolean" ? j.pro : null; })
|
|
@@ -152,7 +175,7 @@
|
|
| 152 |
|
| 153 |
window.CMXPro = { isPro: isPro, onChange: function (fn) { listeners.push(fn); fn(isPro()); }, upsell: upsell, quota: quota, download: download, toast: toast };
|
| 154 |
|
| 155 |
-
var m = /[#&]cmx-pro=([^&]+)/.exec(location.hash || "");
|
| 156 |
function start() {
|
| 157 |
if (m && SID.test(decodeURIComponent(m[1]))) {
|
| 158 |
var code = decodeURIComponent(m[1]);
|
|
@@ -162,3 +185,23 @@
|
|
| 162 |
}
|
| 163 |
if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", start); else start();
|
| 164 |
})();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 15 |
if (!C.id) return;
|
| 16 |
var DATA = "https://data.cybermaxtools.com";
|
| 17 |
var KEY = "cmx-pro:" + C.id;
|
| 18 |
+
var SID = /^(cmxk1\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+|cs_(live|test)_[A-Za-z0-9]{10,200}|[A-Z0-9]{8}-[A-Z0-9]{8}-[A-Z0-9]{8}-[A-Z0-9]{8})$/i; // Stripe order code or Gumroad licence key
|
| 19 |
var RECHECK = 3 * 864e5;
|
| 20 |
var listeners = [];
|
| 21 |
|
|
|
|
| 24 |
var mem = get();
|
| 25 |
function isPro() { return !!(mem && mem.code); }
|
| 26 |
|
| 27 |
+
// Offline Pro keys (17 Oct 2026): "cmxk1.<payload>.<Ed25519 signature>" from data.cybermaxtools.com/unlock is verified
|
| 28 |
+
// here with WebCrypto and the public key below, so unlocking needs no Worker call. Expired, foreign-signed or unverifiable
|
| 29 |
+
// (no Ed25519 in this browser) keys fall back to the online check of the order code inside them, as before.
|
| 30 |
+
var CMX_PUB = "u0FDxbu0d9B9Sz5-yLT6AuL5IagyTlFcbBgEDqZxWtk";
|
| 31 |
+
function b64d(s) { s = s.replace(/-/g, "+").replace(/_/g, "/"); while (s.length % 4) s += "="; var b = atob(s), u = new Uint8Array(b.length); for (var i = 0; i < b.length; i++) u[i] = b.charCodeAt(i); return u; }
|
| 32 |
+
function cmxVerify(k) {
|
| 33 |
+
var parts = k.split("."), p = null;
|
| 34 |
+
try { p = JSON.parse(new TextDecoder().decode(b64d(parts[1]))); } catch (e) { return Promise.resolve({ p: null, ok: false }); }
|
| 35 |
+
if (!(window.crypto && crypto.subtle)) return Promise.resolve({ p: p, ok: null });
|
| 36 |
+
return crypto.subtle.importKey("raw", b64d(CMX_PUB), { name: "Ed25519" }, false, ["verify"])
|
| 37 |
+
.then(function (key) { return crypto.subtle.verify({ name: "Ed25519" }, key, b64d(parts[2]), new TextEncoder().encode(parts[0] + "." + parts[1])); })
|
| 38 |
+
.then(function (ok) { return { p: p, ok: !!ok }; }, function () { return { p: p, ok: null }; });
|
| 39 |
+
}
|
| 40 |
function check(code) {
|
| 41 |
+
if (!/^cmxk1\./.test(code)) return checkOnline(code);
|
| 42 |
+
return cmxVerify(code).then(function (r) {
|
| 43 |
+
var p = r.p;
|
| 44 |
+
if (!p || p.a !== C.id) return false;
|
| 45 |
+
if (r.ok && (!p.x || p.x * 1000 > Date.now())) return true;
|
| 46 |
+
return p.c ? checkOnline(p.c) : false;
|
| 47 |
+
});
|
| 48 |
+
}
|
| 49 |
+
|
| 50 |
+
function checkOnline(code) {
|
| 51 |
return fetch(DATA + "/unlock/" + encodeURIComponent(C.id) + "?json=1&session_id=" + encodeURIComponent(code))
|
| 52 |
.then(function (r) { return r.json(); })
|
| 53 |
.then(function (j) { return j && typeof j.pro === "boolean" ? j.pro : null; })
|
|
|
|
| 175 |
|
| 176 |
window.CMXPro = { isPro: isPro, onChange: function (fn) { listeners.push(fn); fn(isPro()); }, upsell: upsell, quota: quota, download: download, toast: toast };
|
| 177 |
|
| 178 |
+
var m = /[#&]cmx-key=([^&]+)/.exec(location.hash || "") || /[#&]cmx-pro=([^&]+)/.exec(location.hash || "");
|
| 179 |
function start() {
|
| 180 |
if (m && SID.test(decodeURIComponent(m[1]))) {
|
| 181 |
var code = decodeURIComponent(m[1]);
|
|
|
|
| 185 |
}
|
| 186 |
if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", start); else start();
|
| 187 |
})();
|
| 188 |
+
|
| 189 |
+
/* Direct checkout (17 Oct 2026, Workers cap fix): a click on a data.cybermaxtools.com/buy/<offer> link goes straight to
|
| 190 |
+
the Stripe/Polar checkout (map: https://cybermaxtools.com/store/buy-direct.json, a static file) and the click is counted
|
| 191 |
+
by a background beacon. Without the map the link works as before. */
|
| 192 |
+
(function () {
|
| 193 |
+
var MAP = null, U = "https://cybermaxtools.com/store/buy-direct.json";
|
| 194 |
+
try { MAP = JSON.parse(sessionStorage.getItem("cmx-bd") || "null"); } catch (e) { /* none */ }
|
| 195 |
+
if (!MAP && window.fetch) fetch(U).then(function (r) { return r.json(); }).then(function (j) { MAP = j; try { sessionStorage.setItem("cmx-bd", JSON.stringify(j)); } catch (e) { /* full */ } }).catch(function () {});
|
| 196 |
+
document.addEventListener("click", function (e) {
|
| 197 |
+
var a = e.target && e.target.closest && e.target.closest('a[href*="data.cybermaxtools.com/buy/"]');
|
| 198 |
+
if (!a || !MAP || !MAP.offers) return;
|
| 199 |
+
try {
|
| 200 |
+
var u = new URL(a.href), k = /^\/buy\/([a-z0-9-]+)\/?$/.exec(u.pathname), t = k && MAP.offers[k[1]];
|
| 201 |
+
if (!t) return;
|
| 202 |
+
var s = String(u.searchParams.get("s") || "unknown").toLowerCase().replace(/[^a-z0-9-]/g, "").slice(0, 80) || "unknown";
|
| 203 |
+
a.href = t.split(MAP.ph).join(s);
|
| 204 |
+
if (!navigator.webdriver) navigator.sendBeacon(u.href + (u.search ? "&" : "?") + "b=1");
|
| 205 |
+
} catch (x) { /* keep the counted link */ }
|
| 206 |
+
}, true);
|
| 207 |
+
})();
|
platesprig/pro.js
CHANGED
|
@@ -15,7 +15,7 @@
|
|
| 15 |
if (!C.id) return;
|
| 16 |
var DATA = "https://data.cybermaxtools.com";
|
| 17 |
var KEY = "cmx-pro:" + C.id;
|
| 18 |
-
var SID = /^(cs_(live|test)_[A-Za-z0-9]{10,200}|[A-Z0-9]{8}-[A-Z0-9]{8}-[A-Z0-9]{8}-[A-Z0-9]{8})$/i; // Stripe order code or Gumroad licence key
|
| 19 |
var RECHECK = 3 * 864e5;
|
| 20 |
var listeners = [];
|
| 21 |
|
|
@@ -24,7 +24,30 @@
|
|
| 24 |
var mem = get();
|
| 25 |
function isPro() { return !!(mem && mem.code); }
|
| 26 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 27 |
function check(code) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 28 |
return fetch(DATA + "/unlock/" + encodeURIComponent(C.id) + "?json=1&session_id=" + encodeURIComponent(code))
|
| 29 |
.then(function (r) { return r.json(); })
|
| 30 |
.then(function (j) { return j && typeof j.pro === "boolean" ? j.pro : null; })
|
|
@@ -152,7 +175,7 @@
|
|
| 152 |
|
| 153 |
window.CMXPro = { isPro: isPro, onChange: function (fn) { listeners.push(fn); fn(isPro()); }, upsell: upsell, quota: quota, download: download, toast: toast };
|
| 154 |
|
| 155 |
-
var m = /[#&]cmx-pro=([^&]+)/.exec(location.hash || "");
|
| 156 |
function start() {
|
| 157 |
if (m && SID.test(decodeURIComponent(m[1]))) {
|
| 158 |
var code = decodeURIComponent(m[1]);
|
|
@@ -162,3 +185,23 @@
|
|
| 162 |
}
|
| 163 |
if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", start); else start();
|
| 164 |
})();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 15 |
if (!C.id) return;
|
| 16 |
var DATA = "https://data.cybermaxtools.com";
|
| 17 |
var KEY = "cmx-pro:" + C.id;
|
| 18 |
+
var SID = /^(cmxk1\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+|cs_(live|test)_[A-Za-z0-9]{10,200}|[A-Z0-9]{8}-[A-Z0-9]{8}-[A-Z0-9]{8}-[A-Z0-9]{8})$/i; // Stripe order code or Gumroad licence key
|
| 19 |
var RECHECK = 3 * 864e5;
|
| 20 |
var listeners = [];
|
| 21 |
|
|
|
|
| 24 |
var mem = get();
|
| 25 |
function isPro() { return !!(mem && mem.code); }
|
| 26 |
|
| 27 |
+
// Offline Pro keys (17 Oct 2026): "cmxk1.<payload>.<Ed25519 signature>" from data.cybermaxtools.com/unlock is verified
|
| 28 |
+
// here with WebCrypto and the public key below, so unlocking needs no Worker call. Expired, foreign-signed or unverifiable
|
| 29 |
+
// (no Ed25519 in this browser) keys fall back to the online check of the order code inside them, as before.
|
| 30 |
+
var CMX_PUB = "u0FDxbu0d9B9Sz5-yLT6AuL5IagyTlFcbBgEDqZxWtk";
|
| 31 |
+
function b64d(s) { s = s.replace(/-/g, "+").replace(/_/g, "/"); while (s.length % 4) s += "="; var b = atob(s), u = new Uint8Array(b.length); for (var i = 0; i < b.length; i++) u[i] = b.charCodeAt(i); return u; }
|
| 32 |
+
function cmxVerify(k) {
|
| 33 |
+
var parts = k.split("."), p = null;
|
| 34 |
+
try { p = JSON.parse(new TextDecoder().decode(b64d(parts[1]))); } catch (e) { return Promise.resolve({ p: null, ok: false }); }
|
| 35 |
+
if (!(window.crypto && crypto.subtle)) return Promise.resolve({ p: p, ok: null });
|
| 36 |
+
return crypto.subtle.importKey("raw", b64d(CMX_PUB), { name: "Ed25519" }, false, ["verify"])
|
| 37 |
+
.then(function (key) { return crypto.subtle.verify({ name: "Ed25519" }, key, b64d(parts[2]), new TextEncoder().encode(parts[0] + "." + parts[1])); })
|
| 38 |
+
.then(function (ok) { return { p: p, ok: !!ok }; }, function () { return { p: p, ok: null }; });
|
| 39 |
+
}
|
| 40 |
function check(code) {
|
| 41 |
+
if (!/^cmxk1\./.test(code)) return checkOnline(code);
|
| 42 |
+
return cmxVerify(code).then(function (r) {
|
| 43 |
+
var p = r.p;
|
| 44 |
+
if (!p || p.a !== C.id) return false;
|
| 45 |
+
if (r.ok && (!p.x || p.x * 1000 > Date.now())) return true;
|
| 46 |
+
return p.c ? checkOnline(p.c) : false;
|
| 47 |
+
});
|
| 48 |
+
}
|
| 49 |
+
|
| 50 |
+
function checkOnline(code) {
|
| 51 |
return fetch(DATA + "/unlock/" + encodeURIComponent(C.id) + "?json=1&session_id=" + encodeURIComponent(code))
|
| 52 |
.then(function (r) { return r.json(); })
|
| 53 |
.then(function (j) { return j && typeof j.pro === "boolean" ? j.pro : null; })
|
|
|
|
| 175 |
|
| 176 |
window.CMXPro = { isPro: isPro, onChange: function (fn) { listeners.push(fn); fn(isPro()); }, upsell: upsell, quota: quota, download: download, toast: toast };
|
| 177 |
|
| 178 |
+
var m = /[#&]cmx-key=([^&]+)/.exec(location.hash || "") || /[#&]cmx-pro=([^&]+)/.exec(location.hash || "");
|
| 179 |
function start() {
|
| 180 |
if (m && SID.test(decodeURIComponent(m[1]))) {
|
| 181 |
var code = decodeURIComponent(m[1]);
|
|
|
|
| 185 |
}
|
| 186 |
if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", start); else start();
|
| 187 |
})();
|
| 188 |
+
|
| 189 |
+
/* Direct checkout (17 Oct 2026, Workers cap fix): a click on a data.cybermaxtools.com/buy/<offer> link goes straight to
|
| 190 |
+
the Stripe/Polar checkout (map: https://cybermaxtools.com/store/buy-direct.json, a static file) and the click is counted
|
| 191 |
+
by a background beacon. Without the map the link works as before. */
|
| 192 |
+
(function () {
|
| 193 |
+
var MAP = null, U = "https://cybermaxtools.com/store/buy-direct.json";
|
| 194 |
+
try { MAP = JSON.parse(sessionStorage.getItem("cmx-bd") || "null"); } catch (e) { /* none */ }
|
| 195 |
+
if (!MAP && window.fetch) fetch(U).then(function (r) { return r.json(); }).then(function (j) { MAP = j; try { sessionStorage.setItem("cmx-bd", JSON.stringify(j)); } catch (e) { /* full */ } }).catch(function () {});
|
| 196 |
+
document.addEventListener("click", function (e) {
|
| 197 |
+
var a = e.target && e.target.closest && e.target.closest('a[href*="data.cybermaxtools.com/buy/"]');
|
| 198 |
+
if (!a || !MAP || !MAP.offers) return;
|
| 199 |
+
try {
|
| 200 |
+
var u = new URL(a.href), k = /^\/buy\/([a-z0-9-]+)\/?$/.exec(u.pathname), t = k && MAP.offers[k[1]];
|
| 201 |
+
if (!t) return;
|
| 202 |
+
var s = String(u.searchParams.get("s") || "unknown").toLowerCase().replace(/[^a-z0-9-]/g, "").slice(0, 80) || "unknown";
|
| 203 |
+
a.href = t.split(MAP.ph).join(s);
|
| 204 |
+
if (!navigator.webdriver) navigator.sendBeacon(u.href + (u.search ? "&" : "?") + "b=1");
|
| 205 |
+
} catch (x) { /* keep the counted link */ }
|
| 206 |
+
}, true);
|
| 207 |
+
})();
|
profit-margin-calculator/pro.js
CHANGED
|
@@ -11,7 +11,7 @@
|
|
| 11 |
if (!C.id) return;
|
| 12 |
var DATA = "https://data.cybermaxtools.com";
|
| 13 |
var KEY = "cmx-pro:" + C.id;
|
| 14 |
-
var SID = /^(cs_(live|test)_[A-Za-z0-9]{10,200}|[A-Z0-9]{8}-[A-Z0-9]{8}-[A-Z0-9]{8}-[A-Z0-9]{8})$/i; // Stripe order code or Gumroad licence key
|
| 15 |
var listeners = [];
|
| 16 |
|
| 17 |
function get() { try { return JSON.parse(localStorage.getItem(KEY) || "null"); } catch (e) { return null; } }
|
|
@@ -19,7 +19,30 @@
|
|
| 19 |
var mem = get();
|
| 20 |
function isPro() { return !!(mem && mem.code); }
|
| 21 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 22 |
function check(code) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 23 |
return fetch(DATA + "/unlock/" + encodeURIComponent(C.id) + "?json=1&session_id=" + encodeURIComponent(code))
|
| 24 |
.then(function (r) { return r.json(); }).then(function (j) { return !!(j && j.pro); }).catch(function () { return null; });
|
| 25 |
}
|
|
@@ -99,10 +122,30 @@
|
|
| 99 |
|
| 100 |
window.CMXPro = { isPro: isPro, onChange: function (fn) { listeners.push(fn); fn(isPro()); }, download: download, csv: csv, markdown: markdown, rows: rows, toast: toast };
|
| 101 |
|
| 102 |
-
var m = /[#&]cmx-pro=([^&]+)/.exec(location.hash || "");
|
| 103 |
if (m && SID.test(decodeURIComponent(m[1]))) {
|
| 104 |
var code = decodeURIComponent(m[1]);
|
| 105 |
history.replaceState(null, "", location.pathname + location.search);
|
| 106 |
if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", function () { apply(); unlock(code); }); else { apply(); unlock(code); }
|
| 107 |
} else if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", apply); else apply();
|
| 108 |
})();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 11 |
if (!C.id) return;
|
| 12 |
var DATA = "https://data.cybermaxtools.com";
|
| 13 |
var KEY = "cmx-pro:" + C.id;
|
| 14 |
+
var SID = /^(cmxk1\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+|cs_(live|test)_[A-Za-z0-9]{10,200}|[A-Z0-9]{8}-[A-Z0-9]{8}-[A-Z0-9]{8}-[A-Z0-9]{8})$/i; // Stripe order code or Gumroad licence key
|
| 15 |
var listeners = [];
|
| 16 |
|
| 17 |
function get() { try { return JSON.parse(localStorage.getItem(KEY) || "null"); } catch (e) { return null; } }
|
|
|
|
| 19 |
var mem = get();
|
| 20 |
function isPro() { return !!(mem && mem.code); }
|
| 21 |
|
| 22 |
+
// Offline Pro keys (17 Oct 2026): "cmxk1.<payload>.<Ed25519 signature>" from data.cybermaxtools.com/unlock is verified
|
| 23 |
+
// here with WebCrypto and the public key below, so unlocking needs no Worker call. Expired, foreign-signed or unverifiable
|
| 24 |
+
// (no Ed25519 in this browser) keys fall back to the online check of the order code inside them, as before.
|
| 25 |
+
var CMX_PUB = "u0FDxbu0d9B9Sz5-yLT6AuL5IagyTlFcbBgEDqZxWtk";
|
| 26 |
+
function b64d(s) { s = s.replace(/-/g, "+").replace(/_/g, "/"); while (s.length % 4) s += "="; var b = atob(s), u = new Uint8Array(b.length); for (var i = 0; i < b.length; i++) u[i] = b.charCodeAt(i); return u; }
|
| 27 |
+
function cmxVerify(k) {
|
| 28 |
+
var parts = k.split("."), p = null;
|
| 29 |
+
try { p = JSON.parse(new TextDecoder().decode(b64d(parts[1]))); } catch (e) { return Promise.resolve({ p: null, ok: false }); }
|
| 30 |
+
if (!(window.crypto && crypto.subtle)) return Promise.resolve({ p: p, ok: null });
|
| 31 |
+
return crypto.subtle.importKey("raw", b64d(CMX_PUB), { name: "Ed25519" }, false, ["verify"])
|
| 32 |
+
.then(function (key) { return crypto.subtle.verify({ name: "Ed25519" }, key, b64d(parts[2]), new TextEncoder().encode(parts[0] + "." + parts[1])); })
|
| 33 |
+
.then(function (ok) { return { p: p, ok: !!ok }; }, function () { return { p: p, ok: null }; });
|
| 34 |
+
}
|
| 35 |
function check(code) {
|
| 36 |
+
if (!/^cmxk1\./.test(code)) return checkOnline(code);
|
| 37 |
+
return cmxVerify(code).then(function (r) {
|
| 38 |
+
var p = r.p;
|
| 39 |
+
if (!p || p.a !== C.id) return false;
|
| 40 |
+
if (r.ok && (!p.x || p.x * 1000 > Date.now())) return true;
|
| 41 |
+
return p.c ? checkOnline(p.c) : false;
|
| 42 |
+
});
|
| 43 |
+
}
|
| 44 |
+
|
| 45 |
+
function checkOnline(code) {
|
| 46 |
return fetch(DATA + "/unlock/" + encodeURIComponent(C.id) + "?json=1&session_id=" + encodeURIComponent(code))
|
| 47 |
.then(function (r) { return r.json(); }).then(function (j) { return !!(j && j.pro); }).catch(function () { return null; });
|
| 48 |
}
|
|
|
|
| 122 |
|
| 123 |
window.CMXPro = { isPro: isPro, onChange: function (fn) { listeners.push(fn); fn(isPro()); }, download: download, csv: csv, markdown: markdown, rows: rows, toast: toast };
|
| 124 |
|
| 125 |
+
var m = /[#&]cmx-key=([^&]+)/.exec(location.hash || "") || /[#&]cmx-pro=([^&]+)/.exec(location.hash || "");
|
| 126 |
if (m && SID.test(decodeURIComponent(m[1]))) {
|
| 127 |
var code = decodeURIComponent(m[1]);
|
| 128 |
history.replaceState(null, "", location.pathname + location.search);
|
| 129 |
if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", function () { apply(); unlock(code); }); else { apply(); unlock(code); }
|
| 130 |
} else if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", apply); else apply();
|
| 131 |
})();
|
| 132 |
+
|
| 133 |
+
/* Direct checkout (17 Oct 2026, Workers cap fix): a click on a data.cybermaxtools.com/buy/<offer> link goes straight to
|
| 134 |
+
the Stripe/Polar checkout (map: https://cybermaxtools.com/store/buy-direct.json, a static file) and the click is counted
|
| 135 |
+
by a background beacon. Without the map the link works as before. */
|
| 136 |
+
(function () {
|
| 137 |
+
var MAP = null, U = "https://cybermaxtools.com/store/buy-direct.json";
|
| 138 |
+
try { MAP = JSON.parse(sessionStorage.getItem("cmx-bd") || "null"); } catch (e) { /* none */ }
|
| 139 |
+
if (!MAP && window.fetch) fetch(U).then(function (r) { return r.json(); }).then(function (j) { MAP = j; try { sessionStorage.setItem("cmx-bd", JSON.stringify(j)); } catch (e) { /* full */ } }).catch(function () {});
|
| 140 |
+
document.addEventListener("click", function (e) {
|
| 141 |
+
var a = e.target && e.target.closest && e.target.closest('a[href*="data.cybermaxtools.com/buy/"]');
|
| 142 |
+
if (!a || !MAP || !MAP.offers) return;
|
| 143 |
+
try {
|
| 144 |
+
var u = new URL(a.href), k = /^\/buy\/([a-z0-9-]+)\/?$/.exec(u.pathname), t = k && MAP.offers[k[1]];
|
| 145 |
+
if (!t) return;
|
| 146 |
+
var s = String(u.searchParams.get("s") || "unknown").toLowerCase().replace(/[^a-z0-9-]/g, "").slice(0, 80) || "unknown";
|
| 147 |
+
a.href = t.split(MAP.ph).join(s);
|
| 148 |
+
if (!navigator.webdriver) navigator.sendBeacon(u.href + (u.search ? "&" : "?") + "b=1");
|
| 149 |
+
} catch (x) { /* keep the counted link */ }
|
| 150 |
+
}, true);
|
| 151 |
+
})();
|
quotesprig/pro.js
CHANGED
|
@@ -15,7 +15,7 @@
|
|
| 15 |
if (!C.id) return;
|
| 16 |
var DATA = "https://data.cybermaxtools.com";
|
| 17 |
var KEY = "cmx-pro:" + C.id;
|
| 18 |
-
var SID = /^(cs_(live|test)_[A-Za-z0-9]{10,200}|[A-Z0-9]{8}-[A-Z0-9]{8}-[A-Z0-9]{8}-[A-Z0-9]{8})$/i; // Stripe order code or Gumroad licence key
|
| 19 |
var RECHECK = 3 * 864e5;
|
| 20 |
var listeners = [];
|
| 21 |
|
|
@@ -24,7 +24,30 @@
|
|
| 24 |
var mem = get();
|
| 25 |
function isPro() { return !!(mem && mem.code); }
|
| 26 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 27 |
function check(code) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 28 |
return fetch(DATA + "/unlock/" + encodeURIComponent(C.id) + "?json=1&session_id=" + encodeURIComponent(code))
|
| 29 |
.then(function (r) { return r.json(); })
|
| 30 |
.then(function (j) { return j && typeof j.pro === "boolean" ? j.pro : null; })
|
|
@@ -152,7 +175,7 @@
|
|
| 152 |
|
| 153 |
window.CMXPro = { isPro: isPro, onChange: function (fn) { listeners.push(fn); fn(isPro()); }, upsell: upsell, quota: quota, download: download, toast: toast };
|
| 154 |
|
| 155 |
-
var m = /[#&]cmx-pro=([^&]+)/.exec(location.hash || "");
|
| 156 |
function start() {
|
| 157 |
if (m && SID.test(decodeURIComponent(m[1]))) {
|
| 158 |
var code = decodeURIComponent(m[1]);
|
|
@@ -162,3 +185,23 @@
|
|
| 162 |
}
|
| 163 |
if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", start); else start();
|
| 164 |
})();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 15 |
if (!C.id) return;
|
| 16 |
var DATA = "https://data.cybermaxtools.com";
|
| 17 |
var KEY = "cmx-pro:" + C.id;
|
| 18 |
+
var SID = /^(cmxk1\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+|cs_(live|test)_[A-Za-z0-9]{10,200}|[A-Z0-9]{8}-[A-Z0-9]{8}-[A-Z0-9]{8}-[A-Z0-9]{8})$/i; // Stripe order code or Gumroad licence key
|
| 19 |
var RECHECK = 3 * 864e5;
|
| 20 |
var listeners = [];
|
| 21 |
|
|
|
|
| 24 |
var mem = get();
|
| 25 |
function isPro() { return !!(mem && mem.code); }
|
| 26 |
|
| 27 |
+
// Offline Pro keys (17 Oct 2026): "cmxk1.<payload>.<Ed25519 signature>" from data.cybermaxtools.com/unlock is verified
|
| 28 |
+
// here with WebCrypto and the public key below, so unlocking needs no Worker call. Expired, foreign-signed or unverifiable
|
| 29 |
+
// (no Ed25519 in this browser) keys fall back to the online check of the order code inside them, as before.
|
| 30 |
+
var CMX_PUB = "u0FDxbu0d9B9Sz5-yLT6AuL5IagyTlFcbBgEDqZxWtk";
|
| 31 |
+
function b64d(s) { s = s.replace(/-/g, "+").replace(/_/g, "/"); while (s.length % 4) s += "="; var b = atob(s), u = new Uint8Array(b.length); for (var i = 0; i < b.length; i++) u[i] = b.charCodeAt(i); return u; }
|
| 32 |
+
function cmxVerify(k) {
|
| 33 |
+
var parts = k.split("."), p = null;
|
| 34 |
+
try { p = JSON.parse(new TextDecoder().decode(b64d(parts[1]))); } catch (e) { return Promise.resolve({ p: null, ok: false }); }
|
| 35 |
+
if (!(window.crypto && crypto.subtle)) return Promise.resolve({ p: p, ok: null });
|
| 36 |
+
return crypto.subtle.importKey("raw", b64d(CMX_PUB), { name: "Ed25519" }, false, ["verify"])
|
| 37 |
+
.then(function (key) { return crypto.subtle.verify({ name: "Ed25519" }, key, b64d(parts[2]), new TextEncoder().encode(parts[0] + "." + parts[1])); })
|
| 38 |
+
.then(function (ok) { return { p: p, ok: !!ok }; }, function () { return { p: p, ok: null }; });
|
| 39 |
+
}
|
| 40 |
function check(code) {
|
| 41 |
+
if (!/^cmxk1\./.test(code)) return checkOnline(code);
|
| 42 |
+
return cmxVerify(code).then(function (r) {
|
| 43 |
+
var p = r.p;
|
| 44 |
+
if (!p || p.a !== C.id) return false;
|
| 45 |
+
if (r.ok && (!p.x || p.x * 1000 > Date.now())) return true;
|
| 46 |
+
return p.c ? checkOnline(p.c) : false;
|
| 47 |
+
});
|
| 48 |
+
}
|
| 49 |
+
|
| 50 |
+
function checkOnline(code) {
|
| 51 |
return fetch(DATA + "/unlock/" + encodeURIComponent(C.id) + "?json=1&session_id=" + encodeURIComponent(code))
|
| 52 |
.then(function (r) { return r.json(); })
|
| 53 |
.then(function (j) { return j && typeof j.pro === "boolean" ? j.pro : null; })
|
|
|
|
| 175 |
|
| 176 |
window.CMXPro = { isPro: isPro, onChange: function (fn) { listeners.push(fn); fn(isPro()); }, upsell: upsell, quota: quota, download: download, toast: toast };
|
| 177 |
|
| 178 |
+
var m = /[#&]cmx-key=([^&]+)/.exec(location.hash || "") || /[#&]cmx-pro=([^&]+)/.exec(location.hash || "");
|
| 179 |
function start() {
|
| 180 |
if (m && SID.test(decodeURIComponent(m[1]))) {
|
| 181 |
var code = decodeURIComponent(m[1]);
|
|
|
|
| 185 |
}
|
| 186 |
if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", start); else start();
|
| 187 |
})();
|
| 188 |
+
|
| 189 |
+
/* Direct checkout (17 Oct 2026, Workers cap fix): a click on a data.cybermaxtools.com/buy/<offer> link goes straight to
|
| 190 |
+
the Stripe/Polar checkout (map: https://cybermaxtools.com/store/buy-direct.json, a static file) and the click is counted
|
| 191 |
+
by a background beacon. Without the map the link works as before. */
|
| 192 |
+
(function () {
|
| 193 |
+
var MAP = null, U = "https://cybermaxtools.com/store/buy-direct.json";
|
| 194 |
+
try { MAP = JSON.parse(sessionStorage.getItem("cmx-bd") || "null"); } catch (e) { /* none */ }
|
| 195 |
+
if (!MAP && window.fetch) fetch(U).then(function (r) { return r.json(); }).then(function (j) { MAP = j; try { sessionStorage.setItem("cmx-bd", JSON.stringify(j)); } catch (e) { /* full */ } }).catch(function () {});
|
| 196 |
+
document.addEventListener("click", function (e) {
|
| 197 |
+
var a = e.target && e.target.closest && e.target.closest('a[href*="data.cybermaxtools.com/buy/"]');
|
| 198 |
+
if (!a || !MAP || !MAP.offers) return;
|
| 199 |
+
try {
|
| 200 |
+
var u = new URL(a.href), k = /^\/buy\/([a-z0-9-]+)\/?$/.exec(u.pathname), t = k && MAP.offers[k[1]];
|
| 201 |
+
if (!t) return;
|
| 202 |
+
var s = String(u.searchParams.get("s") || "unknown").toLowerCase().replace(/[^a-z0-9-]/g, "").slice(0, 80) || "unknown";
|
| 203 |
+
a.href = t.split(MAP.ph).join(s);
|
| 204 |
+
if (!navigator.webdriver) navigator.sendBeacon(u.href + (u.search ? "&" : "?") + "b=1");
|
| 205 |
+
} catch (x) { /* keep the counted link */ }
|
| 206 |
+
}, true);
|
| 207 |
+
})();
|
rentsprig/pro.js
CHANGED
|
@@ -15,7 +15,7 @@
|
|
| 15 |
if (!C.id) return;
|
| 16 |
var DATA = "https://data.cybermaxtools.com";
|
| 17 |
var KEY = "cmx-pro:" + C.id;
|
| 18 |
-
var SID = /^(cs_(live|test)_[A-Za-z0-9]{10,200}|[A-Z0-9]{8}-[A-Z0-9]{8}-[A-Z0-9]{8}-[A-Z0-9]{8})$/i; // Stripe order code or Gumroad licence key
|
| 19 |
var RECHECK = 3 * 864e5;
|
| 20 |
var listeners = [];
|
| 21 |
|
|
@@ -24,7 +24,30 @@
|
|
| 24 |
var mem = get();
|
| 25 |
function isPro() { return !!(mem && mem.code); }
|
| 26 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 27 |
function check(code) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 28 |
return fetch(DATA + "/unlock/" + encodeURIComponent(C.id) + "?json=1&session_id=" + encodeURIComponent(code))
|
| 29 |
.then(function (r) { return r.json(); })
|
| 30 |
.then(function (j) { return j && typeof j.pro === "boolean" ? j.pro : null; })
|
|
@@ -152,7 +175,7 @@
|
|
| 152 |
|
| 153 |
window.CMXPro = { isPro: isPro, onChange: function (fn) { listeners.push(fn); fn(isPro()); }, upsell: upsell, quota: quota, download: download, toast: toast };
|
| 154 |
|
| 155 |
-
var m = /[#&]cmx-pro=([^&]+)/.exec(location.hash || "");
|
| 156 |
function start() {
|
| 157 |
if (m && SID.test(decodeURIComponent(m[1]))) {
|
| 158 |
var code = decodeURIComponent(m[1]);
|
|
@@ -162,3 +185,23 @@
|
|
| 162 |
}
|
| 163 |
if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", start); else start();
|
| 164 |
})();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 15 |
if (!C.id) return;
|
| 16 |
var DATA = "https://data.cybermaxtools.com";
|
| 17 |
var KEY = "cmx-pro:" + C.id;
|
| 18 |
+
var SID = /^(cmxk1\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+|cs_(live|test)_[A-Za-z0-9]{10,200}|[A-Z0-9]{8}-[A-Z0-9]{8}-[A-Z0-9]{8}-[A-Z0-9]{8})$/i; // Stripe order code or Gumroad licence key
|
| 19 |
var RECHECK = 3 * 864e5;
|
| 20 |
var listeners = [];
|
| 21 |
|
|
|
|
| 24 |
var mem = get();
|
| 25 |
function isPro() { return !!(mem && mem.code); }
|
| 26 |
|
| 27 |
+
// Offline Pro keys (17 Oct 2026): "cmxk1.<payload>.<Ed25519 signature>" from data.cybermaxtools.com/unlock is verified
|
| 28 |
+
// here with WebCrypto and the public key below, so unlocking needs no Worker call. Expired, foreign-signed or unverifiable
|
| 29 |
+
// (no Ed25519 in this browser) keys fall back to the online check of the order code inside them, as before.
|
| 30 |
+
var CMX_PUB = "u0FDxbu0d9B9Sz5-yLT6AuL5IagyTlFcbBgEDqZxWtk";
|
| 31 |
+
function b64d(s) { s = s.replace(/-/g, "+").replace(/_/g, "/"); while (s.length % 4) s += "="; var b = atob(s), u = new Uint8Array(b.length); for (var i = 0; i < b.length; i++) u[i] = b.charCodeAt(i); return u; }
|
| 32 |
+
function cmxVerify(k) {
|
| 33 |
+
var parts = k.split("."), p = null;
|
| 34 |
+
try { p = JSON.parse(new TextDecoder().decode(b64d(parts[1]))); } catch (e) { return Promise.resolve({ p: null, ok: false }); }
|
| 35 |
+
if (!(window.crypto && crypto.subtle)) return Promise.resolve({ p: p, ok: null });
|
| 36 |
+
return crypto.subtle.importKey("raw", b64d(CMX_PUB), { name: "Ed25519" }, false, ["verify"])
|
| 37 |
+
.then(function (key) { return crypto.subtle.verify({ name: "Ed25519" }, key, b64d(parts[2]), new TextEncoder().encode(parts[0] + "." + parts[1])); })
|
| 38 |
+
.then(function (ok) { return { p: p, ok: !!ok }; }, function () { return { p: p, ok: null }; });
|
| 39 |
+
}
|
| 40 |
function check(code) {
|
| 41 |
+
if (!/^cmxk1\./.test(code)) return checkOnline(code);
|
| 42 |
+
return cmxVerify(code).then(function (r) {
|
| 43 |
+
var p = r.p;
|
| 44 |
+
if (!p || p.a !== C.id) return false;
|
| 45 |
+
if (r.ok && (!p.x || p.x * 1000 > Date.now())) return true;
|
| 46 |
+
return p.c ? checkOnline(p.c) : false;
|
| 47 |
+
});
|
| 48 |
+
}
|
| 49 |
+
|
| 50 |
+
function checkOnline(code) {
|
| 51 |
return fetch(DATA + "/unlock/" + encodeURIComponent(C.id) + "?json=1&session_id=" + encodeURIComponent(code))
|
| 52 |
.then(function (r) { return r.json(); })
|
| 53 |
.then(function (j) { return j && typeof j.pro === "boolean" ? j.pro : null; })
|
|
|
|
| 175 |
|
| 176 |
window.CMXPro = { isPro: isPro, onChange: function (fn) { listeners.push(fn); fn(isPro()); }, upsell: upsell, quota: quota, download: download, toast: toast };
|
| 177 |
|
| 178 |
+
var m = /[#&]cmx-key=([^&]+)/.exec(location.hash || "") || /[#&]cmx-pro=([^&]+)/.exec(location.hash || "");
|
| 179 |
function start() {
|
| 180 |
if (m && SID.test(decodeURIComponent(m[1]))) {
|
| 181 |
var code = decodeURIComponent(m[1]);
|
|
|
|
| 185 |
}
|
| 186 |
if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", start); else start();
|
| 187 |
})();
|
| 188 |
+
|
| 189 |
+
/* Direct checkout (17 Oct 2026, Workers cap fix): a click on a data.cybermaxtools.com/buy/<offer> link goes straight to
|
| 190 |
+
the Stripe/Polar checkout (map: https://cybermaxtools.com/store/buy-direct.json, a static file) and the click is counted
|
| 191 |
+
by a background beacon. Without the map the link works as before. */
|
| 192 |
+
(function () {
|
| 193 |
+
var MAP = null, U = "https://cybermaxtools.com/store/buy-direct.json";
|
| 194 |
+
try { MAP = JSON.parse(sessionStorage.getItem("cmx-bd") || "null"); } catch (e) { /* none */ }
|
| 195 |
+
if (!MAP && window.fetch) fetch(U).then(function (r) { return r.json(); }).then(function (j) { MAP = j; try { sessionStorage.setItem("cmx-bd", JSON.stringify(j)); } catch (e) { /* full */ } }).catch(function () {});
|
| 196 |
+
document.addEventListener("click", function (e) {
|
| 197 |
+
var a = e.target && e.target.closest && e.target.closest('a[href*="data.cybermaxtools.com/buy/"]');
|
| 198 |
+
if (!a || !MAP || !MAP.offers) return;
|
| 199 |
+
try {
|
| 200 |
+
var u = new URL(a.href), k = /^\/buy\/([a-z0-9-]+)\/?$/.exec(u.pathname), t = k && MAP.offers[k[1]];
|
| 201 |
+
if (!t) return;
|
| 202 |
+
var s = String(u.searchParams.get("s") || "unknown").toLowerCase().replace(/[^a-z0-9-]/g, "").slice(0, 80) || "unknown";
|
| 203 |
+
a.href = t.split(MAP.ph).join(s);
|
| 204 |
+
if (!navigator.webdriver) navigator.sendBeacon(u.href + (u.search ? "&" : "?") + "b=1");
|
| 205 |
+
} catch (x) { /* keep the counted link */ }
|
| 206 |
+
}, true);
|
| 207 |
+
})();
|
rotasprig/pro.js
CHANGED
|
@@ -15,7 +15,7 @@
|
|
| 15 |
if (!C.id) return;
|
| 16 |
var DATA = "https://data.cybermaxtools.com";
|
| 17 |
var KEY = "cmx-pro:" + C.id;
|
| 18 |
-
var SID = /^(cs_(live|test)_[A-Za-z0-9]{10,200}|[A-Z0-9]{8}-[A-Z0-9]{8}-[A-Z0-9]{8}-[A-Z0-9]{8})$/i; // Stripe order code or Gumroad licence key
|
| 19 |
var RECHECK = 3 * 864e5;
|
| 20 |
var listeners = [];
|
| 21 |
|
|
@@ -24,7 +24,30 @@
|
|
| 24 |
var mem = get();
|
| 25 |
function isPro() { return !!(mem && mem.code); }
|
| 26 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 27 |
function check(code) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 28 |
return fetch(DATA + "/unlock/" + encodeURIComponent(C.id) + "?json=1&session_id=" + encodeURIComponent(code))
|
| 29 |
.then(function (r) { return r.json(); })
|
| 30 |
.then(function (j) { return j && typeof j.pro === "boolean" ? j.pro : null; })
|
|
@@ -154,7 +177,7 @@
|
|
| 154 |
|
| 155 |
window.CMXPro = { isPro: isPro, onChange: function (fn) { listeners.push(fn); fn(isPro()); }, upsell: upsell, quota: quota, download: download, toast: toast };
|
| 156 |
|
| 157 |
-
var m = /[#&]cmx-pro=([^&]+)/.exec(location.hash || "");
|
| 158 |
function start() {
|
| 159 |
if (m && SID.test(decodeURIComponent(m[1]))) {
|
| 160 |
var code = decodeURIComponent(m[1]);
|
|
@@ -164,3 +187,23 @@
|
|
| 164 |
}
|
| 165 |
if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", start); else start();
|
| 166 |
})();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 15 |
if (!C.id) return;
|
| 16 |
var DATA = "https://data.cybermaxtools.com";
|
| 17 |
var KEY = "cmx-pro:" + C.id;
|
| 18 |
+
var SID = /^(cmxk1\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+|cs_(live|test)_[A-Za-z0-9]{10,200}|[A-Z0-9]{8}-[A-Z0-9]{8}-[A-Z0-9]{8}-[A-Z0-9]{8})$/i; // Stripe order code or Gumroad licence key
|
| 19 |
var RECHECK = 3 * 864e5;
|
| 20 |
var listeners = [];
|
| 21 |
|
|
|
|
| 24 |
var mem = get();
|
| 25 |
function isPro() { return !!(mem && mem.code); }
|
| 26 |
|
| 27 |
+
// Offline Pro keys (17 Oct 2026): "cmxk1.<payload>.<Ed25519 signature>" from data.cybermaxtools.com/unlock is verified
|
| 28 |
+
// here with WebCrypto and the public key below, so unlocking needs no Worker call. Expired, foreign-signed or unverifiable
|
| 29 |
+
// (no Ed25519 in this browser) keys fall back to the online check of the order code inside them, as before.
|
| 30 |
+
var CMX_PUB = "u0FDxbu0d9B9Sz5-yLT6AuL5IagyTlFcbBgEDqZxWtk";
|
| 31 |
+
function b64d(s) { s = s.replace(/-/g, "+").replace(/_/g, "/"); while (s.length % 4) s += "="; var b = atob(s), u = new Uint8Array(b.length); for (var i = 0; i < b.length; i++) u[i] = b.charCodeAt(i); return u; }
|
| 32 |
+
function cmxVerify(k) {
|
| 33 |
+
var parts = k.split("."), p = null;
|
| 34 |
+
try { p = JSON.parse(new TextDecoder().decode(b64d(parts[1]))); } catch (e) { return Promise.resolve({ p: null, ok: false }); }
|
| 35 |
+
if (!(window.crypto && crypto.subtle)) return Promise.resolve({ p: p, ok: null });
|
| 36 |
+
return crypto.subtle.importKey("raw", b64d(CMX_PUB), { name: "Ed25519" }, false, ["verify"])
|
| 37 |
+
.then(function (key) { return crypto.subtle.verify({ name: "Ed25519" }, key, b64d(parts[2]), new TextEncoder().encode(parts[0] + "." + parts[1])); })
|
| 38 |
+
.then(function (ok) { return { p: p, ok: !!ok }; }, function () { return { p: p, ok: null }; });
|
| 39 |
+
}
|
| 40 |
function check(code) {
|
| 41 |
+
if (!/^cmxk1\./.test(code)) return checkOnline(code);
|
| 42 |
+
return cmxVerify(code).then(function (r) {
|
| 43 |
+
var p = r.p;
|
| 44 |
+
if (!p || p.a !== C.id) return false;
|
| 45 |
+
if (r.ok && (!p.x || p.x * 1000 > Date.now())) return true;
|
| 46 |
+
return p.c ? checkOnline(p.c) : false;
|
| 47 |
+
});
|
| 48 |
+
}
|
| 49 |
+
|
| 50 |
+
function checkOnline(code) {
|
| 51 |
return fetch(DATA + "/unlock/" + encodeURIComponent(C.id) + "?json=1&session_id=" + encodeURIComponent(code))
|
| 52 |
.then(function (r) { return r.json(); })
|
| 53 |
.then(function (j) { return j && typeof j.pro === "boolean" ? j.pro : null; })
|
|
|
|
| 177 |
|
| 178 |
window.CMXPro = { isPro: isPro, onChange: function (fn) { listeners.push(fn); fn(isPro()); }, upsell: upsell, quota: quota, download: download, toast: toast };
|
| 179 |
|
| 180 |
+
var m = /[#&]cmx-key=([^&]+)/.exec(location.hash || "") || /[#&]cmx-pro=([^&]+)/.exec(location.hash || "");
|
| 181 |
function start() {
|
| 182 |
if (m && SID.test(decodeURIComponent(m[1]))) {
|
| 183 |
var code = decodeURIComponent(m[1]);
|
|
|
|
| 187 |
}
|
| 188 |
if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", start); else start();
|
| 189 |
})();
|
| 190 |
+
|
| 191 |
+
/* Direct checkout (17 Oct 2026, Workers cap fix): a click on a data.cybermaxtools.com/buy/<offer> link goes straight to
|
| 192 |
+
the Stripe/Polar checkout (map: https://cybermaxtools.com/store/buy-direct.json, a static file) and the click is counted
|
| 193 |
+
by a background beacon. Without the map the link works as before. */
|
| 194 |
+
(function () {
|
| 195 |
+
var MAP = null, U = "https://cybermaxtools.com/store/buy-direct.json";
|
| 196 |
+
try { MAP = JSON.parse(sessionStorage.getItem("cmx-bd") || "null"); } catch (e) { /* none */ }
|
| 197 |
+
if (!MAP && window.fetch) fetch(U).then(function (r) { return r.json(); }).then(function (j) { MAP = j; try { sessionStorage.setItem("cmx-bd", JSON.stringify(j)); } catch (e) { /* full */ } }).catch(function () {});
|
| 198 |
+
document.addEventListener("click", function (e) {
|
| 199 |
+
var a = e.target && e.target.closest && e.target.closest('a[href*="data.cybermaxtools.com/buy/"]');
|
| 200 |
+
if (!a || !MAP || !MAP.offers) return;
|
| 201 |
+
try {
|
| 202 |
+
var u = new URL(a.href), k = /^\/buy\/([a-z0-9-]+)\/?$/.exec(u.pathname), t = k && MAP.offers[k[1]];
|
| 203 |
+
if (!t) return;
|
| 204 |
+
var s = String(u.searchParams.get("s") || "unknown").toLowerCase().replace(/[^a-z0-9-]/g, "").slice(0, 80) || "unknown";
|
| 205 |
+
a.href = t.split(MAP.ph).join(s);
|
| 206 |
+
if (!navigator.webdriver) navigator.sendBeacon(u.href + (u.search ? "&" : "?") + "b=1");
|
| 207 |
+
} catch (x) { /* keep the counted link */ }
|
| 208 |
+
}, true);
|
| 209 |
+
})();
|
salary-to-hourly-calculator/pro.js
CHANGED
|
@@ -11,7 +11,7 @@
|
|
| 11 |
if (!C.id) return;
|
| 12 |
var DATA = "https://data.cybermaxtools.com";
|
| 13 |
var KEY = "cmx-pro:" + C.id;
|
| 14 |
-
var SID = /^(cs_(live|test)_[A-Za-z0-9]{10,200}|[A-Z0-9]{8}-[A-Z0-9]{8}-[A-Z0-9]{8}-[A-Z0-9]{8})$/i; // Stripe order code or Gumroad licence key
|
| 15 |
var listeners = [];
|
| 16 |
|
| 17 |
function get() { try { return JSON.parse(localStorage.getItem(KEY) || "null"); } catch (e) { return null; } }
|
|
@@ -19,7 +19,30 @@
|
|
| 19 |
var mem = get();
|
| 20 |
function isPro() { return !!(mem && mem.code); }
|
| 21 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 22 |
function check(code) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 23 |
return fetch(DATA + "/unlock/" + encodeURIComponent(C.id) + "?json=1&session_id=" + encodeURIComponent(code))
|
| 24 |
.then(function (r) { return r.json(); }).then(function (j) { return !!(j && j.pro); }).catch(function () { return null; });
|
| 25 |
}
|
|
@@ -99,10 +122,30 @@
|
|
| 99 |
|
| 100 |
window.CMXPro = { isPro: isPro, onChange: function (fn) { listeners.push(fn); fn(isPro()); }, download: download, csv: csv, markdown: markdown, rows: rows, toast: toast };
|
| 101 |
|
| 102 |
-
var m = /[#&]cmx-pro=([^&]+)/.exec(location.hash || "");
|
| 103 |
if (m && SID.test(decodeURIComponent(m[1]))) {
|
| 104 |
var code = decodeURIComponent(m[1]);
|
| 105 |
history.replaceState(null, "", location.pathname + location.search);
|
| 106 |
if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", function () { apply(); unlock(code); }); else { apply(); unlock(code); }
|
| 107 |
} else if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", apply); else apply();
|
| 108 |
})();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 11 |
if (!C.id) return;
|
| 12 |
var DATA = "https://data.cybermaxtools.com";
|
| 13 |
var KEY = "cmx-pro:" + C.id;
|
| 14 |
+
var SID = /^(cmxk1\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+|cs_(live|test)_[A-Za-z0-9]{10,200}|[A-Z0-9]{8}-[A-Z0-9]{8}-[A-Z0-9]{8}-[A-Z0-9]{8})$/i; // Stripe order code or Gumroad licence key
|
| 15 |
var listeners = [];
|
| 16 |
|
| 17 |
function get() { try { return JSON.parse(localStorage.getItem(KEY) || "null"); } catch (e) { return null; } }
|
|
|
|
| 19 |
var mem = get();
|
| 20 |
function isPro() { return !!(mem && mem.code); }
|
| 21 |
|
| 22 |
+
// Offline Pro keys (17 Oct 2026): "cmxk1.<payload>.<Ed25519 signature>" from data.cybermaxtools.com/unlock is verified
|
| 23 |
+
// here with WebCrypto and the public key below, so unlocking needs no Worker call. Expired, foreign-signed or unverifiable
|
| 24 |
+
// (no Ed25519 in this browser) keys fall back to the online check of the order code inside them, as before.
|
| 25 |
+
var CMX_PUB = "u0FDxbu0d9B9Sz5-yLT6AuL5IagyTlFcbBgEDqZxWtk";
|
| 26 |
+
function b64d(s) { s = s.replace(/-/g, "+").replace(/_/g, "/"); while (s.length % 4) s += "="; var b = atob(s), u = new Uint8Array(b.length); for (var i = 0; i < b.length; i++) u[i] = b.charCodeAt(i); return u; }
|
| 27 |
+
function cmxVerify(k) {
|
| 28 |
+
var parts = k.split("."), p = null;
|
| 29 |
+
try { p = JSON.parse(new TextDecoder().decode(b64d(parts[1]))); } catch (e) { return Promise.resolve({ p: null, ok: false }); }
|
| 30 |
+
if (!(window.crypto && crypto.subtle)) return Promise.resolve({ p: p, ok: null });
|
| 31 |
+
return crypto.subtle.importKey("raw", b64d(CMX_PUB), { name: "Ed25519" }, false, ["verify"])
|
| 32 |
+
.then(function (key) { return crypto.subtle.verify({ name: "Ed25519" }, key, b64d(parts[2]), new TextEncoder().encode(parts[0] + "." + parts[1])); })
|
| 33 |
+
.then(function (ok) { return { p: p, ok: !!ok }; }, function () { return { p: p, ok: null }; });
|
| 34 |
+
}
|
| 35 |
function check(code) {
|
| 36 |
+
if (!/^cmxk1\./.test(code)) return checkOnline(code);
|
| 37 |
+
return cmxVerify(code).then(function (r) {
|
| 38 |
+
var p = r.p;
|
| 39 |
+
if (!p || p.a !== C.id) return false;
|
| 40 |
+
if (r.ok && (!p.x || p.x * 1000 > Date.now())) return true;
|
| 41 |
+
return p.c ? checkOnline(p.c) : false;
|
| 42 |
+
});
|
| 43 |
+
}
|
| 44 |
+
|
| 45 |
+
function checkOnline(code) {
|
| 46 |
return fetch(DATA + "/unlock/" + encodeURIComponent(C.id) + "?json=1&session_id=" + encodeURIComponent(code))
|
| 47 |
.then(function (r) { return r.json(); }).then(function (j) { return !!(j && j.pro); }).catch(function () { return null; });
|
| 48 |
}
|
|
|
|
| 122 |
|
| 123 |
window.CMXPro = { isPro: isPro, onChange: function (fn) { listeners.push(fn); fn(isPro()); }, download: download, csv: csv, markdown: markdown, rows: rows, toast: toast };
|
| 124 |
|
| 125 |
+
var m = /[#&]cmx-key=([^&]+)/.exec(location.hash || "") || /[#&]cmx-pro=([^&]+)/.exec(location.hash || "");
|
| 126 |
if (m && SID.test(decodeURIComponent(m[1]))) {
|
| 127 |
var code = decodeURIComponent(m[1]);
|
| 128 |
history.replaceState(null, "", location.pathname + location.search);
|
| 129 |
if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", function () { apply(); unlock(code); }); else { apply(); unlock(code); }
|
| 130 |
} else if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", apply); else apply();
|
| 131 |
})();
|
| 132 |
+
|
| 133 |
+
/* Direct checkout (17 Oct 2026, Workers cap fix): a click on a data.cybermaxtools.com/buy/<offer> link goes straight to
|
| 134 |
+
the Stripe/Polar checkout (map: https://cybermaxtools.com/store/buy-direct.json, a static file) and the click is counted
|
| 135 |
+
by a background beacon. Without the map the link works as before. */
|
| 136 |
+
(function () {
|
| 137 |
+
var MAP = null, U = "https://cybermaxtools.com/store/buy-direct.json";
|
| 138 |
+
try { MAP = JSON.parse(sessionStorage.getItem("cmx-bd") || "null"); } catch (e) { /* none */ }
|
| 139 |
+
if (!MAP && window.fetch) fetch(U).then(function (r) { return r.json(); }).then(function (j) { MAP = j; try { sessionStorage.setItem("cmx-bd", JSON.stringify(j)); } catch (e) { /* full */ } }).catch(function () {});
|
| 140 |
+
document.addEventListener("click", function (e) {
|
| 141 |
+
var a = e.target && e.target.closest && e.target.closest('a[href*="data.cybermaxtools.com/buy/"]');
|
| 142 |
+
if (!a || !MAP || !MAP.offers) return;
|
| 143 |
+
try {
|
| 144 |
+
var u = new URL(a.href), k = /^\/buy\/([a-z0-9-]+)\/?$/.exec(u.pathname), t = k && MAP.offers[k[1]];
|
| 145 |
+
if (!t) return;
|
| 146 |
+
var s = String(u.searchParams.get("s") || "unknown").toLowerCase().replace(/[^a-z0-9-]/g, "").slice(0, 80) || "unknown";
|
| 147 |
+
a.href = t.split(MAP.ph).join(s);
|
| 148 |
+
if (!navigator.webdriver) navigator.sendBeacon(u.href + (u.search ? "&" : "?") + "b=1");
|
| 149 |
+
} catch (x) { /* keep the counted link */ }
|
| 150 |
+
}, true);
|
| 151 |
+
})();
|
sigsprig/pro.js
CHANGED
|
@@ -15,7 +15,7 @@
|
|
| 15 |
if (!C.id) return;
|
| 16 |
var DATA = "https://data.cybermaxtools.com";
|
| 17 |
var KEY = "cmx-pro:" + C.id;
|
| 18 |
-
var SID = /^(cs_(live|test)_[A-Za-z0-9]{10,200}|[A-Z0-9]{8}-[A-Z0-9]{8}-[A-Z0-9]{8}-[A-Z0-9]{8})$/i; // Stripe order code or Gumroad licence key
|
| 19 |
var RECHECK = 3 * 864e5;
|
| 20 |
var listeners = [];
|
| 21 |
|
|
@@ -24,7 +24,30 @@
|
|
| 24 |
var mem = get();
|
| 25 |
function isPro() { return !!(mem && mem.code); }
|
| 26 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 27 |
function check(code) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 28 |
return fetch(DATA + "/unlock/" + encodeURIComponent(C.id) + "?json=1&session_id=" + encodeURIComponent(code))
|
| 29 |
.then(function (r) { return r.json(); })
|
| 30 |
.then(function (j) { return j && typeof j.pro === "boolean" ? j.pro : null; })
|
|
@@ -152,7 +175,7 @@
|
|
| 152 |
|
| 153 |
window.CMXPro = { isPro: isPro, onChange: function (fn) { listeners.push(fn); fn(isPro()); }, upsell: upsell, quota: quota, download: download, toast: toast };
|
| 154 |
|
| 155 |
-
var m = /[#&]cmx-pro=([^&]+)/.exec(location.hash || "");
|
| 156 |
function start() {
|
| 157 |
if (m && SID.test(decodeURIComponent(m[1]))) {
|
| 158 |
var code = decodeURIComponent(m[1]);
|
|
@@ -162,3 +185,23 @@
|
|
| 162 |
}
|
| 163 |
if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", start); else start();
|
| 164 |
})();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 15 |
if (!C.id) return;
|
| 16 |
var DATA = "https://data.cybermaxtools.com";
|
| 17 |
var KEY = "cmx-pro:" + C.id;
|
| 18 |
+
var SID = /^(cmxk1\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+|cs_(live|test)_[A-Za-z0-9]{10,200}|[A-Z0-9]{8}-[A-Z0-9]{8}-[A-Z0-9]{8}-[A-Z0-9]{8})$/i; // Stripe order code or Gumroad licence key
|
| 19 |
var RECHECK = 3 * 864e5;
|
| 20 |
var listeners = [];
|
| 21 |
|
|
|
|
| 24 |
var mem = get();
|
| 25 |
function isPro() { return !!(mem && mem.code); }
|
| 26 |
|
| 27 |
+
// Offline Pro keys (17 Oct 2026): "cmxk1.<payload>.<Ed25519 signature>" from data.cybermaxtools.com/unlock is verified
|
| 28 |
+
// here with WebCrypto and the public key below, so unlocking needs no Worker call. Expired, foreign-signed or unverifiable
|
| 29 |
+
// (no Ed25519 in this browser) keys fall back to the online check of the order code inside them, as before.
|
| 30 |
+
var CMX_PUB = "u0FDxbu0d9B9Sz5-yLT6AuL5IagyTlFcbBgEDqZxWtk";
|
| 31 |
+
function b64d(s) { s = s.replace(/-/g, "+").replace(/_/g, "/"); while (s.length % 4) s += "="; var b = atob(s), u = new Uint8Array(b.length); for (var i = 0; i < b.length; i++) u[i] = b.charCodeAt(i); return u; }
|
| 32 |
+
function cmxVerify(k) {
|
| 33 |
+
var parts = k.split("."), p = null;
|
| 34 |
+
try { p = JSON.parse(new TextDecoder().decode(b64d(parts[1]))); } catch (e) { return Promise.resolve({ p: null, ok: false }); }
|
| 35 |
+
if (!(window.crypto && crypto.subtle)) return Promise.resolve({ p: p, ok: null });
|
| 36 |
+
return crypto.subtle.importKey("raw", b64d(CMX_PUB), { name: "Ed25519" }, false, ["verify"])
|
| 37 |
+
.then(function (key) { return crypto.subtle.verify({ name: "Ed25519" }, key, b64d(parts[2]), new TextEncoder().encode(parts[0] + "." + parts[1])); })
|
| 38 |
+
.then(function (ok) { return { p: p, ok: !!ok }; }, function () { return { p: p, ok: null }; });
|
| 39 |
+
}
|
| 40 |
function check(code) {
|
| 41 |
+
if (!/^cmxk1\./.test(code)) return checkOnline(code);
|
| 42 |
+
return cmxVerify(code).then(function (r) {
|
| 43 |
+
var p = r.p;
|
| 44 |
+
if (!p || p.a !== C.id) return false;
|
| 45 |
+
if (r.ok && (!p.x || p.x * 1000 > Date.now())) return true;
|
| 46 |
+
return p.c ? checkOnline(p.c) : false;
|
| 47 |
+
});
|
| 48 |
+
}
|
| 49 |
+
|
| 50 |
+
function checkOnline(code) {
|
| 51 |
return fetch(DATA + "/unlock/" + encodeURIComponent(C.id) + "?json=1&session_id=" + encodeURIComponent(code))
|
| 52 |
.then(function (r) { return r.json(); })
|
| 53 |
.then(function (j) { return j && typeof j.pro === "boolean" ? j.pro : null; })
|
|
|
|
| 175 |
|
| 176 |
window.CMXPro = { isPro: isPro, onChange: function (fn) { listeners.push(fn); fn(isPro()); }, upsell: upsell, quota: quota, download: download, toast: toast };
|
| 177 |
|
| 178 |
+
var m = /[#&]cmx-key=([^&]+)/.exec(location.hash || "") || /[#&]cmx-pro=([^&]+)/.exec(location.hash || "");
|
| 179 |
function start() {
|
| 180 |
if (m && SID.test(decodeURIComponent(m[1]))) {
|
| 181 |
var code = decodeURIComponent(m[1]);
|
|
|
|
| 185 |
}
|
| 186 |
if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", start); else start();
|
| 187 |
})();
|
| 188 |
+
|
| 189 |
+
/* Direct checkout (17 Oct 2026, Workers cap fix): a click on a data.cybermaxtools.com/buy/<offer> link goes straight to
|
| 190 |
+
the Stripe/Polar checkout (map: https://cybermaxtools.com/store/buy-direct.json, a static file) and the click is counted
|
| 191 |
+
by a background beacon. Without the map the link works as before. */
|
| 192 |
+
(function () {
|
| 193 |
+
var MAP = null, U = "https://cybermaxtools.com/store/buy-direct.json";
|
| 194 |
+
try { MAP = JSON.parse(sessionStorage.getItem("cmx-bd") || "null"); } catch (e) { /* none */ }
|
| 195 |
+
if (!MAP && window.fetch) fetch(U).then(function (r) { return r.json(); }).then(function (j) { MAP = j; try { sessionStorage.setItem("cmx-bd", JSON.stringify(j)); } catch (e) { /* full */ } }).catch(function () {});
|
| 196 |
+
document.addEventListener("click", function (e) {
|
| 197 |
+
var a = e.target && e.target.closest && e.target.closest('a[href*="data.cybermaxtools.com/buy/"]');
|
| 198 |
+
if (!a || !MAP || !MAP.offers) return;
|
| 199 |
+
try {
|
| 200 |
+
var u = new URL(a.href), k = /^\/buy\/([a-z0-9-]+)\/?$/.exec(u.pathname), t = k && MAP.offers[k[1]];
|
| 201 |
+
if (!t) return;
|
| 202 |
+
var s = String(u.searchParams.get("s") || "unknown").toLowerCase().replace(/[^a-z0-9-]/g, "").slice(0, 80) || "unknown";
|
| 203 |
+
a.href = t.split(MAP.ph).join(s);
|
| 204 |
+
if (!navigator.webdriver) navigator.sendBeacon(u.href + (u.search ? "&" : "?") + "b=1");
|
| 205 |
+
} catch (x) { /* keep the counted link */ }
|
| 206 |
+
}, true);
|
| 207 |
+
})();
|
stampsprig/pro.js
CHANGED
|
@@ -2,8 +2,8 @@
|
|
| 2 |
* self-contained). Extends pro.js with several plans (monthly, yearly, one-time) and a re-check for subscriptions.
|
| 3 |
* Config before this script:
|
| 4 |
* window.CMX_PRO = { id, name, perks: [..], plans: [{ offer, label, price, per, note, best }], free: "one line" }
|
| 5 |
-
* Buy: counted link https://data.
|
| 6 |
-
* After checkout Stripe sends the buyer to data.
|
| 7 |
* Checkout Session (and, for a subscription, that it is still active) and returns here with #cmx-pro=<session id>.
|
| 8 |
* The app checks that code once (/unlock/<id>?json=1&session_id=..) and remembers Pro in this browser; it re-checks every
|
| 9 |
* 3 days, so a cancelled subscription turns off by itself (one tiny request per buyer every 3 days, none for free users).
|
|
@@ -13,9 +13,9 @@
|
|
| 13 |
"use strict";
|
| 14 |
var C = window.CMX_PRO || {};
|
| 15 |
if (!C.id) return;
|
| 16 |
-
var DATA = "https://data.
|
| 17 |
var KEY = "cmx-pro:" + C.id;
|
| 18 |
-
var SID = /^cs_(live|test)_[A-Za-z0-9]{10,200}$/;
|
| 19 |
var RECHECK = 3 * 864e5;
|
| 20 |
var listeners = [];
|
| 21 |
|
|
@@ -24,7 +24,30 @@
|
|
| 24 |
var mem = get();
|
| 25 |
function isPro() { return !!(mem && mem.code); }
|
| 26 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 27 |
function check(code) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 28 |
return fetch(DATA + "/unlock/" + encodeURIComponent(C.id) + "?json=1&session_id=" + encodeURIComponent(code))
|
| 29 |
.then(function (r) { return r.json(); })
|
| 30 |
.then(function (j) { return j && typeof j.pro === "boolean" ? j.pro : null; })
|
|
@@ -58,6 +81,18 @@
|
|
| 58 |
function esc(s) { return String(s).replace(/[&<>"]/g, function (c) { return { "&": "&", "<": "<", ">": ">", '"': """ }[c]; }); }
|
| 59 |
function buyUrl(offer, from) { return DATA + "/buy/" + offer + "?s=app-" + C.id + (from ? "-" + from : ""); }
|
| 60 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 61 |
function box() {
|
| 62 |
var el = document.getElementById("cmx-pro");
|
| 63 |
if (!el) {
|
|
@@ -86,10 +121,16 @@
|
|
| 86 |
}).join("");
|
| 87 |
el.innerHTML = '<h2>' + esc(C.name) + ' Pro</h2>' + (C.free ? '<p class="cmx-pro-small">Free: ' + esc(C.free) + "</p>" : "") +
|
| 88 |
"<ul>" + C.perks.map(function (p) { return "<li>" + esc(p) + "</li>"; }).join("") + '</ul><div class="cmx-plans">' + plans +
|
| 89 |
-
'</div><p class="cmx-pro-small">Secure Stripe checkout. Pro turns on the moment you pay; no account needed.' + (subs ? " Subscriptions cancel any time." : " One payment, no subscription.") +
|
| 90 |
-
'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 91 |
var f = document.getElementById("cmx-pro-form");
|
| 92 |
-
if (f) f.onsubmit = function (e) { e.preventDefault(); var c = (document.getElementById("cmx-pro-code").value || "").trim(); if (SID.test(c)) unlock(c); else toast("Paste the code from your receipt page (it starts with cs_live_)."); };
|
| 93 |
}
|
| 94 |
|
| 95 |
function apply() {
|
|
@@ -103,6 +144,12 @@
|
|
| 103 |
var el = box();
|
| 104 |
if (from) Array.prototype.forEach.call(el.querySelectorAll("a.cmx-plan"), function (a) { a.href = buyUrl(a.getAttribute("data-offer"), from); });
|
| 105 |
if (reason) toast(reason);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 106 |
el.scrollIntoView({ behavior: "smooth", block: "start" });
|
| 107 |
el.classList.add("cmx-pro-flash"); setTimeout(function () { el.classList.remove("cmx-pro-flash"); }, 1600);
|
| 108 |
}
|
|
@@ -128,7 +175,7 @@
|
|
| 128 |
|
| 129 |
window.CMXPro = { isPro: isPro, onChange: function (fn) { listeners.push(fn); fn(isPro()); }, upsell: upsell, quota: quota, download: download, toast: toast };
|
| 130 |
|
| 131 |
-
var m = /[#&]cmx-pro=([^&]+)/.exec(location.hash || "");
|
| 132 |
function start() {
|
| 133 |
if (m && SID.test(decodeURIComponent(m[1]))) {
|
| 134 |
var code = decodeURIComponent(m[1]);
|
|
@@ -138,3 +185,23 @@
|
|
| 138 |
}
|
| 139 |
if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", start); else start();
|
| 140 |
})();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2 |
* self-contained). Extends pro.js with several plans (monthly, yearly, one-time) and a re-check for subscriptions.
|
| 3 |
* Config before this script:
|
| 4 |
* window.CMX_PRO = { id, name, perks: [..], plans: [{ offer, label, price, per, note, best }], free: "one line" }
|
| 5 |
+
* Buy: counted link https://data.cybermaxtools.com/buy/<offer>?s=app-<id> -> Stripe Payment Link.
|
| 6 |
+
* After checkout Stripe sends the buyer to data.cybermaxtools.com/unlock/<id>?session_id=..., which checks the
|
| 7 |
* Checkout Session (and, for a subscription, that it is still active) and returns here with #cmx-pro=<session id>.
|
| 8 |
* The app checks that code once (/unlock/<id>?json=1&session_id=..) and remembers Pro in this browser; it re-checks every
|
| 9 |
* 3 days, so a cancelled subscription turns off by itself (one tiny request per buyer every 3 days, none for free users).
|
|
|
|
| 13 |
"use strict";
|
| 14 |
var C = window.CMX_PRO || {};
|
| 15 |
if (!C.id) return;
|
| 16 |
+
var DATA = "https://data.cybermaxtools.com";
|
| 17 |
var KEY = "cmx-pro:" + C.id;
|
| 18 |
+
var SID = /^(cmxk1\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+|cs_(live|test)_[A-Za-z0-9]{10,200}|[A-Z0-9]{8}-[A-Z0-9]{8}-[A-Z0-9]{8}-[A-Z0-9]{8})$/i; // Stripe order code or Gumroad licence key
|
| 19 |
var RECHECK = 3 * 864e5;
|
| 20 |
var listeners = [];
|
| 21 |
|
|
|
|
| 24 |
var mem = get();
|
| 25 |
function isPro() { return !!(mem && mem.code); }
|
| 26 |
|
| 27 |
+
// Offline Pro keys (17 Oct 2026): "cmxk1.<payload>.<Ed25519 signature>" from data.cybermaxtools.com/unlock is verified
|
| 28 |
+
// here with WebCrypto and the public key below, so unlocking needs no Worker call. Expired, foreign-signed or unverifiable
|
| 29 |
+
// (no Ed25519 in this browser) keys fall back to the online check of the order code inside them, as before.
|
| 30 |
+
var CMX_PUB = "u0FDxbu0d9B9Sz5-yLT6AuL5IagyTlFcbBgEDqZxWtk";
|
| 31 |
+
function b64d(s) { s = s.replace(/-/g, "+").replace(/_/g, "/"); while (s.length % 4) s += "="; var b = atob(s), u = new Uint8Array(b.length); for (var i = 0; i < b.length; i++) u[i] = b.charCodeAt(i); return u; }
|
| 32 |
+
function cmxVerify(k) {
|
| 33 |
+
var parts = k.split("."), p = null;
|
| 34 |
+
try { p = JSON.parse(new TextDecoder().decode(b64d(parts[1]))); } catch (e) { return Promise.resolve({ p: null, ok: false }); }
|
| 35 |
+
if (!(window.crypto && crypto.subtle)) return Promise.resolve({ p: p, ok: null });
|
| 36 |
+
return crypto.subtle.importKey("raw", b64d(CMX_PUB), { name: "Ed25519" }, false, ["verify"])
|
| 37 |
+
.then(function (key) { return crypto.subtle.verify({ name: "Ed25519" }, key, b64d(parts[2]), new TextEncoder().encode(parts[0] + "." + parts[1])); })
|
| 38 |
+
.then(function (ok) { return { p: p, ok: !!ok }; }, function () { return { p: p, ok: null }; });
|
| 39 |
+
}
|
| 40 |
function check(code) {
|
| 41 |
+
if (!/^cmxk1\./.test(code)) return checkOnline(code);
|
| 42 |
+
return cmxVerify(code).then(function (r) {
|
| 43 |
+
var p = r.p;
|
| 44 |
+
if (!p || p.a !== C.id) return false;
|
| 45 |
+
if (r.ok && (!p.x || p.x * 1000 > Date.now())) return true;
|
| 46 |
+
return p.c ? checkOnline(p.c) : false;
|
| 47 |
+
});
|
| 48 |
+
}
|
| 49 |
+
|
| 50 |
+
function checkOnline(code) {
|
| 51 |
return fetch(DATA + "/unlock/" + encodeURIComponent(C.id) + "?json=1&session_id=" + encodeURIComponent(code))
|
| 52 |
.then(function (r) { return r.json(); })
|
| 53 |
.then(function (j) { return j && typeof j.pro === "boolean" ? j.pro : null; })
|
|
|
|
| 81 |
function esc(s) { return String(s).replace(/[&<>"]/g, function (c) { return { "&": "&", "<": "<", ">": ">", '"': """ }[c]; }); }
|
| 82 |
function buyUrl(offer, from) { return DATA + "/buy/" + offer + "?s=app-" + C.id + (from ? "-" + from : ""); }
|
| 83 |
|
| 84 |
+
// Convert kit (funnel beacons, real proof, email capture, phone buy bar), loaded from the CyberMax Store; optional:
|
| 85 |
+
// if it can't load (offline), the app and the Pro box work exactly the same.
|
| 86 |
+
var KIT = "https://cybermaxtools.com/store/convert.js", kitQ = [];
|
| 87 |
+
function conv(fn) {
|
| 88 |
+
if (window.CMXConvert) return fn(window.CMXConvert);
|
| 89 |
+
kitQ.push(fn);
|
| 90 |
+
if (kitQ.length > 1 || !navigator.onLine) return;
|
| 91 |
+
var sc = document.createElement("script"); sc.src = KIT; sc.async = true;
|
| 92 |
+
sc.onload = function () { var q = kitQ.splice(0); q.forEach(function (f) { try { f(window.CMXConvert); } catch (e) { /* */ } }); };
|
| 93 |
+
document.head.appendChild(sc);
|
| 94 |
+
}
|
| 95 |
+
|
| 96 |
function box() {
|
| 97 |
var el = document.getElementById("cmx-pro");
|
| 98 |
if (!el) {
|
|
|
|
| 121 |
}).join("");
|
| 122 |
el.innerHTML = '<h2>' + esc(C.name) + ' Pro</h2>' + (C.free ? '<p class="cmx-pro-small">Free: ' + esc(C.free) + "</p>" : "") +
|
| 123 |
"<ul>" + C.perks.map(function (p) { return "<li>" + esc(p) + "</li>"; }).join("") + '</ul><div class="cmx-plans">' + plans +
|
| 124 |
+
'</div><p class="cmx-pro-small">Secure Stripe checkout. Pro turns on the moment you pay; no account needed.' + (subs ? " Subscriptions cancel any time from your receipt email." : " One payment, no subscription.") +
|
| 125 |
+
' 14-day promise: if it doesn\'t work as described, we fix it or refund you in full (<a href="https://cybermaxtools.com/terms#payments" target="_blank" rel="noopener">terms</a>). Questions: <a href="mailto:cybermax.tools@gmail.com">cybermax.tools@gmail.com</a></p><div class="cmx-pro-proof"></div><div class="cmx-pro-cap"></div>' +
|
| 126 |
+
'<details><summary>Already bought Pro?</summary><form id="cmx-pro-form"><label>Unlock code <input id="cmx-pro-code" autocomplete="off" placeholder="cs_live_… or Gumroad licence key"></label> <button class="btn ghost" type="submit">Unlock</button></form></details><p id="cmx-pro-msg" class="cmx-pro-small" aria-live="polite"></p>';
|
| 127 |
+
Array.prototype.forEach.call(el.querySelectorAll("a.cmx-plan"), function (a) { a.addEventListener("click", function () { conv(function (K) { K.event("upgrade-click", C.id); }); }); });
|
| 128 |
+
conv(function (K) {
|
| 129 |
+
K.proof(el.querySelector(".cmx-pro-proof"), C.id);
|
| 130 |
+
K.capture(el.querySelector(".cmx-pro-cap"), { list: "weekly-" + C.id, src: "app-" + C.id, label: "Not ready for Pro? Email me " + C.name + " tips and new features (about once a week)" });
|
| 131 |
+
});
|
| 132 |
var f = document.getElementById("cmx-pro-form");
|
| 133 |
+
if (f) f.onsubmit = function (e) { e.preventDefault(); var c = (document.getElementById("cmx-pro-code").value || "").trim(); if (SID.test(c)) unlock(c); else toast("Paste the code from your receipt page (it starts with cs_live_) or your Gumroad licence key."); };
|
| 134 |
}
|
| 135 |
|
| 136 |
function apply() {
|
|
|
|
| 144 |
var el = box();
|
| 145 |
if (from) Array.prototype.forEach.call(el.querySelectorAll("a.cmx-plan"), function (a) { a.href = buyUrl(a.getAttribute("data-offer"), from); });
|
| 146 |
if (reason) toast(reason);
|
| 147 |
+
// A real limit: count it, and on phones keep one buy button in reach (no timer; closes with one tap).
|
| 148 |
+
conv(function (K) {
|
| 149 |
+
K.event("limit", C.id); K.event("upgrade-view", C.id);
|
| 150 |
+
var best = (C.plans || []).filter(function (p) { return p.best; })[0] || (C.plans || [])[0];
|
| 151 |
+
if (best && !isPro()) K.sticky({ text: C.name + " Pro: " + best.price + (best.per || ""), cta: "Go Pro", href: buyUrl(best.offer, (from || "limit") + "-bar"), product: C.id });
|
| 152 |
+
});
|
| 153 |
el.scrollIntoView({ behavior: "smooth", block: "start" });
|
| 154 |
el.classList.add("cmx-pro-flash"); setTimeout(function () { el.classList.remove("cmx-pro-flash"); }, 1600);
|
| 155 |
}
|
|
|
|
| 175 |
|
| 176 |
window.CMXPro = { isPro: isPro, onChange: function (fn) { listeners.push(fn); fn(isPro()); }, upsell: upsell, quota: quota, download: download, toast: toast };
|
| 177 |
|
| 178 |
+
var m = /[#&]cmx-key=([^&]+)/.exec(location.hash || "") || /[#&]cmx-pro=([^&]+)/.exec(location.hash || "");
|
| 179 |
function start() {
|
| 180 |
if (m && SID.test(decodeURIComponent(m[1]))) {
|
| 181 |
var code = decodeURIComponent(m[1]);
|
|
|
|
| 185 |
}
|
| 186 |
if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", start); else start();
|
| 187 |
})();
|
| 188 |
+
|
| 189 |
+
/* Direct checkout (17 Oct 2026, Workers cap fix): a click on a data.cybermaxtools.com/buy/<offer> link goes straight to
|
| 190 |
+
the Stripe/Polar checkout (map: https://cybermaxtools.com/store/buy-direct.json, a static file) and the click is counted
|
| 191 |
+
by a background beacon. Without the map the link works as before. */
|
| 192 |
+
(function () {
|
| 193 |
+
var MAP = null, U = "https://cybermaxtools.com/store/buy-direct.json";
|
| 194 |
+
try { MAP = JSON.parse(sessionStorage.getItem("cmx-bd") || "null"); } catch (e) { /* none */ }
|
| 195 |
+
if (!MAP && window.fetch) fetch(U).then(function (r) { return r.json(); }).then(function (j) { MAP = j; try { sessionStorage.setItem("cmx-bd", JSON.stringify(j)); } catch (e) { /* full */ } }).catch(function () {});
|
| 196 |
+
document.addEventListener("click", function (e) {
|
| 197 |
+
var a = e.target && e.target.closest && e.target.closest('a[href*="data.cybermaxtools.com/buy/"]');
|
| 198 |
+
if (!a || !MAP || !MAP.offers) return;
|
| 199 |
+
try {
|
| 200 |
+
var u = new URL(a.href), k = /^\/buy\/([a-z0-9-]+)\/?$/.exec(u.pathname), t = k && MAP.offers[k[1]];
|
| 201 |
+
if (!t) return;
|
| 202 |
+
var s = String(u.searchParams.get("s") || "unknown").toLowerCase().replace(/[^a-z0-9-]/g, "").slice(0, 80) || "unknown";
|
| 203 |
+
a.href = t.split(MAP.ph).join(s);
|
| 204 |
+
if (!navigator.webdriver) navigator.sendBeacon(u.href + (u.search ? "&" : "?") + "b=1");
|
| 205 |
+
} catch (x) { /* keep the counted link */ }
|
| 206 |
+
}, true);
|
| 207 |
+
})();
|
tagwren/pro.js
CHANGED
|
@@ -15,7 +15,7 @@
|
|
| 15 |
if (!C.id) return;
|
| 16 |
var DATA = "https://data.cybermaxtools.com";
|
| 17 |
var KEY = "cmx-pro:" + C.id;
|
| 18 |
-
var SID = /^(cs_(live|test)_[A-Za-z0-9]{10,200}|[A-Z0-9]{8}-[A-Z0-9]{8}-[A-Z0-9]{8}-[A-Z0-9]{8})$/i; // Stripe order code or Gumroad licence key
|
| 19 |
var RECHECK = 3 * 864e5;
|
| 20 |
var listeners = [];
|
| 21 |
|
|
@@ -24,7 +24,30 @@
|
|
| 24 |
var mem = get();
|
| 25 |
function isPro() { return !!(mem && mem.code); }
|
| 26 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 27 |
function check(code) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 28 |
return fetch(DATA + "/unlock/" + encodeURIComponent(C.id) + "?json=1&session_id=" + encodeURIComponent(code))
|
| 29 |
.then(function (r) { return r.json(); })
|
| 30 |
.then(function (j) { return j && typeof j.pro === "boolean" ? j.pro : null; })
|
|
@@ -152,7 +175,7 @@
|
|
| 152 |
|
| 153 |
window.CMXPro = { isPro: isPro, onChange: function (fn) { listeners.push(fn); fn(isPro()); }, upsell: upsell, quota: quota, download: download, toast: toast };
|
| 154 |
|
| 155 |
-
var m = /[#&]cmx-pro=([^&]+)/.exec(location.hash || "");
|
| 156 |
function start() {
|
| 157 |
if (m && SID.test(decodeURIComponent(m[1]))) {
|
| 158 |
var code = decodeURIComponent(m[1]);
|
|
@@ -162,3 +185,23 @@
|
|
| 162 |
}
|
| 163 |
if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", start); else start();
|
| 164 |
})();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 15 |
if (!C.id) return;
|
| 16 |
var DATA = "https://data.cybermaxtools.com";
|
| 17 |
var KEY = "cmx-pro:" + C.id;
|
| 18 |
+
var SID = /^(cmxk1\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+|cs_(live|test)_[A-Za-z0-9]{10,200}|[A-Z0-9]{8}-[A-Z0-9]{8}-[A-Z0-9]{8}-[A-Z0-9]{8})$/i; // Stripe order code or Gumroad licence key
|
| 19 |
var RECHECK = 3 * 864e5;
|
| 20 |
var listeners = [];
|
| 21 |
|
|
|
|
| 24 |
var mem = get();
|
| 25 |
function isPro() { return !!(mem && mem.code); }
|
| 26 |
|
| 27 |
+
// Offline Pro keys (17 Oct 2026): "cmxk1.<payload>.<Ed25519 signature>" from data.cybermaxtools.com/unlock is verified
|
| 28 |
+
// here with WebCrypto and the public key below, so unlocking needs no Worker call. Expired, foreign-signed or unverifiable
|
| 29 |
+
// (no Ed25519 in this browser) keys fall back to the online check of the order code inside them, as before.
|
| 30 |
+
var CMX_PUB = "u0FDxbu0d9B9Sz5-yLT6AuL5IagyTlFcbBgEDqZxWtk";
|
| 31 |
+
function b64d(s) { s = s.replace(/-/g, "+").replace(/_/g, "/"); while (s.length % 4) s += "="; var b = atob(s), u = new Uint8Array(b.length); for (var i = 0; i < b.length; i++) u[i] = b.charCodeAt(i); return u; }
|
| 32 |
+
function cmxVerify(k) {
|
| 33 |
+
var parts = k.split("."), p = null;
|
| 34 |
+
try { p = JSON.parse(new TextDecoder().decode(b64d(parts[1]))); } catch (e) { return Promise.resolve({ p: null, ok: false }); }
|
| 35 |
+
if (!(window.crypto && crypto.subtle)) return Promise.resolve({ p: p, ok: null });
|
| 36 |
+
return crypto.subtle.importKey("raw", b64d(CMX_PUB), { name: "Ed25519" }, false, ["verify"])
|
| 37 |
+
.then(function (key) { return crypto.subtle.verify({ name: "Ed25519" }, key, b64d(parts[2]), new TextEncoder().encode(parts[0] + "." + parts[1])); })
|
| 38 |
+
.then(function (ok) { return { p: p, ok: !!ok }; }, function () { return { p: p, ok: null }; });
|
| 39 |
+
}
|
| 40 |
function check(code) {
|
| 41 |
+
if (!/^cmxk1\./.test(code)) return checkOnline(code);
|
| 42 |
+
return cmxVerify(code).then(function (r) {
|
| 43 |
+
var p = r.p;
|
| 44 |
+
if (!p || p.a !== C.id) return false;
|
| 45 |
+
if (r.ok && (!p.x || p.x * 1000 > Date.now())) return true;
|
| 46 |
+
return p.c ? checkOnline(p.c) : false;
|
| 47 |
+
});
|
| 48 |
+
}
|
| 49 |
+
|
| 50 |
+
function checkOnline(code) {
|
| 51 |
return fetch(DATA + "/unlock/" + encodeURIComponent(C.id) + "?json=1&session_id=" + encodeURIComponent(code))
|
| 52 |
.then(function (r) { return r.json(); })
|
| 53 |
.then(function (j) { return j && typeof j.pro === "boolean" ? j.pro : null; })
|
|
|
|
| 175 |
|
| 176 |
window.CMXPro = { isPro: isPro, onChange: function (fn) { listeners.push(fn); fn(isPro()); }, upsell: upsell, quota: quota, download: download, toast: toast };
|
| 177 |
|
| 178 |
+
var m = /[#&]cmx-key=([^&]+)/.exec(location.hash || "") || /[#&]cmx-pro=([^&]+)/.exec(location.hash || "");
|
| 179 |
function start() {
|
| 180 |
if (m && SID.test(decodeURIComponent(m[1]))) {
|
| 181 |
var code = decodeURIComponent(m[1]);
|
|
|
|
| 185 |
}
|
| 186 |
if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", start); else start();
|
| 187 |
})();
|
| 188 |
+
|
| 189 |
+
/* Direct checkout (17 Oct 2026, Workers cap fix): a click on a data.cybermaxtools.com/buy/<offer> link goes straight to
|
| 190 |
+
the Stripe/Polar checkout (map: https://cybermaxtools.com/store/buy-direct.json, a static file) and the click is counted
|
| 191 |
+
by a background beacon. Without the map the link works as before. */
|
| 192 |
+
(function () {
|
| 193 |
+
var MAP = null, U = "https://cybermaxtools.com/store/buy-direct.json";
|
| 194 |
+
try { MAP = JSON.parse(sessionStorage.getItem("cmx-bd") || "null"); } catch (e) { /* none */ }
|
| 195 |
+
if (!MAP && window.fetch) fetch(U).then(function (r) { return r.json(); }).then(function (j) { MAP = j; try { sessionStorage.setItem("cmx-bd", JSON.stringify(j)); } catch (e) { /* full */ } }).catch(function () {});
|
| 196 |
+
document.addEventListener("click", function (e) {
|
| 197 |
+
var a = e.target && e.target.closest && e.target.closest('a[href*="data.cybermaxtools.com/buy/"]');
|
| 198 |
+
if (!a || !MAP || !MAP.offers) return;
|
| 199 |
+
try {
|
| 200 |
+
var u = new URL(a.href), k = /^\/buy\/([a-z0-9-]+)\/?$/.exec(u.pathname), t = k && MAP.offers[k[1]];
|
| 201 |
+
if (!t) return;
|
| 202 |
+
var s = String(u.searchParams.get("s") || "unknown").toLowerCase().replace(/[^a-z0-9-]/g, "").slice(0, 80) || "unknown";
|
| 203 |
+
a.href = t.split(MAP.ph).join(s);
|
| 204 |
+
if (!navigator.webdriver) navigator.sendBeacon(u.href + (u.search ? "&" : "?") + "b=1");
|
| 205 |
+
} catch (x) { /* keep the counted link */ }
|
| 206 |
+
}, true);
|
| 207 |
+
})();
|
utm-builder/pro.js
CHANGED
|
@@ -11,7 +11,7 @@
|
|
| 11 |
if (!C.id) return;
|
| 12 |
var DATA = "https://data.cybermaxtools.com";
|
| 13 |
var KEY = "cmx-pro:" + C.id;
|
| 14 |
-
var SID = /^(cs_(live|test)_[A-Za-z0-9]{10,200}|[A-Z0-9]{8}-[A-Z0-9]{8}-[A-Z0-9]{8}-[A-Z0-9]{8})$/i; // Stripe order code or Gumroad licence key
|
| 15 |
var listeners = [];
|
| 16 |
|
| 17 |
function get() { try { return JSON.parse(localStorage.getItem(KEY) || "null"); } catch (e) { return null; } }
|
|
@@ -19,7 +19,30 @@
|
|
| 19 |
var mem = get();
|
| 20 |
function isPro() { return !!(mem && mem.code); }
|
| 21 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 22 |
function check(code) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 23 |
return fetch(DATA + "/unlock/" + encodeURIComponent(C.id) + "?json=1&session_id=" + encodeURIComponent(code))
|
| 24 |
.then(function (r) { return r.json(); }).then(function (j) { return !!(j && j.pro); }).catch(function () { return null; });
|
| 25 |
}
|
|
@@ -99,10 +122,30 @@
|
|
| 99 |
|
| 100 |
window.CMXPro = { isPro: isPro, onChange: function (fn) { listeners.push(fn); fn(isPro()); }, download: download, csv: csv, markdown: markdown, rows: rows, toast: toast };
|
| 101 |
|
| 102 |
-
var m = /[#&]cmx-pro=([^&]+)/.exec(location.hash || "");
|
| 103 |
if (m && SID.test(decodeURIComponent(m[1]))) {
|
| 104 |
var code = decodeURIComponent(m[1]);
|
| 105 |
history.replaceState(null, "", location.pathname + location.search);
|
| 106 |
if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", function () { apply(); unlock(code); }); else { apply(); unlock(code); }
|
| 107 |
} else if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", apply); else apply();
|
| 108 |
})();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 11 |
if (!C.id) return;
|
| 12 |
var DATA = "https://data.cybermaxtools.com";
|
| 13 |
var KEY = "cmx-pro:" + C.id;
|
| 14 |
+
var SID = /^(cmxk1\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+|cs_(live|test)_[A-Za-z0-9]{10,200}|[A-Z0-9]{8}-[A-Z0-9]{8}-[A-Z0-9]{8}-[A-Z0-9]{8})$/i; // Stripe order code or Gumroad licence key
|
| 15 |
var listeners = [];
|
| 16 |
|
| 17 |
function get() { try { return JSON.parse(localStorage.getItem(KEY) || "null"); } catch (e) { return null; } }
|
|
|
|
| 19 |
var mem = get();
|
| 20 |
function isPro() { return !!(mem && mem.code); }
|
| 21 |
|
| 22 |
+
// Offline Pro keys (17 Oct 2026): "cmxk1.<payload>.<Ed25519 signature>" from data.cybermaxtools.com/unlock is verified
|
| 23 |
+
// here with WebCrypto and the public key below, so unlocking needs no Worker call. Expired, foreign-signed or unverifiable
|
| 24 |
+
// (no Ed25519 in this browser) keys fall back to the online check of the order code inside them, as before.
|
| 25 |
+
var CMX_PUB = "u0FDxbu0d9B9Sz5-yLT6AuL5IagyTlFcbBgEDqZxWtk";
|
| 26 |
+
function b64d(s) { s = s.replace(/-/g, "+").replace(/_/g, "/"); while (s.length % 4) s += "="; var b = atob(s), u = new Uint8Array(b.length); for (var i = 0; i < b.length; i++) u[i] = b.charCodeAt(i); return u; }
|
| 27 |
+
function cmxVerify(k) {
|
| 28 |
+
var parts = k.split("."), p = null;
|
| 29 |
+
try { p = JSON.parse(new TextDecoder().decode(b64d(parts[1]))); } catch (e) { return Promise.resolve({ p: null, ok: false }); }
|
| 30 |
+
if (!(window.crypto && crypto.subtle)) return Promise.resolve({ p: p, ok: null });
|
| 31 |
+
return crypto.subtle.importKey("raw", b64d(CMX_PUB), { name: "Ed25519" }, false, ["verify"])
|
| 32 |
+
.then(function (key) { return crypto.subtle.verify({ name: "Ed25519" }, key, b64d(parts[2]), new TextEncoder().encode(parts[0] + "." + parts[1])); })
|
| 33 |
+
.then(function (ok) { return { p: p, ok: !!ok }; }, function () { return { p: p, ok: null }; });
|
| 34 |
+
}
|
| 35 |
function check(code) {
|
| 36 |
+
if (!/^cmxk1\./.test(code)) return checkOnline(code);
|
| 37 |
+
return cmxVerify(code).then(function (r) {
|
| 38 |
+
var p = r.p;
|
| 39 |
+
if (!p || p.a !== C.id) return false;
|
| 40 |
+
if (r.ok && (!p.x || p.x * 1000 > Date.now())) return true;
|
| 41 |
+
return p.c ? checkOnline(p.c) : false;
|
| 42 |
+
});
|
| 43 |
+
}
|
| 44 |
+
|
| 45 |
+
function checkOnline(code) {
|
| 46 |
return fetch(DATA + "/unlock/" + encodeURIComponent(C.id) + "?json=1&session_id=" + encodeURIComponent(code))
|
| 47 |
.then(function (r) { return r.json(); }).then(function (j) { return !!(j && j.pro); }).catch(function () { return null; });
|
| 48 |
}
|
|
|
|
| 122 |
|
| 123 |
window.CMXPro = { isPro: isPro, onChange: function (fn) { listeners.push(fn); fn(isPro()); }, download: download, csv: csv, markdown: markdown, rows: rows, toast: toast };
|
| 124 |
|
| 125 |
+
var m = /[#&]cmx-key=([^&]+)/.exec(location.hash || "") || /[#&]cmx-pro=([^&]+)/.exec(location.hash || "");
|
| 126 |
if (m && SID.test(decodeURIComponent(m[1]))) {
|
| 127 |
var code = decodeURIComponent(m[1]);
|
| 128 |
history.replaceState(null, "", location.pathname + location.search);
|
| 129 |
if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", function () { apply(); unlock(code); }); else { apply(); unlock(code); }
|
| 130 |
} else if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", apply); else apply();
|
| 131 |
})();
|
| 132 |
+
|
| 133 |
+
/* Direct checkout (17 Oct 2026, Workers cap fix): a click on a data.cybermaxtools.com/buy/<offer> link goes straight to
|
| 134 |
+
the Stripe/Polar checkout (map: https://cybermaxtools.com/store/buy-direct.json, a static file) and the click is counted
|
| 135 |
+
by a background beacon. Without the map the link works as before. */
|
| 136 |
+
(function () {
|
| 137 |
+
var MAP = null, U = "https://cybermaxtools.com/store/buy-direct.json";
|
| 138 |
+
try { MAP = JSON.parse(sessionStorage.getItem("cmx-bd") || "null"); } catch (e) { /* none */ }
|
| 139 |
+
if (!MAP && window.fetch) fetch(U).then(function (r) { return r.json(); }).then(function (j) { MAP = j; try { sessionStorage.setItem("cmx-bd", JSON.stringify(j)); } catch (e) { /* full */ } }).catch(function () {});
|
| 140 |
+
document.addEventListener("click", function (e) {
|
| 141 |
+
var a = e.target && e.target.closest && e.target.closest('a[href*="data.cybermaxtools.com/buy/"]');
|
| 142 |
+
if (!a || !MAP || !MAP.offers) return;
|
| 143 |
+
try {
|
| 144 |
+
var u = new URL(a.href), k = /^\/buy\/([a-z0-9-]+)\/?$/.exec(u.pathname), t = k && MAP.offers[k[1]];
|
| 145 |
+
if (!t) return;
|
| 146 |
+
var s = String(u.searchParams.get("s") || "unknown").toLowerCase().replace(/[^a-z0-9-]/g, "").slice(0, 80) || "unknown";
|
| 147 |
+
a.href = t.split(MAP.ph).join(s);
|
| 148 |
+
if (!navigator.webdriver) navigator.sendBeacon(u.href + (u.search ? "&" : "?") + "b=1");
|
| 149 |
+
} catch (x) { /* keep the counted link */ }
|
| 150 |
+
}, true);
|
| 151 |
+
})();
|