From 1d6511b043cc415018bad04d64787450f09a1f7e Mon Sep 17 00:00:00 2001 From: Reece Browne Date: Mon, 9 Dec 2024 13:20:08 +0000 Subject: [PATCH] Check if file is encrypted without password --- .../static/js/multitool/DecryptFiles.js | 80 +++++++++++-------- .../static/js/multitool/PdfContainer.js | 16 +++- 2 files changed, 60 insertions(+), 36 deletions(-) diff --git a/src/main/resources/static/js/multitool/DecryptFiles.js b/src/main/resources/static/js/multitool/DecryptFiles.js index f050aec1..509c1acd 100644 --- a/src/main/resources/static/js/multitool/DecryptFiles.js +++ b/src/main/resources/static/js/multitool/DecryptFiles.js @@ -1,34 +1,30 @@ export class DecryptFile { - async decryptFile(file) { + async decryptFile(file, requiresPassword) { try { - const password = prompt(`${window.translations.passwordPrompt}`); - - if (password === null) { - // User cancelled - console.error(`Password prompt cancelled for PDF: ${file.name}`); - this.showErrorBanner( - `${window.translations.cancelled.replace('{0}', file.name)}`, - '', - `${window.translations.unexpectedError}` - ); - return null; // No file to return - } - - if (!password) { - // No password provided - console.error(`No password provided for encrypted PDF: ${file.name}`); - this.showErrorBanner( - `${window.translations.noPassword.replace('{0}', file.name)}`, - '', - `${window.translations.unexpectedError}` - ); - return null; // No file to return - } - const formData = new FormData(); formData.append('fileInput', file); - formData.append('password', password); + if (requiresPassword) { + const password = prompt(`${window.translations.passwordPrompt}`); + if (password === null) { + // User cancelled + console.error(`Password prompt cancelled for PDF: ${file.name}`); + return null; // No file to return + } + + if (!password) { + // No password provided + console.error(`No password provided for encrypted PDF: ${file.name}`); + this.showErrorBanner( + `${window.translations.noPassword.replace('{0}', file.name)}`, + '', + `${window.translations.unexpectedError}` + ); + return null; // No file to return + } + + formData.append('password', password); + } // Send decryption request const response = await fetch('/api/v1/security/remove-password', { method: 'POST', @@ -64,17 +60,35 @@ export class DecryptFile { async checkFileEncrypted(file) { try { pdfjsLib.GlobalWorkerOptions.workerSrc = './pdfjs-legacy/pdf.worker.mjs'; - const arrayBuffer = await file.arrayBuffer(); // Convert file to ArrayBuffer - await pdfjsLib.getDocument({ - data: arrayBuffer, - password: '', - }).promise; + const arrayBuffer = await file.arrayBuffer(); + const arrayBufferForPdfLib = arrayBuffer.slice(0); - return false; // File is not encrypted + const loadingTask = pdfjsLib.getDocument({ + data: arrayBuffer, + }); + + await loadingTask.promise; + + try { + //Uses PDFLib.PDFDocument to check if unpassworded but encrypted + const pdfDoc = await PDFLib.PDFDocument.load(arrayBufferForPdfLib); + return {isEncrypted: false, requiresPassword: false}; + } catch (error) { + if (error.message.includes('Input document to `PDFDocument.load` is encrypted')) { + return {isEncrypted: true, requiresPassword: false}; + } + console.error('Error checking encryption:', error); + throw new Error('Failed to determine if the file is encrypted.'); + } } catch (error) { if (error.name === 'PasswordException') { - return true; // File is encrypted + if (error.code === pdfjsLib.PasswordResponses.NEED_PASSWORD) { + return {isEncrypted: true, requiresPassword: true}; + } else if (error.code === pdfjsLib.PasswordResponses.INCORRECT_PASSWORD) { + return {isEncrypted: true, requiresPassword: false}; + } } + console.error('Error checking encryption:', error); throw new Error('Failed to determine if the file is encrypted.'); } diff --git a/src/main/resources/static/js/multitool/PdfContainer.js b/src/main/resources/static/js/multitool/PdfContainer.js index f7fa2536..bbc664f7 100644 --- a/src/main/resources/static/js/multitool/PdfContainer.js +++ b/src/main/resources/static/js/multitool/PdfContainer.js @@ -178,9 +178,19 @@ class PdfContainer { try { let decryptedFile = files[i]; - - if (decryptedFile.type === 'application/pdf' && (await this.decryptFile.checkFileEncrypted(decryptedFile))) { - decryptedFile = await this.decryptFile.decryptFile(decryptedFile); + let isEncrypted = false; + let requiresPassword = false; + await this.decryptFile + .checkFileEncrypted(decryptedFile) + .then((result) => { + isEncrypted = result.isEncrypted; + requiresPassword = result.requiresPassword; + }) + .catch((error) => { + console.error(error); + }); + if (decryptedFile.type === 'application/pdf' && isEncrypted) { + decryptedFile = await this.decryptFile.decryptFile(decryptedFile, requiresPassword); if (!decryptedFile) { throw new Error('File decryption failed.'); }