Merge pull request #21022 from calixteman/bug2028369

Encrypt pdf data when merging the same pdf (bug 2028369)
This commit is contained in:
calixteman 2026-04-01 22:28:59 +02:00 committed by GitHub
commit e37709ea76
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 54 additions and 2 deletions

View File

@ -108,8 +108,16 @@ class XRefWrapper {
}
class PDFEditor {
// Whether the edited PDF contains only one file. This is used to determine if
// we can handle some potential duplications.
// For example, there are no obvious way to dedup page labels when merging
// multiple PDF files.
hasSingleFile = false;
// Whether the edited PDF contains multiple files. This is used to determine
// if we can preserve some information such as passwords.
isSingleFile = false;
#newAnnotationsParams = null;
currentDocument = null;
@ -563,6 +571,9 @@ class PDFEditor {
async extractPages(pageInfos, annotationStorage, handler, task) {
const promises = [];
let newIndex = 0;
this.isSingleFile =
pageInfos.length === 1 ||
pageInfos.every(info => info.document === pageInfos[0].document);
this.hasSingleFile = pageInfos.length === 1;
const allDocumentData = [];
@ -2323,7 +2334,7 @@ class PDFEditor {
*/
#makeInfo() {
const infoMap = new Map();
if (this.hasSingleFile) {
if (this.isSingleFile) {
const {
xref: { trailer },
} = this.oldPages[0].documentData.document;
@ -2356,7 +2367,7 @@ class PDFEditor {
* @returns {Promise<[Dict|null, CipherTransformFactory|null, Array|null]>}
*/
async #makeEncrypt() {
if (!this.hasSingleFile) {
if (!this.isSingleFile) {
return [null, null, null];
}
const { documentData } = this.oldPages[0];

View File

@ -6982,5 +6982,46 @@ small scripts as well as for`);
await newLoadingTask.destroy();
});
});
describe("extract pages from password-protected PDF (bug 2028369)", function () {
it("should preserve password protection when merging the same pdf", async function () {
const loadingTask = getDocument(
buildGetDocumentParams("pr6531_2.pdf", { password: "asdfasdf" })
);
const pdfDoc = await loadingTask.promise;
const data = await pdfDoc.extractPages([
{ document: null },
{ document: null },
]);
await loadingTask.destroy();
// Opening the result without a password must fail.
// Use a copy so the underlying ArrayBuffer is not detached before the
// second getDocument call below.
const passwordNeededLoadingTask = getDocument(data.slice());
await passwordNeededLoadingTask.promise.then(
function () {
// Shouldn't get here.
expect(false).toEqual(true);
},
function (err) {
expect(err).toBeInstanceOf(PasswordException);
expect(err.code).toEqual(PasswordResponses.NEED_PASSWORD);
}
);
await passwordNeededLoadingTask.destroy();
// Opening the result with the correct password must succeed.
const passwordAcceptedLoadingTask = getDocument({
data,
password: "asdfasdf",
});
const newPdfDoc = await passwordAcceptedLoadingTask.promise;
expect(newPdfDoc).toBeInstanceOf(PDFDocumentProxy);
expect(newPdfDoc.numPages).toEqual(2);
await passwordAcceptedLoadingTask.destroy();
});
});
});
});