Merge pull request #14067 from calixteman/1732344

Don't save anything in XFA entry if no XFA! (bug 1732344)
This commit is contained in:
Brendan Dahl 2021-09-23 15:07:00 -07:00 committed by GitHub
commit d370a281c4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 60 additions and 32 deletions

View File

@ -624,18 +624,18 @@ class WorkerMessageHandler {
} }
const xfa = (acroForm instanceof Dict && acroForm.get("XFA")) || null; const xfa = (acroForm instanceof Dict && acroForm.get("XFA")) || null;
let xfaDatasets = null; let xfaDatasetsRef = null;
let hasDatasets = false; let hasXfaDatasetsEntry = false;
if (Array.isArray(xfa)) { if (Array.isArray(xfa)) {
for (let i = 0, ii = xfa.length; i < ii; i += 2) { for (let i = 0, ii = xfa.length; i < ii; i += 2) {
if (xfa[i] === "datasets") { if (xfa[i] === "datasets") {
xfaDatasets = xfa[i + 1]; xfaDatasetsRef = xfa[i + 1];
acroFormRef = null; acroFormRef = null;
hasDatasets = true; hasXfaDatasetsEntry = true;
} }
} }
if (xfaDatasets === null) { if (xfaDatasetsRef === null) {
xfaDatasets = xref.getNewRef(); xfaDatasetsRef = xref.getNewRef();
} }
} else if (xfa) { } else if (xfa) {
acroFormRef = null; acroFormRef = null;
@ -674,8 +674,9 @@ class WorkerMessageHandler {
xrefInfo: newXrefInfo, xrefInfo: newXrefInfo,
newRefs, newRefs,
xref, xref,
datasetsRef: xfaDatasets, hasXfa: !!xfa,
hasDatasets, xfaDatasetsRef,
hasXfaDatasetsEntry,
acroFormRef, acroFormRef,
acroForm, acroForm,
xfaData, xfaData,

View File

@ -154,8 +154,8 @@ function writeXFADataForAcroform(str, newRefs) {
function updateXFA({ function updateXFA({
xfaData, xfaData,
datasetsRef, xfaDatasetsRef,
hasDatasets, hasXfaDatasetsEntry,
acroFormRef, acroFormRef,
acroForm, acroForm,
newRefs, newRefs,
@ -166,7 +166,7 @@ function updateXFA({
return; return;
} }
if (!hasDatasets) { if (!hasXfaDatasetsEntry) {
if (!acroFormRef) { if (!acroFormRef) {
warn("XFA - Cannot save it"); warn("XFA - Cannot save it");
return; return;
@ -178,7 +178,7 @@ function updateXFA({
const oldXfa = acroForm.get("XFA"); const oldXfa = acroForm.get("XFA");
const newXfa = oldXfa.slice(); const newXfa = oldXfa.slice();
newXfa.splice(2, 0, "datasets"); newXfa.splice(2, 0, "datasets");
newXfa.splice(3, 0, datasetsRef); newXfa.splice(3, 0, xfaDatasetsRef);
acroForm.set("XFA", newXfa); acroForm.set("XFA", newXfa);
@ -201,25 +201,25 @@ function updateXFA({
} }
if (xfaData === null) { if (xfaData === null) {
const datasets = xref.fetchIfRef(datasetsRef); const datasets = xref.fetchIfRef(xfaDatasetsRef);
xfaData = writeXFADataForAcroform(datasets.getString(), newRefs); xfaData = writeXFADataForAcroform(datasets.getString(), newRefs);
} }
const encrypt = xref.encrypt; const encrypt = xref.encrypt;
if (encrypt) { if (encrypt) {
const transform = encrypt.createCipherTransform( const transform = encrypt.createCipherTransform(
datasetsRef.num, xfaDatasetsRef.num,
datasetsRef.gen xfaDatasetsRef.gen
); );
xfaData = transform.encryptString(xfaData); xfaData = transform.encryptString(xfaData);
} }
const data = const data =
`${datasetsRef.num} ${datasetsRef.gen} obj\n` + `${xfaDatasetsRef.num} ${xfaDatasetsRef.gen} obj\n` +
`<< /Type /EmbeddedFile /Length ${xfaData.length}>>\nstream\n` + `<< /Type /EmbeddedFile /Length ${xfaData.length}>>\nstream\n` +
xfaData + xfaData +
"\nendstream\nendobj\n"; "\nendstream\nendobj\n";
newRefs.push({ ref: datasetsRef, data }); newRefs.push({ ref: xfaDatasetsRef, data });
} }
function incrementalUpdate({ function incrementalUpdate({
@ -227,22 +227,25 @@ function incrementalUpdate({
xrefInfo, xrefInfo,
newRefs, newRefs,
xref = null, xref = null,
datasetsRef = null, hasXfa = false,
hasDatasets = false, xfaDatasetsRef = null,
hasXfaDatasetsEntry = false,
acroFormRef = null, acroFormRef = null,
acroForm = null, acroForm = null,
xfaData = null, xfaData = null,
}) { }) {
updateXFA({ if (hasXfa) {
xfaData, updateXFA({
datasetsRef, xfaData,
hasDatasets, xfaDatasetsRef,
acroFormRef, hasXfaDatasetsEntry,
acroForm, acroFormRef,
newRefs, acroForm,
xref, newRefs,
xrefInfo, xref,
}); xrefInfo,
});
}
const newXref = new Dict(null); const newXref = new Dict(null);
const refForXrefTable = xrefInfo.newRef; const refForXrefTable = xrefInfo.newRef;

View File

@ -1283,6 +1283,28 @@ describe("api", function () {
await Promise.all([loadingTask1.destroy(), loadingTask2.destroy()]); await Promise.all([loadingTask1.destroy(), loadingTask2.destroy()]);
}); });
it("write a value in an annotation, save the pdf and load it", async function () {
let loadingTask = getDocument(buildGetDocumentParams("evaljs.pdf"));
let pdfDoc = await loadingTask.promise;
const value = "Hello World";
pdfDoc.annotationStorage.setValue("55R", { value });
const data = await pdfDoc.saveDocument();
await loadingTask.destroy();
loadingTask = getDocument(data);
pdfDoc = await loadingTask.promise;
const pdfPage = await pdfDoc.getPage(1);
const annotations = await pdfPage.getAnnotations();
const field = annotations.find(annotation => annotation.id === "55R");
expect(!!field).toEqual(true);
expect(field.fieldValue).toEqual(value);
await loadingTask.destroy();
});
describe("Cross-origin", function () { describe("Cross-origin", function () {
let loadingTask; let loadingTask;
function _checkCanLoad(expectSuccess, filename, options) { function _checkCanLoad(expectSuccess, filename, options) {

View File

@ -162,7 +162,7 @@ describe("Writer", function () {
Ref.get(456, 0), Ref.get(456, 0),
]); ]);
const acroFormRef = Ref.get(789, 0); const acroFormRef = Ref.get(789, 0);
const datasetsRef = Ref.get(101112, 0); const xfaDatasetsRef = Ref.get(101112, 0);
const xfaData = "<hello>world</hello>"; const xfaData = "<hello>world</hello>";
const xrefInfo = { const xrefInfo = {
@ -180,8 +180,9 @@ describe("Writer", function () {
originalData, originalData,
xrefInfo, xrefInfo,
newRefs, newRefs,
datasetsRef, hasXfa: true,
hasDatasets: false, xfaDatasetsRef,
hasXfaDatasetsEntry: false,
acroFormRef, acroFormRef,
acroForm, acroForm,
xfaData, xfaData,

View File

@ -1015,6 +1015,7 @@ const PDFViewerApplication = {
} catch (reason) { } catch (reason) {
// When the PDF document isn't ready, or the PDF file is still // When the PDF document isn't ready, or the PDF file is still
// downloading, simply fallback to a "regular" download. // downloading, simply fallback to a "regular" download.
console.error(`Error when saving the document: ${reason.message}`);
await this.download({ sourceEventType }); await this.download({ sourceEventType });
} finally { } finally {
await this.pdfScriptingManager.dispatchDidSave(); await this.pdfScriptingManager.dispatchDidSave();