nodebb-plugin-pdf-secure 1.2.29 → 1.2.30

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.
@@ -1,184 +0,0 @@
1
- import { getDocument, GlobalWorkerOptions } from './pdf.min.mjs';
2
-
3
- GlobalWorkerOptions.workerSrc = new URL('./pdf.worker.min.mjs', import.meta.url).href;
4
- console.log('[PDF-Secure][Viewer] ES module loaded, worker:', GlobalWorkerOptions.workerSrc);
5
-
6
- // Listen for NodeBB SPA navigations (jQuery event)
7
- $(window).on('action:ajaxify.end', function () {
8
- console.log('[PDF-Secure][Viewer] action:ajaxify.end fired');
9
- interceptPdfLinks();
10
- });
11
-
12
- // Also run immediately for the current page
13
- console.log('[PDF-Secure][Viewer] Running initial interceptPdfLinks...');
14
- interceptPdfLinks();
15
-
16
- function interceptPdfLinks() {
17
- var postContents = document.querySelectorAll('[component="post/content"]');
18
- console.log('[PDF-Secure][Viewer] Found ' + postContents.length + ' post areas');
19
-
20
- postContents.forEach(function (content, idx) {
21
- var pdfLinks = content.querySelectorAll('a[href$=".pdf"], a[href$=".PDF"]');
22
- console.log('[PDF-Secure][Viewer] Post #' + idx + ': ' + pdfLinks.length + ' PDF links');
23
-
24
- pdfLinks.forEach(function (link) {
25
- if (link.dataset.pdfSecure) return;
26
- link.dataset.pdfSecure = 'true';
27
-
28
- var href = link.getAttribute('href');
29
- var parts = href.split('/');
30
- var filename = parts[parts.length - 1];
31
- console.log('[PDF-Secure][Viewer] Processing:', filename);
32
-
33
- var container = document.createElement('div');
34
- container.className = 'pdf-secure-inline';
35
- container.innerHTML =
36
- '<div class="pdf-secure-inline-header">' +
37
- '<i class="fa fa-file-pdf-o"></i> ' +
38
- '<span class="pdf-secure-filename">' + escapeHtml(link.textContent || filename) + '</span>' +
39
- '</div>' +
40
- '<div class="pdf-secure-inline-body">' +
41
- '<div class="pdf-secure-loading">Loading PDF...</div>' +
42
- '<div class="pdf-secure-error"></div>' +
43
- '<canvas class="pdf-secure-canvas"></canvas>' +
44
- '</div>' +
45
- '<div class="pdf-secure-inline-footer">' +
46
- '<button class="pdf-secure-prev" disabled>&#8249; Prev</button>' +
47
- '<span class="pdf-secure-page-info"></span>' +
48
- '<button class="pdf-secure-next" disabled>Next &#8250;</button>' +
49
- '</div>';
50
-
51
- link.replaceWith(container);
52
- console.log('[PDF-Secure][Viewer] Container created for:', filename);
53
-
54
- loadPdf(container, filename);
55
- });
56
- });
57
- }
58
-
59
- async function loadPdf(container, filename) {
60
- var loadingEl = container.querySelector('.pdf-secure-loading');
61
- var errorEl = container.querySelector('.pdf-secure-error');
62
- var canvas = container.querySelector('.pdf-secure-canvas');
63
- var footer = container.querySelector('.pdf-secure-inline-footer');
64
- var prevBtn = container.querySelector('.pdf-secure-prev');
65
- var nextBtn = container.querySelector('.pdf-secure-next');
66
- var pageInfo = container.querySelector('.pdf-secure-page-info');
67
- var bodyEl = container.querySelector('.pdf-secure-inline-body');
68
-
69
- function showError(msg) {
70
- console.error('[PDF-Secure][Viewer] ERROR ' + filename + ':', msg);
71
- loadingEl.style.display = 'none';
72
- canvas.style.display = 'none';
73
- errorEl.style.display = 'flex';
74
- errorEl.textContent = msg;
75
- }
76
-
77
- try {
78
- // Step 1: Fetch nonce
79
- var nonceUrl = config.relative_path + '/api/v3/plugins/pdf-secure/nonce?file=' + encodeURIComponent(filename);
80
- console.log('[PDF-Secure][Viewer] Step 1 - Nonce request:', nonceUrl);
81
-
82
- var nonceRes = await fetch(nonceUrl, {
83
- credentials: 'same-origin',
84
- headers: { 'x-csrf-token': config.csrf_token },
85
- });
86
- console.log('[PDF-Secure][Viewer] Step 1 - Status:', nonceRes.status);
87
-
88
- if (!nonceRes.ok) {
89
- showError(nonceRes.status === 401 ? 'Log in to view this PDF.' : 'Failed to load PDF (' + nonceRes.status + ')');
90
- return;
91
- }
92
-
93
- var result = await nonceRes.json();
94
- var nonce = result.response.nonce;
95
- console.log('[PDF-Secure][Viewer] Step 1 - Nonce:', nonce);
96
-
97
- // Step 2: Fetch PDF binary
98
- var pdfUrl = config.relative_path + '/api/v3/plugins/pdf-secure/pdf-data?nonce=' + encodeURIComponent(nonce);
99
- console.log('[PDF-Secure][Viewer] Step 2 - PDF request:', pdfUrl);
100
-
101
- var pdfRes = await fetch(pdfUrl, { credentials: 'same-origin' });
102
- console.log('[PDF-Secure][Viewer] Step 2 - Status:', pdfRes.status);
103
-
104
- if (!pdfRes.ok) {
105
- showError('Failed to load PDF data (' + pdfRes.status + ')');
106
- return;
107
- }
108
-
109
- var pdfArrayBuffer = await pdfRes.arrayBuffer();
110
- console.log('[PDF-Secure][Viewer] Step 2 - PDF loaded:', pdfArrayBuffer.byteLength, 'bytes');
111
-
112
- // Step 3: Render PDF
113
- console.log('[PDF-Secure][Viewer] Step 3 - Rendering...');
114
- var pdfDoc = await getDocument({ data: new Uint8Array(pdfArrayBuffer) }).promise;
115
- var totalPages = pdfDoc.numPages;
116
- console.log('[PDF-Secure][Viewer] Step 3 - Pages:', totalPages);
117
-
118
- loadingEl.style.display = 'none';
119
- canvas.style.display = 'block';
120
-
121
- // Security: scoped to container
122
- container.addEventListener('contextmenu', function (e) { e.preventDefault(); });
123
- container.addEventListener('dragstart', function (e) { e.preventDefault(); });
124
- container.addEventListener('selectstart', function (e) { e.preventDefault(); });
125
-
126
- var ctx = canvas.getContext('2d');
127
- var currentPage = 1;
128
- var rendering = false;
129
-
130
- async function renderPage(pageNum) {
131
- if (rendering) return;
132
- rendering = true;
133
- console.log('[PDF-Secure][Viewer] renderPage(' + pageNum + ')');
134
-
135
- try {
136
- var page = await pdfDoc.getPage(pageNum);
137
- var containerWidth = bodyEl.clientWidth - 20;
138
- var vp = page.getViewport({ scale: 1 });
139
- var scale = Math.min(containerWidth / vp.width, 2.0);
140
- var scaled = page.getViewport({ scale: scale });
141
-
142
- canvas.width = scaled.width;
143
- canvas.height = scaled.height;
144
-
145
- await page.render({ canvasContext: ctx, viewport: scaled }).promise;
146
-
147
- currentPage = pageNum;
148
- pageInfo.textContent = currentPage + ' / ' + totalPages;
149
- prevBtn.disabled = currentPage <= 1;
150
- nextBtn.disabled = currentPage >= totalPages;
151
- console.log('[PDF-Secure][Viewer] renderPage(' + pageNum + ') done, canvas:', scaled.width + 'x' + scaled.height);
152
- } catch (err) {
153
- console.error('[PDF-Secure][Viewer] Render error:', err);
154
- showError('Error rendering page.');
155
- }
156
- rendering = false;
157
- }
158
-
159
- await renderPage(1);
160
-
161
- if (totalPages > 1) {
162
- footer.style.display = 'flex';
163
- prevBtn.addEventListener('click', function () {
164
- if (currentPage > 1) renderPage(currentPage - 1);
165
- });
166
- nextBtn.addEventListener('click', function () {
167
- if (currentPage < totalPages) renderPage(currentPage + 1);
168
- });
169
- console.log('[PDF-Secure][Viewer] Navigation enabled (' + totalPages + ' pages)');
170
- }
171
-
172
- console.log('[PDF-Secure][Viewer] DONE for:', filename);
173
- } catch (err) {
174
- console.error('[PDF-Secure][Viewer] CATCH:', err);
175
- console.error('[PDF-Secure][Viewer] Stack:', err.stack);
176
- showError('Failed to load PDF.');
177
- }
178
- }
179
-
180
- function escapeHtml(str) {
181
- var d = document.createElement('div');
182
- d.textContent = str;
183
- return d.innerHTML;
184
- }