Check if file is encrypted without password

This commit is contained in:
Reece Browne 2024-12-09 13:20:08 +00:00
parent 6ee6254f5a
commit 1d6511b043
2 changed files with 60 additions and 36 deletions

View File

@ -1,34 +1,30 @@
export class DecryptFile { export class DecryptFile {
async decryptFile(file) { async decryptFile(file, requiresPassword) {
try { 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(); const formData = new FormData();
formData.append('fileInput', file); 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 // Send decryption request
const response = await fetch('/api/v1/security/remove-password', { const response = await fetch('/api/v1/security/remove-password', {
method: 'POST', method: 'POST',
@ -64,17 +60,35 @@ export class DecryptFile {
async checkFileEncrypted(file) { async checkFileEncrypted(file) {
try { try {
pdfjsLib.GlobalWorkerOptions.workerSrc = './pdfjs-legacy/pdf.worker.mjs'; pdfjsLib.GlobalWorkerOptions.workerSrc = './pdfjs-legacy/pdf.worker.mjs';
const arrayBuffer = await file.arrayBuffer(); // Convert file to ArrayBuffer const arrayBuffer = await file.arrayBuffer();
await pdfjsLib.getDocument({ const arrayBufferForPdfLib = arrayBuffer.slice(0);
data: arrayBuffer,
password: '',
}).promise;
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) { } catch (error) {
if (error.name === 'PasswordException') { 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); console.error('Error checking encryption:', error);
throw new Error('Failed to determine if the file is encrypted.'); throw new Error('Failed to determine if the file is encrypted.');
} }

View File

@ -178,9 +178,19 @@ class PdfContainer {
try { try {
let decryptedFile = files[i]; let decryptedFile = files[i];
let isEncrypted = false;
if (decryptedFile.type === 'application/pdf' && (await this.decryptFile.checkFileEncrypted(decryptedFile))) { let requiresPassword = false;
decryptedFile = await this.decryptFile.decryptFile(decryptedFile); 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) { if (!decryptedFile) {
throw new Error('File decryption failed.'); throw new Error('File decryption failed.');
} }