nodebb-plugin-pdf-secure 1.2.20 → 1.2.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/static/image.png +0 -0
- package/static/viewer.html +114 -78
package/package.json
CHANGED
package/static/image.png
ADDED
|
Binary file
|
package/static/viewer.html
CHANGED
|
@@ -1573,47 +1573,46 @@
|
|
|
1573
1573
|
}
|
|
1574
1574
|
}
|
|
1575
1575
|
|
|
1576
|
-
/*
|
|
1577
|
-
|
|
1576
|
+
/* Per-page lock overlay - her kilitli sayfa icin */
|
|
1577
|
+
.page-lock-overlay {
|
|
1578
|
+
position: absolute;
|
|
1579
|
+
top: 0; left: 0; right: 0; bottom: 0;
|
|
1578
1580
|
display: flex;
|
|
1579
1581
|
flex-direction: column;
|
|
1580
1582
|
align-items: center;
|
|
1581
1583
|
justify-content: center;
|
|
1582
|
-
padding: 60px 20px;
|
|
1583
|
-
text-align: center;
|
|
1584
1584
|
background: linear-gradient(180deg, rgba(31,31,31,0.95) 0%, rgba(20,20,20,0.98) 100%);
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
max-width: 100%;
|
|
1585
|
+
z-index: 5;
|
|
1586
|
+
text-align: center;
|
|
1587
|
+
padding: 20px;
|
|
1589
1588
|
}
|
|
1590
1589
|
|
|
1591
|
-
.
|
|
1592
|
-
margin-bottom:
|
|
1590
|
+
.page-lock-icon {
|
|
1591
|
+
margin-bottom: 16px;
|
|
1593
1592
|
opacity: 0.9;
|
|
1594
1593
|
}
|
|
1595
1594
|
|
|
1596
|
-
.
|
|
1597
|
-
font-size:
|
|
1595
|
+
.page-lock-title {
|
|
1596
|
+
font-size: 20px;
|
|
1598
1597
|
font-weight: 600;
|
|
1599
1598
|
color: #ffd700;
|
|
1600
|
-
margin-bottom:
|
|
1599
|
+
margin-bottom: 10px;
|
|
1601
1600
|
}
|
|
1602
1601
|
|
|
1603
|
-
.
|
|
1604
|
-
font-size:
|
|
1602
|
+
.page-lock-message {
|
|
1603
|
+
font-size: 14px;
|
|
1605
1604
|
color: #a0a0a0;
|
|
1606
|
-
margin-bottom:
|
|
1607
|
-
max-width:
|
|
1605
|
+
margin-bottom: 24px;
|
|
1606
|
+
max-width: 320px;
|
|
1608
1607
|
line-height: 1.5;
|
|
1609
1608
|
}
|
|
1610
1609
|
|
|
1611
|
-
.
|
|
1610
|
+
.page-lock-button {
|
|
1612
1611
|
display: inline-block;
|
|
1613
|
-
padding:
|
|
1612
|
+
padding: 12px 36px;
|
|
1614
1613
|
background: linear-gradient(135deg, #ffd700 0%, #ffaa00 100%);
|
|
1615
1614
|
color: #1a1a1a;
|
|
1616
|
-
font-size:
|
|
1615
|
+
font-size: 15px;
|
|
1617
1616
|
font-weight: 700;
|
|
1618
1617
|
border-radius: 8px;
|
|
1619
1618
|
text-decoration: none;
|
|
@@ -1621,22 +1620,29 @@
|
|
|
1621
1620
|
box-shadow: 0 4px 15px rgba(255, 215, 0, 0.3);
|
|
1622
1621
|
}
|
|
1623
1622
|
|
|
1624
|
-
.
|
|
1623
|
+
.page-lock-button:hover {
|
|
1625
1624
|
transform: translateY(-2px);
|
|
1626
1625
|
box-shadow: 0 6px 20px rgba(255, 215, 0, 0.4);
|
|
1627
1626
|
}
|
|
1628
1627
|
|
|
1629
|
-
.
|
|
1630
|
-
margin-top:
|
|
1631
|
-
font-size:
|
|
1628
|
+
.page-lock-secondary {
|
|
1629
|
+
margin-top: 16px;
|
|
1630
|
+
font-size: 13px;
|
|
1632
1631
|
color: #888;
|
|
1633
1632
|
font-style: italic;
|
|
1634
1633
|
}
|
|
1635
1634
|
|
|
1635
|
+
/* Blur locked page content - even if overlay removed, content unreadable */
|
|
1636
|
+
.page-locked-blur canvas,
|
|
1637
|
+
.page-locked-blur .textLayer,
|
|
1638
|
+
.page-locked-blur .annotationLayer {
|
|
1639
|
+
filter: blur(8px) !important;
|
|
1640
|
+
-webkit-filter: blur(8px) !important;
|
|
1641
|
+
}
|
|
1642
|
+
|
|
1636
1643
|
/* Locked Thumbnails */
|
|
1637
1644
|
.thumbnail.locked {
|
|
1638
|
-
opacity: 0.
|
|
1639
|
-
cursor: not-allowed;
|
|
1645
|
+
opacity: 0.5;
|
|
1640
1646
|
position: relative;
|
|
1641
1647
|
}
|
|
1642
1648
|
|
|
@@ -1654,22 +1660,17 @@
|
|
|
1654
1660
|
}
|
|
1655
1661
|
|
|
1656
1662
|
@media (max-width: 768px) {
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
min-height: 300px;
|
|
1660
|
-
}
|
|
1661
|
-
|
|
1662
|
-
.premium-lock-pages {
|
|
1663
|
-
font-size: 18px;
|
|
1663
|
+
.page-lock-title {
|
|
1664
|
+
font-size: 17px;
|
|
1664
1665
|
}
|
|
1665
1666
|
|
|
1666
|
-
.
|
|
1667
|
-
font-size:
|
|
1667
|
+
.page-lock-message {
|
|
1668
|
+
font-size: 13px;
|
|
1668
1669
|
}
|
|
1669
1670
|
|
|
1670
|
-
.
|
|
1671
|
-
padding:
|
|
1672
|
-
font-size:
|
|
1671
|
+
.page-lock-button {
|
|
1672
|
+
padding: 10px 28px;
|
|
1673
|
+
font-size: 13px;
|
|
1673
1674
|
}
|
|
1674
1675
|
}
|
|
1675
1676
|
</style>
|
|
@@ -2224,24 +2225,53 @@
|
|
|
2224
2225
|
return data.buffer;
|
|
2225
2226
|
}
|
|
2226
2227
|
|
|
2227
|
-
function
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2228
|
+
function injectPageLock(pageEl) {
|
|
2229
|
+
if (!pageEl) return;
|
|
2230
|
+
// Add blur class to page content
|
|
2231
|
+
if (!pageEl.classList.contains('page-locked-blur')) {
|
|
2232
|
+
pageEl.classList.add('page-locked-blur');
|
|
2233
|
+
}
|
|
2234
|
+
// Don't duplicate overlay
|
|
2235
|
+
if (pageEl.querySelector('.page-lock-overlay')) return;
|
|
2231
2236
|
var overlay = document.createElement('div');
|
|
2232
|
-
overlay.
|
|
2237
|
+
overlay.className = 'page-lock-overlay';
|
|
2233
2238
|
overlay.innerHTML = '\
|
|
2234
|
-
<div class="
|
|
2235
|
-
<svg viewBox="0 0 24 24" width="
|
|
2239
|
+
<div class="page-lock-icon">\
|
|
2240
|
+
<svg viewBox="0 0 24 24" width="48" height="48" fill="#ffd700">\
|
|
2236
2241
|
<path d="M18 8h-1V6c0-2.76-2.24-5-5-5S7 3.24 7 6v2H6c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V10c0-1.1-.9-2-2-2zm-6 9c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2zm3.1-9H8.9V6c0-1.71 1.39-3.1 3.1-3.1s3.1 1.39 3.1 3.1v2z"/>\
|
|
2237
2242
|
</svg>\
|
|
2238
2243
|
</div>\
|
|
2239
|
-
<div class="
|
|
2240
|
-
<div class="
|
|
2241
|
-
<a href="https://forumtest.ieu.app/premium" target="_blank" class="
|
|
2242
|
-
<div class="
|
|
2244
|
+
<div class="page-lock-title">Kilitli</div>\
|
|
2245
|
+
<div class="page-lock-message">Bu sayfayi goruntulemeye devam etmek icin Premium uyelik gereklidir.</div>\
|
|
2246
|
+
<a href="https://forumtest.ieu.app/premium" target="_blank" class="page-lock-button">Premium Satin Al</a>\
|
|
2247
|
+
<div class="page-lock-secondary">Materyal yukleyerek de Premium olabilirsiniz!</div>';
|
|
2248
|
+
pageEl.style.position = 'relative';
|
|
2249
|
+
pageEl.appendChild(overlay);
|
|
2250
|
+
}
|
|
2251
|
+
|
|
2252
|
+
function resetOverlayCSS(overlay) {
|
|
2253
|
+
overlay.style.cssText = 'position:absolute;top:0;left:0;right:0;bottom:0;display:flex;z-index:5;opacity:1;visibility:visible;pointer-events:auto;';
|
|
2254
|
+
}
|
|
2243
2255
|
|
|
2244
|
-
|
|
2256
|
+
function applyPageLocks() {
|
|
2257
|
+
var pages = document.querySelectorAll('#viewer .page');
|
|
2258
|
+
pages.forEach(function (page) {
|
|
2259
|
+
var pageNum = parseInt(page.dataset.pageNumber || '0', 10);
|
|
2260
|
+
if (pageNum > 1) {
|
|
2261
|
+
// Ensure page is visible (undo any old display:none)
|
|
2262
|
+
if (page.style.display === 'none') {
|
|
2263
|
+
page.style.display = '';
|
|
2264
|
+
}
|
|
2265
|
+
injectPageLock(page);
|
|
2266
|
+
// CSS integrity: reset overlay styles in case of tampering
|
|
2267
|
+
var existing = page.querySelector('.page-lock-overlay');
|
|
2268
|
+
if (existing) resetOverlayCSS(existing);
|
|
2269
|
+
// Ensure blur class is present
|
|
2270
|
+
if (!page.classList.contains('page-locked-blur')) {
|
|
2271
|
+
page.classList.add('page-locked-blur');
|
|
2272
|
+
}
|
|
2273
|
+
}
|
|
2274
|
+
});
|
|
2245
2275
|
}
|
|
2246
2276
|
|
|
2247
2277
|
// ============================================
|
|
@@ -2250,18 +2280,7 @@
|
|
|
2250
2280
|
function startPeriodicCheck() {
|
|
2251
2281
|
setInterval(function () {
|
|
2252
2282
|
if (!premiumInfo || premiumInfo.isPremium) return;
|
|
2253
|
-
|
|
2254
|
-
pages.forEach(function (page, idx) {
|
|
2255
|
-
if (idx > 0 && page.style.display !== 'none') {
|
|
2256
|
-
page.style.display = 'none';
|
|
2257
|
-
}
|
|
2258
|
-
});
|
|
2259
|
-
if (!document.getElementById('premiumLockOverlay')) {
|
|
2260
|
-
showPremiumLockOverlay(premiumInfo.totalPages);
|
|
2261
|
-
}
|
|
2262
|
-
if (pdfViewer && pdfViewer.currentPageNumber > 1) {
|
|
2263
|
-
pdfViewer.currentPageNumber = 1;
|
|
2264
|
-
}
|
|
2283
|
+
applyPageLocks();
|
|
2265
2284
|
}, 2000);
|
|
2266
2285
|
}
|
|
2267
2286
|
|
|
@@ -2272,32 +2291,41 @@
|
|
|
2272
2291
|
var viewerEl = document.getElementById('viewer');
|
|
2273
2292
|
if (!viewerEl) return;
|
|
2274
2293
|
|
|
2294
|
+
// Observer 1: Watch for lock overlay removal from any page
|
|
2275
2295
|
new MutationObserver(function (mutations) {
|
|
2296
|
+
if (!premiumInfo || premiumInfo.isPremium) return;
|
|
2276
2297
|
for (var i = 0; i < mutations.length; i++) {
|
|
2277
2298
|
var removed = mutations[i].removedNodes;
|
|
2278
2299
|
for (var j = 0; j < removed.length; j++) {
|
|
2279
|
-
if (removed[j].
|
|
2280
|
-
|
|
2281
|
-
|
|
2300
|
+
if (removed[j].classList && removed[j].classList.contains('page-lock-overlay')) {
|
|
2301
|
+
var pageEl = mutations[i].target;
|
|
2302
|
+
if (pageEl && pageEl.classList && pageEl.classList.contains('page')) {
|
|
2303
|
+
injectPageLock(pageEl);
|
|
2304
|
+
}
|
|
2282
2305
|
}
|
|
2283
2306
|
}
|
|
2284
2307
|
}
|
|
2285
|
-
}).observe(viewerEl, { childList: true });
|
|
2308
|
+
}).observe(viewerEl, { childList: true, subtree: true });
|
|
2286
2309
|
|
|
2310
|
+
// Observer 2: Watch for style/class tampering on overlays and pages
|
|
2287
2311
|
new MutationObserver(function (mutations) {
|
|
2312
|
+
if (!premiumInfo || premiumInfo.isPremium) return;
|
|
2288
2313
|
for (var i = 0; i < mutations.length; i++) {
|
|
2289
|
-
var
|
|
2290
|
-
if (
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2314
|
+
var target = mutations[i].target;
|
|
2315
|
+
if (!target || !target.classList) continue;
|
|
2316
|
+
// Overlay CSS tampered - reset it
|
|
2317
|
+
if (target.classList.contains('page-lock-overlay')) {
|
|
2318
|
+
resetOverlayCSS(target);
|
|
2319
|
+
}
|
|
2320
|
+
// Blur class removed from locked page - re-add it
|
|
2321
|
+
if (target.classList.contains('page') && !target.classList.contains('page-locked-blur')) {
|
|
2322
|
+
var pageNum = parseInt(target.dataset.pageNumber || '0', 10);
|
|
2323
|
+
if (pageNum > 1) {
|
|
2324
|
+
target.classList.add('page-locked-blur');
|
|
2297
2325
|
}
|
|
2298
2326
|
}
|
|
2299
2327
|
}
|
|
2300
|
-
}).observe(viewerEl, {
|
|
2328
|
+
}).observe(viewerEl, { subtree: true, attributes: true, attributeFilter: ['style', 'class'] });
|
|
2301
2329
|
}
|
|
2302
2330
|
|
|
2303
2331
|
// Auto-load PDF if config is present (injected by NodeBB plugin)
|
|
@@ -2399,7 +2427,7 @@
|
|
|
2399
2427
|
// Premium Gate: Client-side page restriction for non-premium users
|
|
2400
2428
|
if (config.isPremium === false && pdfDoc && pdfDoc.numPages > 1) {
|
|
2401
2429
|
premiumInfo = Object.freeze({ isPremium: false, totalPages: pdfDoc.numPages });
|
|
2402
|
-
|
|
2430
|
+
applyPageLocks();
|
|
2403
2431
|
startPeriodicCheck();
|
|
2404
2432
|
setupAntiTampering();
|
|
2405
2433
|
} else {
|
|
@@ -2477,9 +2505,11 @@
|
|
|
2477
2505
|
}).promise;
|
|
2478
2506
|
|
|
2479
2507
|
const thumb = document.createElement('div');
|
|
2480
|
-
|
|
2508
|
+
const isLocked = premiumInfo && !premiumInfo.isPremium && i > 1;
|
|
2509
|
+
thumb.className = 'thumbnail' + (i === 1 ? ' active' : '') + (isLocked ? ' locked' : '');
|
|
2481
2510
|
thumb.dataset.page = i;
|
|
2482
|
-
thumb.innerHTML = `<div class="thumbnailNum">${i}</div
|
|
2511
|
+
thumb.innerHTML = `<div class="thumbnailNum">${i}</div>` +
|
|
2512
|
+
(isLocked ? '<div class="thumbnail-lock">\u{1F512}</div>' : '');
|
|
2483
2513
|
thumb.insertBefore(canvas, thumb.firstChild);
|
|
2484
2514
|
|
|
2485
2515
|
thumb.onclick = () => {
|
|
@@ -2525,6 +2555,12 @@
|
|
|
2525
2555
|
eventBus.on('pagerendered', (evt) => {
|
|
2526
2556
|
injectAnnotationLayer(evt.pageNumber);
|
|
2527
2557
|
|
|
2558
|
+
// Re-inject lock overlay if this is a locked page (PDF.js re-render removes it)
|
|
2559
|
+
if (premiumInfo && !premiumInfo.isPremium && evt.pageNumber > 1) {
|
|
2560
|
+
var pageEl = document.querySelector('#viewer .page[data-page-number="' + evt.pageNumber + '"]');
|
|
2561
|
+
if (pageEl) injectPageLock(pageEl);
|
|
2562
|
+
}
|
|
2563
|
+
|
|
2528
2564
|
// Rotation is handled natively by PDF.js via pagesRotation
|
|
2529
2565
|
});
|
|
2530
2566
|
|