feat(pdf-tools): add remove-restrictions tool for unlocking pdfs
Implement new feature to remove security restrictions from PDFs including password protection and digital signature limitations. The tool allows users to unlock PDFs they have legitimate access to for editing and printing purposes. Includes UI components, error handling, and legal disclaimer about proper usage.
This commit is contained in:
@@ -1,18 +1,22 @@
|
||||
import { showLoader, hideLoader, showAlert } from '../ui.js';
|
||||
import { downloadFile, initializeQpdf, readFileAsArrayBuffer } from '../utils/helpers.js';
|
||||
import {
|
||||
downloadFile,
|
||||
initializeQpdf,
|
||||
readFileAsArrayBuffer,
|
||||
} from '../utils/helpers.js';
|
||||
import { state } from '../state.js';
|
||||
|
||||
export async function changePermissions() {
|
||||
const file = state.files[0];
|
||||
const currentPassword = (
|
||||
document.getElementById('current-password') as HTMLInputElement
|
||||
)?.value || '';
|
||||
const newUserPassword = (
|
||||
document.getElementById('new-user-password') as HTMLInputElement
|
||||
)?.value || '';
|
||||
const newOwnerPassword = (
|
||||
document.getElementById('new-owner-password') as HTMLInputElement
|
||||
)?.value || '';
|
||||
const currentPassword =
|
||||
(document.getElementById('current-password') as HTMLInputElement)?.value ||
|
||||
'';
|
||||
const newUserPassword =
|
||||
(document.getElementById('new-user-password') as HTMLInputElement)?.value ||
|
||||
'';
|
||||
const newOwnerPassword =
|
||||
(document.getElementById('new-owner-password') as HTMLInputElement)
|
||||
?.value || '';
|
||||
|
||||
const inputPath = '/input.pdf';
|
||||
const outputPath = '/output.pdf';
|
||||
@@ -37,21 +41,34 @@ export async function changePermissions() {
|
||||
}
|
||||
|
||||
const shouldEncrypt = newUserPassword || newOwnerPassword;
|
||||
|
||||
|
||||
if (shouldEncrypt) {
|
||||
const finalUserPassword = newUserPassword;
|
||||
const finalOwnerPassword = newOwnerPassword;
|
||||
|
||||
args.push('--encrypt', finalUserPassword, finalOwnerPassword, '256');
|
||||
|
||||
// Get permission checkboxes
|
||||
const allowPrinting = (document.getElementById('allow-printing') as HTMLInputElement)?.checked;
|
||||
const allowCopying = (document.getElementById('allow-copying') as HTMLInputElement)?.checked;
|
||||
const allowModifying = (document.getElementById('allow-modifying') as HTMLInputElement)?.checked;
|
||||
const allowAnnotating = (document.getElementById('allow-annotating') as HTMLInputElement)?.checked;
|
||||
const allowFillingForms = (document.getElementById('allow-filling-forms') as HTMLInputElement)?.checked;
|
||||
const allowDocumentAssembly = (document.getElementById('allow-document-assembly') as HTMLInputElement)?.checked;
|
||||
const allowPageExtraction = (document.getElementById('allow-page-extraction') as HTMLInputElement)?.checked;
|
||||
const allowPrinting = (
|
||||
document.getElementById('allow-printing') as HTMLInputElement
|
||||
)?.checked;
|
||||
const allowCopying = (
|
||||
document.getElementById('allow-copying') as HTMLInputElement
|
||||
)?.checked;
|
||||
const allowModifying = (
|
||||
document.getElementById('allow-modifying') as HTMLInputElement
|
||||
)?.checked;
|
||||
const allowAnnotating = (
|
||||
document.getElementById('allow-annotating') as HTMLInputElement
|
||||
)?.checked;
|
||||
const allowFillingForms = (
|
||||
document.getElementById('allow-filling-forms') as HTMLInputElement
|
||||
)?.checked;
|
||||
const allowDocumentAssembly = (
|
||||
document.getElementById('allow-document-assembly') as HTMLInputElement
|
||||
)?.checked;
|
||||
const allowPageExtraction = (
|
||||
document.getElementById('allow-page-extraction') as HTMLInputElement
|
||||
)?.checked;
|
||||
|
||||
if (finalOwnerPassword) {
|
||||
if (!allowModifying) args.push('--modify=none');
|
||||
@@ -71,28 +88,28 @@ export async function changePermissions() {
|
||||
}
|
||||
|
||||
args.push('--', outputPath);
|
||||
|
||||
console.log('qpdf args:', args);
|
||||
|
||||
try {
|
||||
qpdf.callMain(args);
|
||||
} catch (qpdfError: any) {
|
||||
console.error('qpdf execution error:', qpdfError);
|
||||
|
||||
// Check for various password-related errors
|
||||
|
||||
const errorMsg = qpdfError.message || '';
|
||||
|
||||
if (errorMsg.includes('invalid password') ||
|
||||
errorMsg.includes('incorrect password') ||
|
||||
errorMsg.includes('password')) {
|
||||
|
||||
if (
|
||||
errorMsg.includes('invalid password') ||
|
||||
errorMsg.includes('incorrect password') ||
|
||||
errorMsg.includes('password')
|
||||
) {
|
||||
throw new Error('INVALID_PASSWORD');
|
||||
}
|
||||
|
||||
if (errorMsg.includes('encrypted') ||
|
||||
errorMsg.includes('password required')) {
|
||||
|
||||
if (
|
||||
errorMsg.includes('encrypted') ||
|
||||
errorMsg.includes('password required')
|
||||
) {
|
||||
throw new Error('PASSWORD_REQUIRED');
|
||||
}
|
||||
|
||||
|
||||
throw new Error('Processing failed: ' + errorMsg || 'Unknown error');
|
||||
}
|
||||
|
||||
@@ -107,17 +124,18 @@ export async function changePermissions() {
|
||||
downloadFile(blob, `permissions-changed-${file.name}`);
|
||||
|
||||
hideLoader();
|
||||
|
||||
|
||||
let successMessage = 'PDF permissions changed successfully!';
|
||||
if (!shouldEncrypt) {
|
||||
successMessage = 'PDF decrypted successfully! All encryption and restrictions removed.';
|
||||
successMessage =
|
||||
'PDF decrypted successfully! All encryption and restrictions removed.';
|
||||
}
|
||||
|
||||
|
||||
showAlert('Success', successMessage);
|
||||
} catch (error: any) {
|
||||
console.error('Error during PDF permission change:', error);
|
||||
hideLoader();
|
||||
|
||||
|
||||
if (error.message === 'INVALID_PASSWORD') {
|
||||
showAlert(
|
||||
'Incorrect Password',
|
||||
@@ -139,17 +157,13 @@ export async function changePermissions() {
|
||||
if (qpdf?.FS) {
|
||||
try {
|
||||
qpdf.FS.unlink(inputPath);
|
||||
} catch (e) {
|
||||
|
||||
}
|
||||
} catch (e) {}
|
||||
try {
|
||||
qpdf.FS.unlink(outputPath);
|
||||
} catch (e) {
|
||||
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
} catch (cleanupError) {
|
||||
console.warn('Failed to cleanup WASM FS:', cleanupError);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user