nodebb-plugin-pdf-secure 1.0.1 → 1.0.2
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/lib/main.js +21 -3
- package/static/lib/viewer.js +25 -48
package/package.json
CHANGED
package/static/lib/main.js
CHANGED
|
@@ -65,24 +65,42 @@
|
|
|
65
65
|
const result = await response.json();
|
|
66
66
|
const { nonce, isPremium } = result.response;
|
|
67
67
|
|
|
68
|
+
// Fetch PDF binary in parent (before iframe creation)
|
|
69
|
+
const pdfResponse = await fetch(
|
|
70
|
+
`${config.relative_path}/api/v3/plugins/pdf-secure/pdf-data?nonce=${encodeURIComponent(nonce)}`,
|
|
71
|
+
{ credentials: 'same-origin' }
|
|
72
|
+
);
|
|
73
|
+
if (!pdfResponse.ok) {
|
|
74
|
+
app.alertError('Failed to load PDF data.');
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
const pdfArrayBuffer = await pdfResponse.arrayBuffer();
|
|
78
|
+
|
|
68
79
|
// Create overlay with iframe
|
|
69
80
|
const overlay = document.createElement('div');
|
|
70
81
|
overlay.className = 'pdf-secure-overlay';
|
|
71
82
|
overlay.id = 'pdf-secure-overlay';
|
|
72
83
|
|
|
73
84
|
const iframe = document.createElement('iframe');
|
|
74
|
-
const viewerUrl = `${config.relative_path}/plugins/nodebb-plugin-pdf-secure/static/lib/viewer.html
|
|
85
|
+
const viewerUrl = `${config.relative_path}/plugins/nodebb-plugin-pdf-secure/static/lib/viewer.html`;
|
|
75
86
|
iframe.src = viewerUrl;
|
|
76
87
|
iframe.className = 'pdf-secure-iframe';
|
|
77
|
-
iframe.setAttribute('sandbox', 'allow-scripts
|
|
88
|
+
iframe.setAttribute('sandbox', 'allow-scripts');
|
|
78
89
|
|
|
79
90
|
overlay.appendChild(iframe);
|
|
80
91
|
document.body.appendChild(overlay);
|
|
81
92
|
|
|
82
|
-
// Listen for
|
|
93
|
+
// Listen for messages from viewer
|
|
83
94
|
function onMessage(e) {
|
|
95
|
+
if (e.source !== iframe.contentWindow) return;
|
|
84
96
|
if (e.data && e.data.type === 'pdf-viewer-close') {
|
|
85
97
|
closeOverlay();
|
|
98
|
+
} else if (e.data && e.data.type === 'pdf-viewer-ready') {
|
|
99
|
+
iframe.contentWindow.postMessage(
|
|
100
|
+
{ type: 'pdf-data', pdf: pdfArrayBuffer, isPremium: isPremium },
|
|
101
|
+
'*',
|
|
102
|
+
[pdfArrayBuffer]
|
|
103
|
+
);
|
|
86
104
|
}
|
|
87
105
|
}
|
|
88
106
|
window.addEventListener('message', onMessage);
|
package/static/lib/viewer.js
CHANGED
|
@@ -49,17 +49,6 @@ let currentPage = 1;
|
|
|
49
49
|
let totalPages = 0;
|
|
50
50
|
let rendering = false;
|
|
51
51
|
|
|
52
|
-
// Parse URL parameters
|
|
53
|
-
const params = new URLSearchParams(window.location.search);
|
|
54
|
-
const nonce = params.get('nonce');
|
|
55
|
-
const isPremium = params.get('premium') === 'true';
|
|
56
|
-
const apiBase = params.get('apiBase') || '';
|
|
57
|
-
|
|
58
|
-
// Show premium banner for non-premium users
|
|
59
|
-
if (!isPremium) {
|
|
60
|
-
premiumBanner.style.display = 'block';
|
|
61
|
-
}
|
|
62
|
-
|
|
63
52
|
// Close button handler
|
|
64
53
|
closeBtn.addEventListener('click', () => {
|
|
65
54
|
if (window.parent && window.parent !== window) {
|
|
@@ -129,53 +118,41 @@ document.addEventListener('keydown', (e) => {
|
|
|
129
118
|
}
|
|
130
119
|
});
|
|
131
120
|
|
|
132
|
-
//
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
121
|
+
// Handle window resize
|
|
122
|
+
let resizeTimeout;
|
|
123
|
+
window.addEventListener('resize', () => {
|
|
124
|
+
clearTimeout(resizeTimeout);
|
|
125
|
+
resizeTimeout = setTimeout(() => {
|
|
126
|
+
if (pdfDoc) renderPage(currentPage);
|
|
127
|
+
}, 250);
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
// 30 second timeout for receiving PDF data
|
|
131
|
+
const dataTimeout = setTimeout(() => {
|
|
132
|
+
showError('Timed out waiting for PDF data.');
|
|
133
|
+
}, 30000);
|
|
134
|
+
|
|
135
|
+
// Listen for PDF data from parent
|
|
136
|
+
window.addEventListener('message', async (e) => {
|
|
137
|
+
if (!e.data || e.data.type !== 'pdf-data') return;
|
|
138
|
+
clearTimeout(dataTimeout);
|
|
139
|
+
|
|
140
|
+
const { pdf, isPremium } = e.data;
|
|
141
|
+
if (!isPremium) {
|
|
142
|
+
premiumBanner.style.display = 'block';
|
|
137
143
|
}
|
|
138
144
|
|
|
139
145
|
try {
|
|
140
|
-
const
|
|
141
|
-
credentials: 'same-origin',
|
|
142
|
-
});
|
|
143
|
-
|
|
144
|
-
if (!response.ok) {
|
|
145
|
-
if (response.status === 401) {
|
|
146
|
-
showError('You must be logged in to view this PDF.');
|
|
147
|
-
} else if (response.status === 403) {
|
|
148
|
-
showError('Access denied. The link may have expired.');
|
|
149
|
-
} else if (response.status === 404) {
|
|
150
|
-
showError('PDF file not found.');
|
|
151
|
-
} else {
|
|
152
|
-
showError('Failed to load PDF.');
|
|
153
|
-
}
|
|
154
|
-
return;
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
const arrayBuffer = await response.arrayBuffer();
|
|
158
|
-
const data = new Uint8Array(arrayBuffer);
|
|
159
|
-
|
|
146
|
+
const data = new Uint8Array(pdf);
|
|
160
147
|
pdfDoc = await getDocument({ data }).promise;
|
|
161
148
|
totalPages = pdfDoc.numPages;
|
|
162
|
-
|
|
163
149
|
loadingEl.style.display = 'none';
|
|
164
150
|
canvas.style.display = 'block';
|
|
165
|
-
|
|
166
151
|
await renderPage(1);
|
|
167
152
|
} catch (err) {
|
|
168
153
|
showError('Failed to load PDF. Please try again.');
|
|
169
154
|
}
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
// Handle window resize
|
|
173
|
-
let resizeTimeout;
|
|
174
|
-
window.addEventListener('resize', () => {
|
|
175
|
-
clearTimeout(resizeTimeout);
|
|
176
|
-
resizeTimeout = setTimeout(() => {
|
|
177
|
-
if (pdfDoc) renderPage(currentPage);
|
|
178
|
-
}, 250);
|
|
179
155
|
});
|
|
180
156
|
|
|
181
|
-
|
|
157
|
+
// Notify parent that viewer is ready (after listener is registered)
|
|
158
|
+
window.parent.postMessage({ type: 'pdf-viewer-ready' }, '*');
|