nodebb-plugin-pdf-secure2 1.2.30 → 1.2.32

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/image copy.png ADDED
Binary file
package/library.js CHANGED
@@ -125,7 +125,7 @@ plugin.init = async (params) => {
125
125
  'Expires': '0',
126
126
  'Referrer-Policy': 'no-referrer',
127
127
  'Permissions-Policy': 'accelerometer=(), camera=(), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), payment=(), usb=()',
128
- 'Content-Security-Policy': "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://cdnjs.cloudflare.com; style-src 'self' 'unsafe-inline' https://cdnjs.cloudflare.com; img-src 'self' data: blob:; connect-src 'self'; frame-ancestors 'self'",
128
+ 'Content-Security-Policy': "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://cdnjs.cloudflare.com; style-src 'self' 'unsafe-inline' https://cdnjs.cloudflare.com; img-src 'self' data: blob: https://i.ibb.co; connect-src 'self'; frame-ancestors 'self'",
129
129
  });
130
130
 
131
131
  // Inject the filename, nonce, and key into the cached viewer
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nodebb-plugin-pdf-secure2",
3
- "version": "1.2.30",
3
+ "version": "1.2.32",
4
4
  "description": "Secure PDF viewer plugin for NodeBB - prevents downloading, enables canvas-only rendering with Premium group support",
5
5
  "main": "library.js",
6
6
  "repository": {
@@ -178,23 +178,29 @@
178
178
  }
179
179
 
180
180
  // Create fake locked page placeholders for pages 2..totalPages
181
+ // Appended to #viewerContainer (not #viewer) so PDF.js layout is not affected
181
182
  function createLockedPagePlaceholders(totalPages) {
182
- const viewerEl = document.getElementById('viewer');
183
- if (!viewerEl) return;
184
- if (viewerEl.querySelector('.fake-locked-page')) return;
183
+ const containerEl = document.getElementById('viewerContainer');
184
+ if (!containerEl) return;
185
+ if (document.getElementById('fakeLockedPages')) return;
185
186
 
186
- const page1 = viewerEl.querySelector('.page');
187
- const pageWidth = page1 ? (page1.style.width || page1.offsetWidth + 'px') : '816px';
188
- const pageHeight = page1 ? (page1.style.height || page1.offsetHeight + 'px') : '1056px';
187
+ const viewerEl = document.getElementById('viewer');
188
+ const page1 = viewerEl ? viewerEl.querySelector('.page') : null;
189
+ const pageWidth = page1 ? (page1.offsetWidth || 816) : 816;
190
+ const pageHeight = page1 ? (page1.offsetHeight || 1056) : 1056;
189
191
 
190
192
  const uid = (_cfg && _cfg.uid) || 0;
191
193
  const checkoutUrl = 'https://forum.ieu.app/pay/checkout?uid=' + uid;
192
194
 
195
+ const wrapper = document.createElement('div');
196
+ wrapper.id = 'fakeLockedPages';
197
+ wrapper.style.cssText = 'display:flex;flex-direction:column;align-items:center;';
198
+
193
199
  for (let i = 2; i <= totalPages; i++) {
194
200
  const fakePage = document.createElement('div');
195
- fakePage.className = 'page fake-locked-page';
201
+ fakePage.className = 'fake-locked-page';
196
202
  fakePage.dataset.pageNumber = i;
197
- fakePage.style.cssText = `position:relative;width:${pageWidth};height:${pageHeight};margin:10px auto;overflow:hidden;background:#1a1a1a;border:1px solid rgba(255,255,255,0.05);box-shadow:0 2px 8px rgba(0,0,0,0.3);`;
203
+ fakePage.style.cssText = `position:relative;width:${pageWidth}px;height:${pageHeight}px;max-width:100%;margin:8px auto;overflow:hidden;background:#1a1a1a;border:1px solid rgba(255,255,255,0.05);box-shadow:0 2px 8px rgba(0,0,0,0.3);`;
198
204
 
199
205
  const overlay = document.createElement('div');
200
206
  overlay.className = 'page-lock-overlay';
@@ -219,8 +225,9 @@
219
225
  </div>
220
226
  `;
221
227
  fakePage.appendChild(overlay);
222
- viewerEl.appendChild(fakePage);
228
+ wrapper.appendChild(fakePage);
223
229
  }
230
+ containerEl.appendChild(wrapper);
224
231
  }
225
232
 
226
233
  // ============================================
@@ -275,20 +282,9 @@
275
282
  setInterval(function () {
276
283
  if (!premiumInfo || premiumInfo.isPremium) return;
277
284
  // Ensure fake locked pages still exist
278
- if (!document.querySelector('.fake-locked-page')) {
285
+ if (!document.getElementById('fakeLockedPages')) {
279
286
  createLockedPagePlaceholders(premiumInfo.totalPages);
280
287
  }
281
- // Ensure lock overlays on fake pages
282
- document.querySelectorAll('.fake-locked-page').forEach(function (page) {
283
- if (!page.querySelector('.page-lock-overlay')) {
284
- var uid = (_cfg && _cfg.uid) || 0;
285
- var checkoutUrl = 'https://forum.ieu.app/pay/checkout?uid=' + uid;
286
- var overlay = document.createElement('div');
287
- overlay.className = 'page-lock-overlay';
288
- overlay.innerHTML = '<div class="page-lock-icon"><svg viewBox="0 0 24 24" width="48" height="48" fill="#ffd700"><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"/></svg></div><div class="page-lock-title">Bu sayfa kilitli</div><div class="page-lock-message">Tum sayfalara erisim icin Premium satin alabilir veya materyal yukleyerek erisim kazanabilirsiniz.</div>';
289
- page.appendChild(overlay);
290
- }
291
- });
292
288
  }, 2000);
293
289
  }
294
290
 
@@ -300,20 +296,24 @@
300
296
  var viewerEl = document.getElementById('viewer');
301
297
  if (!viewerEl) return;
302
298
 
303
- // Observer 1: Watch for fake page removal (childList)
299
+ var containerEl = document.getElementById('viewerContainer') || viewerEl;
300
+
301
+ // Observer 1: Watch for fake pages wrapper removal (childList)
304
302
  new MutationObserver(function (mutations) {
305
303
  for (var i = 0; i < mutations.length; i++) {
306
304
  var removed = mutations[i].removedNodes;
307
305
  for (var j = 0; j < removed.length; j++) {
308
- if (removed[j].classList && removed[j].classList.contains('fake-locked-page')) {
306
+ if (removed[j].id === 'fakeLockedPages' || (removed[j].classList && removed[j].classList.contains('fake-locked-page'))) {
307
+ var existingWrapper = document.getElementById('fakeLockedPages');
308
+ if (existingWrapper) existingWrapper.remove();
309
309
  createLockedPagePlaceholders(premiumInfo.totalPages);
310
310
  return;
311
311
  }
312
312
  }
313
313
  }
314
- }).observe(viewerEl, { childList: true, subtree: true });
314
+ }).observe(containerEl, { childList: true, subtree: true });
315
315
 
316
- // Observer 2: Watch for page visibility tampering (attributes)
316
+ // Observer 2: Watch for overlay style tampering (attributes)
317
317
  new MutationObserver(function (mutations) {
318
318
  for (var i = 0; i < mutations.length; i++) {
319
319
  var m = mutations[i];
@@ -1581,10 +1581,20 @@
1581
1581
  }
1582
1582
 
1583
1583
  /* Fake locked page placeholders - no real PDF data, purely visual */
1584
+ #fakeLockedPages {
1585
+ display: flex;
1586
+ flex-direction: column;
1587
+ align-items: center;
1588
+ }
1589
+
1584
1590
  .fake-locked-page {
1591
+ position: relative;
1592
+ margin: 8px auto;
1593
+ max-width: 100%;
1585
1594
  background: #1a1a1a;
1586
1595
  border: 1px solid rgba(255,255,255,0.05);
1587
1596
  box-shadow: 0 2px 8px rgba(0,0,0,0.3);
1597
+ overflow: hidden;
1588
1598
  }
1589
1599
 
1590
1600
  /* Per-page lock overlay - her kilitli sayfa icin */
@@ -1594,30 +1604,38 @@
1594
1604
  display: flex;
1595
1605
  flex-direction: column;
1596
1606
  align-items: center;
1597
- justify-content: center;
1607
+ justify-content: flex-start;
1608
+ padding-top: clamp(30px, 8%, 80px);
1598
1609
  background: linear-gradient(180deg, rgba(31,31,31,0.95) 0%, rgba(20,20,20,0.98) 100%);
1599
1610
  z-index: 15;
1600
1611
  text-align: center;
1601
- padding: 20px;
1612
+ padding-left: 20px;
1613
+ padding-right: 20px;
1614
+ box-sizing: border-box;
1602
1615
  }
1603
1616
 
1604
1617
  .page-lock-icon {
1605
- margin-bottom: 16px;
1618
+ margin-bottom: clamp(8px, 2vw, 16px);
1606
1619
  opacity: 0.9;
1607
1620
  }
1608
1621
 
1622
+ .page-lock-icon svg {
1623
+ width: clamp(32px, 6vw, 48px);
1624
+ height: clamp(32px, 6vw, 48px);
1625
+ }
1626
+
1609
1627
  .page-lock-title {
1610
- font-size: 20px;
1628
+ font-size: clamp(14px, 3vw, 20px);
1611
1629
  font-weight: 600;
1612
1630
  color: #ffd700;
1613
- margin-bottom: 10px;
1631
+ margin-bottom: clamp(6px, 1.5vw, 10px);
1614
1632
  }
1615
1633
 
1616
1634
  .page-lock-message {
1617
- font-size: 14px;
1635
+ font-size: clamp(11px, 2vw, 14px);
1618
1636
  color: #a0a0a0;
1619
- margin-bottom: 24px;
1620
- max-width: 320px;
1637
+ margin-bottom: clamp(12px, 3vw, 24px);
1638
+ max-width: min(320px, 90%);
1621
1639
  line-height: 1.5;
1622
1640
  }
1623
1641
 
@@ -1626,7 +1644,7 @@
1626
1644
  flex-direction: column;
1627
1645
  align-items: center;
1628
1646
  gap: 0;
1629
- width: 100%;
1647
+ width: 90%;
1630
1648
  max-width: 300px;
1631
1649
  }
1632
1650
 
@@ -1634,18 +1652,19 @@
1634
1652
  display: flex;
1635
1653
  align-items: center;
1636
1654
  justify-content: center;
1637
- gap: 8px;
1655
+ gap: 6px;
1638
1656
  width: 100%;
1639
- padding: 13px 24px;
1657
+ padding: clamp(9px, 2vw, 13px) clamp(14px, 3vw, 24px);
1640
1658
  background: linear-gradient(135deg, #ffd700 0%, #ffaa00 100%);
1641
1659
  color: #1a1a1a;
1642
- font-size: 15px;
1660
+ font-size: clamp(12px, 2.2vw, 15px);
1643
1661
  font-weight: 700;
1644
1662
  border-radius: 10px;
1645
1663
  text-decoration: none;
1646
1664
  transition: transform 0.2s, box-shadow 0.2s;
1647
1665
  box-shadow: 0 4px 15px rgba(255, 215, 0, 0.3);
1648
1666
  box-sizing: border-box;
1667
+ white-space: nowrap;
1649
1668
  }
1650
1669
 
1651
1670
  .page-lock-button:hover {
@@ -1655,6 +1674,8 @@
1655
1674
 
1656
1675
  .page-lock-button svg {
1657
1676
  flex-shrink: 0;
1677
+ width: clamp(14px, 2.5vw, 18px);
1678
+ height: clamp(14px, 2.5vw, 18px);
1658
1679
  }
1659
1680
 
1660
1681
  .page-lock-divider {
@@ -1662,9 +1683,9 @@
1662
1683
  align-items: center;
1663
1684
  gap: 12px;
1664
1685
  width: 100%;
1665
- margin: 14px 0;
1686
+ margin: clamp(8px, 2vw, 14px) 0;
1666
1687
  color: #666;
1667
- font-size: 12px;
1688
+ font-size: clamp(10px, 1.8vw, 12px);
1668
1689
  font-weight: 500;
1669
1690
  letter-spacing: 0.5px;
1670
1691
  text-transform: lowercase;
@@ -1682,18 +1703,19 @@
1682
1703
  display: flex;
1683
1704
  align-items: center;
1684
1705
  justify-content: center;
1685
- gap: 8px;
1706
+ gap: 6px;
1686
1707
  width: 100%;
1687
- padding: 11px 24px;
1708
+ padding: clamp(7px, 1.8vw, 11px) clamp(14px, 3vw, 24px);
1688
1709
  background: transparent;
1689
1710
  color: #ccc;
1690
- font-size: 13px;
1711
+ font-size: clamp(11px, 2vw, 13px);
1691
1712
  font-weight: 600;
1692
1713
  border-radius: 10px;
1693
1714
  border: 1.5px solid rgba(255, 255, 255, 0.15);
1694
1715
  text-decoration: none;
1695
1716
  transition: transform 0.2s, border-color 0.2s, background 0.2s;
1696
1717
  box-sizing: border-box;
1718
+ white-space: nowrap;
1697
1719
  }
1698
1720
 
1699
1721
  .page-lock-button-secondary:hover {
@@ -1704,6 +1726,8 @@
1704
1726
 
1705
1727
  .page-lock-button-secondary svg {
1706
1728
  flex-shrink: 0;
1729
+ width: clamp(12px, 2.2vw, 16px);
1730
+ height: clamp(12px, 2.2vw, 16px);
1707
1731
  }
1708
1732
 
1709
1733
  /* Blur locked page content - even if overlay removed, content unreadable */
@@ -1733,29 +1757,7 @@
1733
1757
  z-index: 2;
1734
1758
  }
1735
1759
 
1736
- @media (max-width: 768px) {
1737
- .page-lock-title {
1738
- font-size: 17px;
1739
- }
1740
-
1741
- .page-lock-message {
1742
- font-size: 13px;
1743
- }
1744
-
1745
- .page-lock-actions {
1746
- max-width: 260px;
1747
- }
1748
-
1749
- .page-lock-button {
1750
- padding: 11px 20px;
1751
- font-size: 13px;
1752
- }
1753
-
1754
- .page-lock-button-secondary {
1755
- padding: 9px 20px;
1756
- font-size: 12px;
1757
- }
1758
- }
1760
+ /* Lock overlay responsive - clamp() handles all breakpoints above */
1759
1761
 
1760
1762
  /* ── Unicourse Page Watermark ── */
1761
1763
  .unicourse-page-wm {
@@ -2363,26 +2365,31 @@
2363
2365
  }
2364
2366
 
2365
2367
  // Create fake locked page placeholders for pages 2..totalPages
2366
- // These look like real PDF pages but contain no actual data - purely visual
2368
+ // Appended to #viewerContainer (not #viewer) so PDF.js layout is not affected
2367
2369
  function createLockedPagePlaceholders(totalPages) {
2368
- var viewerEl = document.getElementById('viewer');
2369
- if (!viewerEl) return;
2370
+ var containerEl = document.getElementById('viewerContainer');
2371
+ if (!containerEl) return;
2370
2372
  // Already created?
2371
- if (viewerEl.querySelector('.fake-locked-page')) return;
2373
+ if (document.getElementById('fakeLockedPages')) return;
2372
2374
 
2373
2375
  // Get page 1 dimensions to match fake pages
2374
- var page1 = viewerEl.querySelector('.page');
2375
- var pageWidth = page1 ? page1.style.width || (page1.offsetWidth + 'px') : '816px';
2376
- var pageHeight = page1 ? page1.style.height || (page1.offsetHeight + 'px') : '1056px';
2376
+ var viewerEl = document.getElementById('viewer');
2377
+ var page1 = viewerEl ? viewerEl.querySelector('.page') : null;
2378
+ var pageWidth = page1 ? (page1.offsetWidth || 816) : 816;
2379
+ var pageHeight = page1 ? (page1.offsetHeight || 1056) : 1056;
2377
2380
 
2378
2381
  var uid = (_cfg && _cfg.uid) || 0;
2379
2382
  var checkoutUrl = 'https://forum.ieu.app/pay/checkout?uid=' + uid;
2380
2383
 
2384
+ var wrapper = document.createElement('div');
2385
+ wrapper.id = 'fakeLockedPages';
2386
+
2381
2387
  for (var i = 2; i <= totalPages; i++) {
2382
2388
  var fakePage = document.createElement('div');
2383
- fakePage.className = 'page fake-locked-page';
2389
+ fakePage.className = 'fake-locked-page';
2384
2390
  fakePage.dataset.pageNumber = i;
2385
- fakePage.style.cssText = 'position:relative;width:' + pageWidth + ';height:' + pageHeight + ';margin:10px auto;overflow:hidden;';
2391
+ fakePage.style.width = pageWidth + 'px';
2392
+ fakePage.style.height = pageHeight + 'px';
2386
2393
 
2387
2394
  var overlay = document.createElement('div');
2388
2395
  overlay.className = 'page-lock-overlay';
@@ -2406,8 +2413,9 @@
2406
2413
  </a>\
2407
2414
  </div>';
2408
2415
  fakePage.appendChild(overlay);
2409
- viewerEl.appendChild(fakePage);
2416
+ wrapper.appendChild(fakePage);
2410
2417
  }
2418
+ containerEl.appendChild(wrapper);
2411
2419
  }
2412
2420
 
2413
2421
  function injectPageLock(pageEl) {
@@ -2493,31 +2501,35 @@
2493
2501
  // PREMIUM INTEGRITY: MutationObserver Anti-Tampering
2494
2502
  // ============================================
2495
2503
  function setupAntiTampering() {
2496
- var viewerEl = document.getElementById('viewer');
2497
- if (!viewerEl) return;
2504
+ var containerEl = document.getElementById('viewerContainer');
2505
+ if (!containerEl) return;
2498
2506
 
2499
- // Observer 1: Watch for lock overlay removal from any page
2507
+ // Observer 1: Watch for fake pages wrapper or overlay removal
2500
2508
  new MutationObserver(function (mutations) {
2501
2509
  if (!premiumInfo || premiumInfo.isPremium) return;
2502
2510
  for (var i = 0; i < mutations.length; i++) {
2503
2511
  var removed = mutations[i].removedNodes;
2504
2512
  for (var j = 0; j < removed.length; j++) {
2513
+ var node = removed[j];
2505
2514
  // Re-inject per-page lock if removed
2506
- if (removed[j].classList && removed[j].classList.contains('page-lock-overlay')) {
2515
+ if (node.classList && node.classList.contains('page-lock-overlay')) {
2507
2516
  var pageEl = mutations[i].target;
2508
- if (pageEl && pageEl.classList && pageEl.classList.contains('page')) {
2517
+ if (pageEl && pageEl.classList && pageEl.classList.contains('fake-locked-page')) {
2509
2518
  injectPageLock(pageEl);
2510
2519
  }
2511
2520
  }
2512
- // Re-inject fake locked pages if removed
2513
- if (removed[j].classList && removed[j].classList.contains('fake-locked-page')) {
2521
+ // Re-create entire fake pages wrapper if removed
2522
+ if (node.id === 'fakeLockedPages' || (node.classList && node.classList.contains('fake-locked-page'))) {
2523
+ // Remove stale wrapper if partially emptied
2524
+ var existingWrapper = document.getElementById('fakeLockedPages');
2525
+ if (existingWrapper) existingWrapper.remove();
2514
2526
  createLockedPagePlaceholders(premiumInfo.totalPages);
2515
2527
  }
2516
2528
  }
2517
2529
  }
2518
- }).observe(viewerEl, { childList: true, subtree: true });
2530
+ }).observe(containerEl, { childList: true, subtree: true });
2519
2531
 
2520
- // Observer 2: Watch for style/class tampering on overlays and pages
2532
+ // Observer 2: Watch for style tampering on overlays (display:none, opacity:0 etc.)
2521
2533
  new MutationObserver(function (mutations) {
2522
2534
  if (!premiumInfo || premiumInfo.isPremium) return;
2523
2535
  for (var i = 0; i < mutations.length; i++) {
@@ -2528,14 +2540,8 @@
2528
2540
  resetOverlayCSS(target);
2529
2541
  }
2530
2542
  }
2531
- if (target.classList.contains('page') && !target.classList.contains('page-locked-blur')) {
2532
- var pageNum = parseInt(target.dataset.pageNumber || '0', 10);
2533
- if (pageNum > 1) {
2534
- target.classList.add('page-locked-blur');
2535
- }
2536
- }
2537
2543
  }
2538
- }).observe(viewerEl, { subtree: true, attributes: true, attributeFilter: ['style', 'class'] });
2544
+ }).observe(containerEl, { subtree: true, attributes: true, attributeFilter: ['style', 'class'] });
2539
2545
  }
2540
2546
 
2541
2547
  // ============================================
@@ -2830,7 +2836,7 @@
2830
2836
  a.rel = 'noopener';
2831
2837
  a.className = 'unicourse-page-wm';
2832
2838
  a.style.setProperty('--wm-scale', scale);
2833
- a.innerHTML = '<img src="https://cdn.prod.website-files.com/66c986ba4ac79c4fbbd5f45e/66c9958f0188acfb12a2d2fb_64a464c6b3b7df67c22a255b_logo_full.png" alt="unicourse">' +
2839
+ a.innerHTML = '<img src="https://i.ibb.co/SbzdR8K/logo-unicorn.png" alt="unicourse">' +
2834
2840
  '<div class="unicourse-page-wm-text">' +
2835
2841
  '<span>Çıkmış sorular ve</span>' +
2836
2842
  '<span>ders notları için tıkla</span>' +
package/image.png DELETED
Binary file