7#include "public/fpdf_save.h"
12#include "build/build_config.h"
13#include "core/fpdfapi/edit/cpdf_creator.h"
14#include "core/fpdfapi/parser/cpdf_array.h"
15#include "core/fpdfapi/parser/cpdf_dictionary.h"
16#include "core/fpdfapi/parser/cpdf_document.h"
17#include "core/fpdfapi/parser/cpdf_reference.h"
18#include "core/fpdfapi/parser/cpdf_stream_acc.h"
19#include "core/fpdfapi/parser/cpdf_string.h"
20#include "core/fxcrt/fx_extension.h"
21#include "core/fxcrt/stl_util.h"
22#include "fpdfsdk/cpdfsdk_filewriteadapter.h"
23#include "fpdfsdk/cpdfsdk_helpers.h"
24#include "public/fpdf_edit.h"
25#include "third_party/abseil-cpp/absl/types/optional.h"
28#include "core/fpdfapi/parser/cpdf_stream.h"
29#include "core/fxcrt/cfx_memorystream.h"
30#include "fpdfsdk/fpdfxfa/cpdfxfa_context.h"
31#include "public/fpdf_formfill.h"
37bool SaveXFADocumentData(CPDFXFA_Context* pContext,
38 std::vector<RetainPtr<IFX_SeekableStream>>* fileList) {
42 if (!pContext->ContainsExtensionForm())
45 CPDF_Document* pPDFDocument = pContext->GetPDFDoc();
49 RetainPtr<CPDF_Dictionary> pRoot = pPDFDocument->GetMutableRoot();
53 RetainPtr<CPDF_Dictionary> pAcroForm = pRoot->GetMutableDictFor(
"AcroForm");
57 RetainPtr<CPDF_Object> pXFA = pAcroForm->GetMutableObjectFor(
"XFA");
61 CPDF_Array* pArray = pXFA->AsMutableArray();
65 int size = fxcrt::CollectionSize<
int>(*pArray);
67 int iDataSetsIndex = -1;
68 for (
int i = 0; i < size - 1; i++) {
69 RetainPtr<
const CPDF_Object> pPDFObj = pArray->GetObjectAt(i);
70 if (!pPDFObj->IsString())
72 if (pPDFObj->GetString() ==
"form")
74 else if (pPDFObj->GetString() ==
"datasets")
75 iDataSetsIndex = i + 1;
78 RetainPtr<CPDF_Stream> pFormStream;
79 if (iFormIndex != -1) {
81 RetainPtr<CPDF_Object> pFormPDFObj = pArray->GetMutableObjectAt(iFormIndex);
82 if (pFormPDFObj->IsReference()) {
83 RetainPtr<CPDF_Object> pFormDirectObj = pFormPDFObj->GetMutableDirect();
84 if (pFormDirectObj && pFormDirectObj->IsStream()) {
85 pFormStream.Reset(pFormDirectObj->AsMutableStream());
87 }
else if (pFormPDFObj->IsStream()) {
88 pFormStream.Reset(pFormPDFObj->AsMutableStream());
92 RetainPtr<CPDF_Stream> pDataSetsStream;
93 if (iDataSetsIndex != -1) {
95 RetainPtr<CPDF_Object> pDataSetsPDFObj =
96 pArray->GetMutableObjectAt(iDataSetsIndex);
97 if (pDataSetsPDFObj->IsReference()) {
98 CPDF_Reference* pDataSetsRefObj = pDataSetsPDFObj->AsMutableReference();
99 RetainPtr<CPDF_Object> pDataSetsDirectObj =
100 pDataSetsRefObj->GetMutableDirect();
101 if (pDataSetsDirectObj && pDataSetsDirectObj->IsStream()) {
102 pDataSetsStream.Reset(pDataSetsDirectObj->AsMutableStream());
104 }
else if (pDataSetsPDFObj->IsStream()) {
105 pDataSetsStream.Reset(pDataSetsPDFObj->AsMutableStream());
110 RetainPtr<IFX_SeekableStream> pFileWrite =
111 pdfium::MakeRetain<CFX_MemoryStream>();
112 if (pContext->SaveDatasetsPackage(pFileWrite) &&
113 pFileWrite->GetSize() > 0) {
114 auto pDataDict = pPDFDocument->New<CPDF_Dictionary>();
115 if (iDataSetsIndex != -1) {
116 if (pDataSetsStream) {
117 pDataSetsStream->InitStreamFromFile(pFileWrite, std::move(pDataDict));
120 auto pData = pPDFDocument->NewIndirect<CPDF_Stream>();
121 pData->InitStreamFromFile(pFileWrite, std::move(pDataDict));
122 int iLast = fxcrt::CollectionSize<
int>(*pArray) - 2;
123 pArray->InsertNewAt<CPDF_String>(iLast,
"datasets",
false);
124 pArray->InsertNewAt<CPDF_Reference>(iLast + 1, pPDFDocument,
127 fileList->push_back(std::move(pFileWrite));
132 RetainPtr<IFX_SeekableStream> pFileWrite =
133 pdfium::MakeRetain<CFX_MemoryStream>();
134 if (pContext->SaveFormPackage(pFileWrite) && pFileWrite->GetSize() > 0) {
135 auto pDataDict = pPDFDocument->New<CPDF_Dictionary>();
136 if (iFormIndex != -1) {
138 pFormStream->InitStreamFromFile(pFileWrite, std::move(pDataDict));
140 auto pData = pPDFDocument->NewIndirect<CPDF_Stream>();
141 pData->InitStreamFromFile(pFileWrite, std::move(pDataDict));
142 int iLast = fxcrt::CollectionSize<
int>(*pArray) - 2;
143 pArray->InsertNewAt<CPDF_String>(iLast,
"form",
false);
144 pArray->InsertNewAt<CPDF_Reference>(iLast + 1, pPDFDocument,
147 fileList->push_back(std::move(pFileWrite));
154bool DoDocSave(FPDF_DOCUMENT document,
155 FPDF_FILEWRITE* pFileWrite,
157 absl::optional<
int> version) {
163 auto* pContext =
static_cast<CPDFXFA_Context*>(pPDFDoc->GetExtension());
165 std::vector<RetainPtr<IFX_SeekableStream>> fileList;
166 pContext->SendPreSaveToXFADoc(&fileList);
167 SaveXFADocumentData(pContext, &fileList);
175 pPDFDoc, pdfium::MakeRetain<CPDFSDK_FileWriteAdapter>(pFileWrite));
176 if (version.has_value())
183 bool bRet = fileMaker
.Create(static_cast<uint32_t>(flags)
);
187 pContext->SendPostSaveToXFADoc();
196 FPDF_FILEWRITE* pFileWrite,
198 return DoDocSave(document, pFileWrite, flags, {});
203 FPDF_FILEWRITE* pFileWrite,
206 return DoDocSave(document, pFileWrite, flags, fileVersion);
bool SetFileVersion(int32_t fileVersion)
bool Create(uint32_t flags)
CPDF_Document * CPDFDocumentFromFPDFDocument(FPDF_DOCUMENT doc)
#define FPDF_REMOVE_SECURITY
FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_SaveAsCopy(FPDF_DOCUMENT document, FPDF_FILEWRITE *pFileWrite, FPDF_DWORD flags)
FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_SaveWithVersion(FPDF_DOCUMENT document, FPDF_FILEWRITE *pFileWrite, FPDF_DWORD flags, int fileVersion)