nodebb-plugin-pdf-secure2 1.2.30 → 1.2.31

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/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.31",
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 */
@@ -1599,25 +1609,31 @@
1599
1609
  z-index: 15;
1600
1610
  text-align: center;
1601
1611
  padding: 20px;
1612
+ box-sizing: border-box;
1602
1613
  }
1603
1614
 
1604
1615
  .page-lock-icon {
1605
- margin-bottom: 16px;
1616
+ margin-bottom: clamp(8px, 2vw, 16px);
1606
1617
  opacity: 0.9;
1607
1618
  }
1608
1619
 
1620
+ .page-lock-icon svg {
1621
+ width: clamp(32px, 6vw, 48px);
1622
+ height: clamp(32px, 6vw, 48px);
1623
+ }
1624
+
1609
1625
  .page-lock-title {
1610
- font-size: 20px;
1626
+ font-size: clamp(14px, 3vw, 20px);
1611
1627
  font-weight: 600;
1612
1628
  color: #ffd700;
1613
- margin-bottom: 10px;
1629
+ margin-bottom: clamp(6px, 1.5vw, 10px);
1614
1630
  }
1615
1631
 
1616
1632
  .page-lock-message {
1617
- font-size: 14px;
1633
+ font-size: clamp(11px, 2vw, 14px);
1618
1634
  color: #a0a0a0;
1619
- margin-bottom: 24px;
1620
- max-width: 320px;
1635
+ margin-bottom: clamp(12px, 3vw, 24px);
1636
+ max-width: min(320px, 90%);
1621
1637
  line-height: 1.5;
1622
1638
  }
1623
1639
 
@@ -1626,7 +1642,7 @@
1626
1642
  flex-direction: column;
1627
1643
  align-items: center;
1628
1644
  gap: 0;
1629
- width: 100%;
1645
+ width: 90%;
1630
1646
  max-width: 300px;
1631
1647
  }
1632
1648
 
@@ -1634,18 +1650,19 @@
1634
1650
  display: flex;
1635
1651
  align-items: center;
1636
1652
  justify-content: center;
1637
- gap: 8px;
1653
+ gap: 6px;
1638
1654
  width: 100%;
1639
- padding: 13px 24px;
1655
+ padding: clamp(9px, 2vw, 13px) clamp(14px, 3vw, 24px);
1640
1656
  background: linear-gradient(135deg, #ffd700 0%, #ffaa00 100%);
1641
1657
  color: #1a1a1a;
1642
- font-size: 15px;
1658
+ font-size: clamp(12px, 2.2vw, 15px);
1643
1659
  font-weight: 700;
1644
1660
  border-radius: 10px;
1645
1661
  text-decoration: none;
1646
1662
  transition: transform 0.2s, box-shadow 0.2s;
1647
1663
  box-shadow: 0 4px 15px rgba(255, 215, 0, 0.3);
1648
1664
  box-sizing: border-box;
1665
+ white-space: nowrap;
1649
1666
  }
1650
1667
 
1651
1668
  .page-lock-button:hover {
@@ -1655,6 +1672,8 @@
1655
1672
 
1656
1673
  .page-lock-button svg {
1657
1674
  flex-shrink: 0;
1675
+ width: clamp(14px, 2.5vw, 18px);
1676
+ height: clamp(14px, 2.5vw, 18px);
1658
1677
  }
1659
1678
 
1660
1679
  .page-lock-divider {
@@ -1662,9 +1681,9 @@
1662
1681
  align-items: center;
1663
1682
  gap: 12px;
1664
1683
  width: 100%;
1665
- margin: 14px 0;
1684
+ margin: clamp(8px, 2vw, 14px) 0;
1666
1685
  color: #666;
1667
- font-size: 12px;
1686
+ font-size: clamp(10px, 1.8vw, 12px);
1668
1687
  font-weight: 500;
1669
1688
  letter-spacing: 0.5px;
1670
1689
  text-transform: lowercase;
@@ -1682,18 +1701,19 @@
1682
1701
  display: flex;
1683
1702
  align-items: center;
1684
1703
  justify-content: center;
1685
- gap: 8px;
1704
+ gap: 6px;
1686
1705
  width: 100%;
1687
- padding: 11px 24px;
1706
+ padding: clamp(7px, 1.8vw, 11px) clamp(14px, 3vw, 24px);
1688
1707
  background: transparent;
1689
1708
  color: #ccc;
1690
- font-size: 13px;
1709
+ font-size: clamp(11px, 2vw, 13px);
1691
1710
  font-weight: 600;
1692
1711
  border-radius: 10px;
1693
1712
  border: 1.5px solid rgba(255, 255, 255, 0.15);
1694
1713
  text-decoration: none;
1695
1714
  transition: transform 0.2s, border-color 0.2s, background 0.2s;
1696
1715
  box-sizing: border-box;
1716
+ white-space: nowrap;
1697
1717
  }
1698
1718
 
1699
1719
  .page-lock-button-secondary:hover {
@@ -1704,6 +1724,8 @@
1704
1724
 
1705
1725
  .page-lock-button-secondary svg {
1706
1726
  flex-shrink: 0;
1727
+ width: clamp(12px, 2.2vw, 16px);
1728
+ height: clamp(12px, 2.2vw, 16px);
1707
1729
  }
1708
1730
 
1709
1731
  /* Blur locked page content - even if overlay removed, content unreadable */
@@ -1733,29 +1755,7 @@
1733
1755
  z-index: 2;
1734
1756
  }
1735
1757
 
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
- }
1758
+ /* Lock overlay responsive - clamp() handles all breakpoints above */
1759
1759
 
1760
1760
  /* ── Unicourse Page Watermark ── */
1761
1761
  .unicourse-page-wm {
@@ -2363,26 +2363,31 @@
2363
2363
  }
2364
2364
 
2365
2365
  // Create fake locked page placeholders for pages 2..totalPages
2366
- // These look like real PDF pages but contain no actual data - purely visual
2366
+ // Appended to #viewerContainer (not #viewer) so PDF.js layout is not affected
2367
2367
  function createLockedPagePlaceholders(totalPages) {
2368
- var viewerEl = document.getElementById('viewer');
2369
- if (!viewerEl) return;
2368
+ var containerEl = document.getElementById('viewerContainer');
2369
+ if (!containerEl) return;
2370
2370
  // Already created?
2371
- if (viewerEl.querySelector('.fake-locked-page')) return;
2371
+ if (document.getElementById('fakeLockedPages')) return;
2372
2372
 
2373
2373
  // 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';
2374
+ var viewerEl = document.getElementById('viewer');
2375
+ var page1 = viewerEl ? viewerEl.querySelector('.page') : null;
2376
+ var pageWidth = page1 ? (page1.offsetWidth || 816) : 816;
2377
+ var pageHeight = page1 ? (page1.offsetHeight || 1056) : 1056;
2377
2378
 
2378
2379
  var uid = (_cfg && _cfg.uid) || 0;
2379
2380
  var checkoutUrl = 'https://forum.ieu.app/pay/checkout?uid=' + uid;
2380
2381
 
2382
+ var wrapper = document.createElement('div');
2383
+ wrapper.id = 'fakeLockedPages';
2384
+
2381
2385
  for (var i = 2; i <= totalPages; i++) {
2382
2386
  var fakePage = document.createElement('div');
2383
- fakePage.className = 'page fake-locked-page';
2387
+ fakePage.className = 'fake-locked-page';
2384
2388
  fakePage.dataset.pageNumber = i;
2385
- fakePage.style.cssText = 'position:relative;width:' + pageWidth + ';height:' + pageHeight + ';margin:10px auto;overflow:hidden;';
2389
+ fakePage.style.width = pageWidth + 'px';
2390
+ fakePage.style.height = pageHeight + 'px';
2386
2391
 
2387
2392
  var overlay = document.createElement('div');
2388
2393
  overlay.className = 'page-lock-overlay';
@@ -2406,8 +2411,9 @@
2406
2411
  </a>\
2407
2412
  </div>';
2408
2413
  fakePage.appendChild(overlay);
2409
- viewerEl.appendChild(fakePage);
2414
+ wrapper.appendChild(fakePage);
2410
2415
  }
2416
+ containerEl.appendChild(wrapper);
2411
2417
  }
2412
2418
 
2413
2419
  function injectPageLock(pageEl) {
@@ -2493,31 +2499,35 @@
2493
2499
  // PREMIUM INTEGRITY: MutationObserver Anti-Tampering
2494
2500
  // ============================================
2495
2501
  function setupAntiTampering() {
2496
- var viewerEl = document.getElementById('viewer');
2497
- if (!viewerEl) return;
2502
+ var containerEl = document.getElementById('viewerContainer');
2503
+ if (!containerEl) return;
2498
2504
 
2499
- // Observer 1: Watch for lock overlay removal from any page
2505
+ // Observer 1: Watch for fake pages wrapper or overlay removal
2500
2506
  new MutationObserver(function (mutations) {
2501
2507
  if (!premiumInfo || premiumInfo.isPremium) return;
2502
2508
  for (var i = 0; i < mutations.length; i++) {
2503
2509
  var removed = mutations[i].removedNodes;
2504
2510
  for (var j = 0; j < removed.length; j++) {
2511
+ var node = removed[j];
2505
2512
  // Re-inject per-page lock if removed
2506
- if (removed[j].classList && removed[j].classList.contains('page-lock-overlay')) {
2513
+ if (node.classList && node.classList.contains('page-lock-overlay')) {
2507
2514
  var pageEl = mutations[i].target;
2508
- if (pageEl && pageEl.classList && pageEl.classList.contains('page')) {
2515
+ if (pageEl && pageEl.classList && pageEl.classList.contains('fake-locked-page')) {
2509
2516
  injectPageLock(pageEl);
2510
2517
  }
2511
2518
  }
2512
- // Re-inject fake locked pages if removed
2513
- if (removed[j].classList && removed[j].classList.contains('fake-locked-page')) {
2519
+ // Re-create entire fake pages wrapper if removed
2520
+ if (node.id === 'fakeLockedPages' || (node.classList && node.classList.contains('fake-locked-page'))) {
2521
+ // Remove stale wrapper if partially emptied
2522
+ var existingWrapper = document.getElementById('fakeLockedPages');
2523
+ if (existingWrapper) existingWrapper.remove();
2514
2524
  createLockedPagePlaceholders(premiumInfo.totalPages);
2515
2525
  }
2516
2526
  }
2517
2527
  }
2518
- }).observe(viewerEl, { childList: true, subtree: true });
2528
+ }).observe(containerEl, { childList: true, subtree: true });
2519
2529
 
2520
- // Observer 2: Watch for style/class tampering on overlays and pages
2530
+ // Observer 2: Watch for style tampering on overlays (display:none, opacity:0 etc.)
2521
2531
  new MutationObserver(function (mutations) {
2522
2532
  if (!premiumInfo || premiumInfo.isPremium) return;
2523
2533
  for (var i = 0; i < mutations.length; i++) {
@@ -2528,14 +2538,8 @@
2528
2538
  resetOverlayCSS(target);
2529
2539
  }
2530
2540
  }
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
2541
  }
2538
- }).observe(viewerEl, { subtree: true, attributes: true, attributeFilter: ['style', 'class'] });
2542
+ }).observe(containerEl, { subtree: true, attributes: true, attributeFilter: ['style', 'class'] });
2539
2543
  }
2540
2544
 
2541
2545
  // ============================================
@@ -2830,7 +2834,7 @@
2830
2834
  a.rel = 'noopener';
2831
2835
  a.className = 'unicourse-page-wm';
2832
2836
  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">' +
2837
+ a.innerHTML = '<img src="https://unicourse.co/logo_unicorn.png" alt="unicourse">' +
2834
2838
  '<div class="unicourse-page-wm-text">' +
2835
2839
  '<span>Çıkmış sorular ve</span>' +
2836
2840
  '<span>ders notları için tıkla</span>' +
package/image.png DELETED
Binary file