Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
fpdf_save.cpp
Go to the documentation of this file.
1// Copyright 2014 The PDFium Authors
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7#include "public/fpdf_save.h"
8
9#include <optional>
10#include <utility>
11#include <vector>
12
13#include "build/build_config.h"
14#include "core/fpdfapi/edit/cpdf_creator.h"
15#include "core/fpdfapi/parser/cpdf_array.h"
16#include "core/fpdfapi/parser/cpdf_dictionary.h"
17#include "core/fpdfapi/parser/cpdf_document.h"
18#include "core/fpdfapi/parser/cpdf_reference.h"
19#include "core/fpdfapi/parser/cpdf_stream_acc.h"
20#include "core/fpdfapi/parser/cpdf_string.h"
21#include "core/fxcrt/fx_extension.h"
22#include "core/fxcrt/stl_util.h"
23#include "fpdfsdk/cpdfsdk_filewriteadapter.h"
24#include "fpdfsdk/cpdfsdk_helpers.h"
25#include "public/fpdf_edit.h"
26
27#ifdef PDF_ENABLE_XFA
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"
32#endif
33
34namespace {
35
36#ifdef PDF_ENABLE_XFA
37bool SaveXFADocumentData(CPDFXFA_Context* pContext,
38 std::vector<RetainPtr<IFX_SeekableStream>>* fileList) {
39 if (!pContext)
40 return false;
41
42 if (!pContext->ContainsExtensionForm())
43 return true;
44
45 CPDF_Document* pPDFDocument = pContext->GetPDFDoc();
46 if (!pPDFDocument)
47 return false;
48
49 RetainPtr<CPDF_Dictionary> pRoot = pPDFDocument->GetMutableRoot();
50 if (!pRoot)
51 return false;
52
53 RetainPtr<CPDF_Dictionary> pAcroForm = pRoot->GetMutableDictFor("AcroForm");
54 if (!pAcroForm)
55 return false;
56
57 RetainPtr<CPDF_Object> pXFA = pAcroForm->GetMutableObjectFor("XFA");
58 if (!pXFA)
59 return true;
60
61 CPDF_Array* pArray = pXFA->AsMutableArray();
62 if (!pArray)
63 return false;
64
65 int size = fxcrt::CollectionSize<int>(*pArray);
66 int iFormIndex = -1;
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())
71 continue;
72 if (pPDFObj->GetString() == "form")
73 iFormIndex = i + 1;
74 else if (pPDFObj->GetString() == "datasets")
75 iDataSetsIndex = i + 1;
76 }
77
78 RetainPtr<CPDF_Stream> pFormStream;
79 if (iFormIndex != -1) {
80 // Get form CPDF_Stream
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());
86 }
87 } else if (pFormPDFObj->IsStream()) {
88 pFormStream.Reset(pFormPDFObj->AsMutableStream());
89 }
90 }
91
92 RetainPtr<CPDF_Stream> pDataSetsStream;
93 if (iDataSetsIndex != -1) {
94 // Get datasets CPDF_Stream
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());
103 }
104 } else if (pDataSetsPDFObj->IsStream()) {
105 pDataSetsStream.Reset(pDataSetsPDFObj->AsMutableStream());
106 }
107 }
108 // L"datasets"
109 {
110 RetainPtr<IFX_SeekableStream> pFileWrite =
111 pdfium::MakeRetain<CFX_MemoryStream>();
112 if (pContext->SaveDatasetsPackage(pFileWrite) &&
113 pFileWrite->GetSize() > 0) {
114 if (iDataSetsIndex != -1) {
115 if (pDataSetsStream) {
116 pDataSetsStream->InitStreamFromFile(pFileWrite);
117 }
118 } else {
119 auto data_stream = pPDFDocument->NewIndirect<CPDF_Stream>(
120 pFileWrite, pPDFDocument->New<CPDF_Dictionary>());
121 int iLast = fxcrt::CollectionSize<int>(*pArray) - 2;
122 pArray->InsertNewAt<CPDF_String>(iLast, "datasets");
123 pArray->InsertNewAt<CPDF_Reference>(iLast + 1, pPDFDocument,
124 data_stream->GetObjNum());
125 }
126 fileList->push_back(std::move(pFileWrite));
127 }
128 }
129 // L"form"
130 {
131 RetainPtr<IFX_SeekableStream> pFileWrite =
132 pdfium::MakeRetain<CFX_MemoryStream>();
133 if (pContext->SaveFormPackage(pFileWrite) && pFileWrite->GetSize() > 0) {
134 if (iFormIndex != -1) {
135 if (pFormStream) {
136 pFormStream->InitStreamFromFile(pFileWrite);
137 }
138 } else {
139 auto data_stream = pPDFDocument->NewIndirect<CPDF_Stream>(
140 pFileWrite, pPDFDocument->New<CPDF_Dictionary>());
141 int iLast = fxcrt::CollectionSize<int>(*pArray) - 2;
142 pArray->InsertNewAt<CPDF_String>(iLast, "form");
143 pArray->InsertNewAt<CPDF_Reference>(iLast + 1, pPDFDocument,
144 data_stream->GetObjNum());
145 }
146 fileList->push_back(std::move(pFileWrite));
147 }
148 }
149 return true;
150}
151#endif // PDF_ENABLE_XFA
152
153bool DoDocSave(FPDF_DOCUMENT document,
154 FPDF_FILEWRITE* pFileWrite,
155 FPDF_DWORD flags,
156 std::optional<int> version) {
158 if (!pPDFDoc)
159 return false;
160
161#ifdef PDF_ENABLE_XFA
162 auto* pContext = static_cast<CPDFXFA_Context*>(pPDFDoc->GetExtension());
163 if (pContext) {
164 std::vector<RetainPtr<IFX_SeekableStream>> fileList;
165 pContext->SendPreSaveToXFADoc(&fileList);
166 SaveXFADocumentData(pContext, &fileList);
167 }
168#endif // PDF_ENABLE_XFA
169
170 if (flags < FPDF_INCREMENTAL || flags > FPDF_REMOVE_SECURITY)
171 flags = 0;
172
173 CPDF_Creator fileMaker(
174 pPDFDoc, pdfium::MakeRetain<CPDFSDK_FileWriteAdapter>(pFileWrite));
175 if (version.has_value())
176 fileMaker.SetFileVersion(version.value());
177 if (flags == FPDF_REMOVE_SECURITY) {
178 flags = 0;
179 fileMaker.RemoveSecurity();
180 }
181
182 bool bRet = fileMaker.Create(static_cast<uint32_t>(flags));
183
184#ifdef PDF_ENABLE_XFA
185 if (pContext)
186 pContext->SendPostSaveToXFADoc();
187#endif // PDF_ENABLE_XFA
188
189 return bRet;
190}
191
192} // namespace
193
194FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_SaveAsCopy(FPDF_DOCUMENT document,
195 FPDF_FILEWRITE* pFileWrite,
196 FPDF_DWORD flags) {
197 return DoDocSave(document, pFileWrite, flags, {});
198}
199
201FPDF_SaveWithVersion(FPDF_DOCUMENT document,
202 FPDF_FILEWRITE* pFileWrite,
203 FPDF_DWORD flags,
204 int fileVersion) {
205 return DoDocSave(document, pFileWrite, flags, fileVersion);
206}
bool SetFileVersion(int32_t fileVersion)
void RemoveSecurity()
bool Create(uint32_t flags)
CPDF_Document * CPDFDocumentFromFPDFDocument(FPDF_DOCUMENT doc)
#define FPDF_INCREMENTAL
Definition fpdf_save.h:45
#define FPDF_REMOVE_SECURITY
Definition fpdf_save.h:47
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)
#define FPDF_CALLCONV
Definition fpdfview.h:229
#define FPDF_EXPORT
Definition fpdfview.h:223