blob: 13475f690ea39c06e7fc5963a6e93195d544d1c0 [file] [log] [blame]
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07001// Copyright 2014 PDFium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
Lei Zhanga6d9f0e2015-06-13 00:48:38 -07004
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -07005// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
Lei Zhangb4e7f302015-11-06 15:52:32 -08007#include "public/fpdf_save.h"
8
Dan Sinclair85c8e7f2016-11-21 13:50:32 -05009#include <memory>
10#include <utility>
Dan Sinclair3ebd1212016-03-09 09:59:23 -050011#include <vector>
12
dsinclair24154352016-10-04 11:01:48 -070013#include "core/fpdfapi/edit/cpdf_creator.h"
dsinclair488b7ad2016-10-04 11:55:50 -070014#include "core/fpdfapi/parser/cpdf_array.h"
15#include "core/fpdfapi/parser/cpdf_document.h"
16#include "core/fpdfapi/parser/cpdf_reference.h"
17#include "core/fpdfapi/parser/cpdf_stream_acc.h"
18#include "core/fpdfapi/parser/cpdf_string.h"
Dan Sinclair283a0432017-04-20 14:11:21 -040019#include "core/fxcrt/cfx_memorystream.h"
Dan Sinclaircfb19442017-04-20 13:13:04 -040020#include "core/fxcrt/fx_extension.h"
dsinclair114e46a2016-09-29 17:18:21 -070021#include "fpdfsdk/fsdk_define.h"
Dan Sinclairae4656e2017-05-09 12:36:41 -040022#include "fpdfsdk/fsdk_filewriteadapter.h"
Tom Sepez40e9ff32015-11-30 12:39:54 -080023#include "public/fpdf_edit.h"
24
Tom Sepez51da0932015-11-25 16:05:49 -080025#ifdef PDF_ENABLE_XFA
Dan Sinclairddb70162017-03-30 14:01:31 -040026#include "core/fxcrt/cfx_checksumcontext.h"
dsinclair521b7502016-11-02 13:02:28 -070027#include "fpdfsdk/fpdfxfa/cpdfxfa_context.h"
dsinclair4d29e782016-10-04 14:02:47 -070028#include "fpdfsdk/fpdfxfa/cxfa_fwladaptertimermgr.h"
Lei Zhangb4e7f302015-11-06 15:52:32 -080029#include "public/fpdf_formfill.h"
dsinclair5b493092016-09-29 20:20:24 -070030#include "xfa/fxfa/cxfa_eventparam.h"
Dan Sinclair80c48782017-03-23 12:11:20 -040031#include "xfa/fxfa/cxfa_ffapp.h"
32#include "xfa/fxfa/cxfa_ffdocview.h"
33#include "xfa/fxfa/cxfa_ffwidgethandler.h"
34#include "xfa/fxfa/cxfa_widgetacciterator.h"
Tom Sepez51da0932015-11-25 16:05:49 -080035#endif
Tom Sepez1ed8a212015-05-11 15:25:39 -070036
Dan Sinclair698aed72017-09-26 16:24:49 -040037#if _FX_OS_ == _FX_OS_ANDROID_
Dan Sinclair85c8e7f2016-11-21 13:50:32 -050038#include <time.h>
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -070039#else
40#include <ctime>
41#endif
42
Tom Sepez7a73eff2016-02-08 13:39:53 -080043namespace {
44
Tom Sepez51da0932015-11-25 16:05:49 -080045#ifdef PDF_ENABLE_XFA
Dan Sinclair0b950422017-09-21 15:49:49 -040046bool SaveXFADocumentData(CPDFXFA_Context* pContext,
47 std::vector<RetainPtr<IFX_SeekableStream>>* fileList) {
dsinclair521b7502016-11-02 13:02:28 -070048 if (!pContext)
Tom Sepez7a73eff2016-02-08 13:39:53 -080049 return false;
50
Dan Sinclaircdba7472017-03-23 09:17:10 -040051 if (pContext->GetDocType() != XFA_DocType::Dynamic &&
52 pContext->GetDocType() != XFA_DocType::Static) {
Tom Sepez7a73eff2016-02-08 13:39:53 -080053 return true;
Dan Sinclaircdba7472017-03-23 09:17:10 -040054 }
Tom Sepez7a73eff2016-02-08 13:39:53 -080055
dsinclair521b7502016-11-02 13:02:28 -070056 CXFA_FFDocView* pXFADocView = pContext->GetXFADocView();
Tom Sepez7a73eff2016-02-08 13:39:53 -080057 if (!pXFADocView)
58 return true;
Bo Xufdc00a72014-10-28 23:03:33 -070059
dsinclair521b7502016-11-02 13:02:28 -070060 CPDF_Document* pPDFDocument = pContext->GetPDFDoc();
61 if (!pPDFDocument)
Tom Sepez7a73eff2016-02-08 13:39:53 -080062 return false;
Bo Xufdc00a72014-10-28 23:03:33 -070063
Lei Zhang01581062017-08-30 14:19:26 -070064 const CPDF_Dictionary* pRoot = pPDFDocument->GetRoot();
Tom Sepez7a73eff2016-02-08 13:39:53 -080065 if (!pRoot)
66 return false;
67
dsinclair38fd8442016-09-15 10:15:32 -070068 CPDF_Dictionary* pAcroForm = pRoot->GetDictFor("AcroForm");
Tom Sepez7a73eff2016-02-08 13:39:53 -080069 if (!pAcroForm)
70 return false;
71
dsinclair38fd8442016-09-15 10:15:32 -070072 CPDF_Object* pXFA = pAcroForm->GetObjectFor("XFA");
Tom Sepez7a73eff2016-02-08 13:39:53 -080073 if (!pXFA)
74 return true;
75
thestigb8bf55f2016-05-21 21:08:05 -070076 CPDF_Array* pArray = pXFA->AsArray();
Tom Sepez7a73eff2016-02-08 13:39:53 -080077 if (!pArray)
78 return false;
79
Nico Weber9d8ec5a2015-08-04 13:00:21 -070080 int size = pArray->GetCount();
81 int iFormIndex = -1;
82 int iDataSetsIndex = -1;
83 int iTemplate = -1;
84 int iLast = size - 2;
85 for (int i = 0; i < size - 1; i++) {
tsepezbd567552016-03-29 14:51:50 -070086 CPDF_Object* pPDFObj = pArray->GetObjectAt(i);
Tom Sepez8e5cd192016-01-26 13:20:26 -080087 if (!pPDFObj->IsString())
Nico Weber9d8ec5a2015-08-04 13:00:21 -070088 continue;
89 if (pPDFObj->GetString() == "form")
90 iFormIndex = i + 1;
91 else if (pPDFObj->GetString() == "datasets")
92 iDataSetsIndex = i + 1;
Lei Zhangd983b092015-12-14 16:58:33 -080093 else if (pPDFObj->GetString() == "template")
Nico Weber9d8ec5a2015-08-04 13:00:21 -070094 iTemplate = i + 1;
95 }
Dan Sinclair0bb13332017-03-30 16:12:02 -040096 auto pChecksum = pdfium::MakeUnique<CFX_ChecksumContext>();
dsinclair521b7502016-11-02 13:02:28 -070097 pChecksum->StartChecksum();
Lei Zhanga6d9f0e2015-06-13 00:48:38 -070098
Nico Weber9d8ec5a2015-08-04 13:00:21 -070099 // template
100 if (iTemplate > -1) {
Wei Li9b761132016-01-29 15:44:20 -0800101 CPDF_Stream* pTemplateStream = pArray->GetStreamAt(iTemplate);
Tom Sepezafd0d1f2017-04-04 14:37:18 -0700102 auto pAcc = pdfium::MakeRetain<CPDF_StreamAcc>(pTemplateStream);
103 pAcc->LoadAllData();
Dan Sinclair0b950422017-09-21 15:49:49 -0400104 RetainPtr<IFX_SeekableStream> pTemplate =
Dan Sinclair283a0432017-04-20 14:11:21 -0400105 pdfium::MakeRetain<CFX_MemoryStream>(
106 const_cast<uint8_t*>(pAcc->GetData()), pAcc->GetSize(), false);
tsepez833619b2016-12-07 09:21:17 -0800107 pChecksum->UpdateChecksum(pTemplate);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700108 }
thestig1cd352e2016-06-07 17:53:06 -0700109 CPDF_Stream* pFormStream = nullptr;
110 CPDF_Stream* pDataSetsStream = nullptr;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700111 if (iFormIndex != -1) {
112 // Get form CPDF_Stream
tsepezbd567552016-03-29 14:51:50 -0700113 CPDF_Object* pFormPDFObj = pArray->GetObjectAt(iFormIndex);
Tom Sepez8e5cd192016-01-26 13:20:26 -0800114 if (pFormPDFObj->IsReference()) {
115 CPDF_Object* pFormDirectObj = pFormPDFObj->GetDirect();
116 if (pFormDirectObj && pFormDirectObj->IsStream()) {
117 pFormStream = (CPDF_Stream*)pFormDirectObj;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700118 }
Tom Sepez8e5cd192016-01-26 13:20:26 -0800119 } else if (pFormPDFObj->IsStream()) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700120 pFormStream = (CPDF_Stream*)pFormPDFObj;
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700121 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700122 }
Lei Zhanga6d9f0e2015-06-13 00:48:38 -0700123
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700124 if (iDataSetsIndex != -1) {
125 // Get datasets CPDF_Stream
tsepezbd567552016-03-29 14:51:50 -0700126 CPDF_Object* pDataSetsPDFObj = pArray->GetObjectAt(iDataSetsIndex);
Tom Sepez8e5cd192016-01-26 13:20:26 -0800127 if (pDataSetsPDFObj->IsReference()) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700128 CPDF_Reference* pDataSetsRefObj = (CPDF_Reference*)pDataSetsPDFObj;
Tom Sepez8e5cd192016-01-26 13:20:26 -0800129 CPDF_Object* pDataSetsDirectObj = pDataSetsRefObj->GetDirect();
130 if (pDataSetsDirectObj && pDataSetsDirectObj->IsStream()) {
131 pDataSetsStream = (CPDF_Stream*)pDataSetsDirectObj;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700132 }
Tom Sepez8e5cd192016-01-26 13:20:26 -0800133 } else if (pDataSetsPDFObj->IsStream()) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700134 pDataSetsStream = (CPDF_Stream*)pDataSetsPDFObj;
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700135 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700136 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700137 // L"datasets"
138 {
Dan Sinclair0b950422017-09-21 15:49:49 -0400139 RetainPtr<IFX_SeekableStream> pDsfileWrite =
Dan Sinclair283a0432017-04-20 14:11:21 -0400140 pdfium::MakeRetain<CFX_MemoryStream>(false);
tsepez833619b2016-12-07 09:21:17 -0800141 if (pXFADocView->GetDoc()->SavePackage(XFA_HASHCODE_Datasets, pDsfileWrite,
142 nullptr) &&
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700143 pDsfileWrite->GetSize() > 0) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700144 // Datasets
tsepez833619b2016-12-07 09:21:17 -0800145 pChecksum->UpdateChecksum(pDsfileWrite);
dsinclair521b7502016-11-02 13:02:28 -0700146 pChecksum->FinishChecksum();
tsepez9e05ee12016-11-21 13:19:10 -0800147 auto pDataDict = pdfium::MakeUnique<CPDF_Dictionary>(
148 pPDFDocument->GetByteStringPool());
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700149 if (iDataSetsIndex != -1) {
tsepez9e05ee12016-11-21 13:19:10 -0800150 if (pDataSetsStream) {
tsepez833619b2016-12-07 09:21:17 -0800151 pDataSetsStream->InitStreamFromFile(pDsfileWrite,
tsepez9e05ee12016-11-21 13:19:10 -0800152 std::move(pDataDict));
153 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700154 } else {
tsepez70c4afd2016-11-15 11:33:44 -0800155 CPDF_Stream* pData = pPDFDocument->NewIndirect<CPDF_Stream>();
tsepez833619b2016-12-07 09:21:17 -0800156 pData->InitStreamFromFile(pDsfileWrite, std::move(pDataDict));
Tom Sepez3343d142015-11-02 09:54:54 -0800157 iLast = pArray->GetCount() - 2;
tsepez8a3aa452016-11-16 12:26:06 -0800158 pArray->InsertNewAt<CPDF_String>(iLast, "datasets", false);
159 pArray->InsertNewAt<CPDF_Reference>(iLast + 1, pPDFDocument,
160 pData->GetObjNum());
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700161 }
Tom Sepez7a73eff2016-02-08 13:39:53 -0800162 fileList->push_back(std::move(pDsfileWrite));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700163 }
164 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700165 // L"form"
166 {
Dan Sinclair0b950422017-09-21 15:49:49 -0400167 RetainPtr<IFX_SeekableStream> pfileWrite =
Dan Sinclair283a0432017-04-20 14:11:21 -0400168 pdfium::MakeRetain<CFX_MemoryStream>(false);
tsepez833619b2016-12-07 09:21:17 -0800169 if (pXFADocView->GetDoc()->SavePackage(XFA_HASHCODE_Form, pfileWrite,
dsinclair521b7502016-11-02 13:02:28 -0700170 pChecksum.get()) &&
Tom Sepez7a73eff2016-02-08 13:39:53 -0800171 pfileWrite->GetSize() > 0) {
tsepez9e05ee12016-11-21 13:19:10 -0800172 auto pDataDict = pdfium::MakeUnique<CPDF_Dictionary>(
173 pPDFDocument->GetByteStringPool());
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700174 if (iFormIndex != -1) {
tsepez833619b2016-12-07 09:21:17 -0800175 if (pFormStream)
176 pFormStream->InitStreamFromFile(pfileWrite, std::move(pDataDict));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700177 } else {
tsepez70c4afd2016-11-15 11:33:44 -0800178 CPDF_Stream* pData = pPDFDocument->NewIndirect<CPDF_Stream>();
tsepez833619b2016-12-07 09:21:17 -0800179 pData->InitStreamFromFile(pfileWrite, std::move(pDataDict));
Tom Sepez3343d142015-11-02 09:54:54 -0800180 iLast = pArray->GetCount() - 2;
tsepez8a3aa452016-11-16 12:26:06 -0800181 pArray->InsertNewAt<CPDF_String>(iLast, "form", false);
182 pArray->InsertNewAt<CPDF_Reference>(iLast + 1, pPDFDocument,
183 pData->GetObjNum());
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700184 }
Tom Sepez7a73eff2016-02-08 13:39:53 -0800185 fileList->push_back(std::move(pfileWrite));
Tom Sepez2f2ffec2015-07-23 14:42:09 -0700186 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700187 }
Tom Sepez7a73eff2016-02-08 13:39:53 -0800188 return true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700189}
190
dsinclair521b7502016-11-02 13:02:28 -0700191bool SendPostSaveToXFADoc(CPDFXFA_Context* pContext) {
192 if (!pContext)
Tom Sepez7a73eff2016-02-08 13:39:53 -0800193 return false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700194
Dan Sinclaircdba7472017-03-23 09:17:10 -0400195 if (pContext->GetDocType() != XFA_DocType::Dynamic &&
196 pContext->GetDocType() != XFA_DocType::Static)
Tom Sepez7a73eff2016-02-08 13:39:53 -0800197 return true;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700198
dsinclair521b7502016-11-02 13:02:28 -0700199 CXFA_FFDocView* pXFADocView = pContext->GetXFADocView();
Tom Sepez7a73eff2016-02-08 13:39:53 -0800200 if (!pXFADocView)
201 return false;
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700202
Lei Zhangcddc8ed2017-06-20 17:26:44 -0700203 CXFA_FFWidgetHandler* pWidgetHandler = pXFADocView->GetWidgetHandler();
Tom Sepez40badde2017-05-01 13:21:39 -0700204 std::unique_ptr<CXFA_WidgetAccIterator> pWidgetAccIterator =
205 pXFADocView->CreateWidgetAccIterator();
tsepeze7b28532016-05-18 12:10:49 -0700206 while (CXFA_WidgetAcc* pWidgetAcc = pWidgetAccIterator->MoveToNext()) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700207 CXFA_EventParam preParam;
208 preParam.m_eType = XFA_EVENT_PostSave;
Lei Zhangcddc8ed2017-06-20 17:26:44 -0700209 pWidgetHandler->ProcessEvent(pWidgetAcc, &preParam);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700210 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700211 pXFADocView->UpdateDocView();
dsinclair521b7502016-11-02 13:02:28 -0700212 pContext->ClearChangeMark();
Tom Sepez7a73eff2016-02-08 13:39:53 -0800213 return true;
Bo Xufdc00a72014-10-28 23:03:33 -0700214}
215
Dan Sinclair0b950422017-09-21 15:49:49 -0400216bool SendPreSaveToXFADoc(CPDFXFA_Context* pContext,
217 std::vector<RetainPtr<IFX_SeekableStream>>* fileList) {
Dan Sinclaircdba7472017-03-23 09:17:10 -0400218 if (pContext->GetDocType() != XFA_DocType::Dynamic &&
219 pContext->GetDocType() != XFA_DocType::Static)
Tom Sepez7a73eff2016-02-08 13:39:53 -0800220 return true;
221
dsinclair521b7502016-11-02 13:02:28 -0700222 CXFA_FFDocView* pXFADocView = pContext->GetXFADocView();
Tom Sepez7a73eff2016-02-08 13:39:53 -0800223 if (!pXFADocView)
224 return true;
225
Lei Zhangcddc8ed2017-06-20 17:26:44 -0700226 CXFA_FFWidgetHandler* pWidgetHandler = pXFADocView->GetWidgetHandler();
Tom Sepez40badde2017-05-01 13:21:39 -0700227 std::unique_ptr<CXFA_WidgetAccIterator> pWidgetAccIterator =
228 pXFADocView->CreateWidgetAccIterator();
tsepeze7b28532016-05-18 12:10:49 -0700229 while (CXFA_WidgetAcc* pWidgetAcc = pWidgetAccIterator->MoveToNext()) {
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700230 CXFA_EventParam preParam;
231 preParam.m_eType = XFA_EVENT_PreSave;
Lei Zhangcddc8ed2017-06-20 17:26:44 -0700232 pWidgetHandler->ProcessEvent(pWidgetAcc, &preParam);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700233 }
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700234 pXFADocView->UpdateDocView();
dsinclair521b7502016-11-02 13:02:28 -0700235 return SaveXFADocumentData(pContext, fileList);
Bo Xufdc00a72014-10-28 23:03:33 -0700236}
Tom Sepez40e9ff32015-11-30 12:39:54 -0800237#endif // PDF_ENABLE_XFA
Bo Xufdc00a72014-10-28 23:03:33 -0700238
Tom Sepez7a73eff2016-02-08 13:39:53 -0800239bool FPDF_Doc_Save(FPDF_DOCUMENT document,
240 FPDF_FILEWRITE* pFileWrite,
241 FPDF_DWORD flags,
242 FPDF_BOOL bSetVersion,
243 int fileVerion) {
Tom Sepez1b246282015-11-25 15:15:31 -0800244 CPDF_Document* pPDFDoc = CPDFDocumentFromFPDFDocument(document);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700245 if (!pPDFDoc)
246 return 0;
Lei Zhanga6d9f0e2015-06-13 00:48:38 -0700247
Tom Sepez51da0932015-11-25 16:05:49 -0800248#ifdef PDF_ENABLE_XFA
dsinclair521b7502016-11-02 13:02:28 -0700249 CPDFXFA_Context* pContext = static_cast<CPDFXFA_Context*>(document);
Dan Sinclair0b950422017-09-21 15:49:49 -0400250 std::vector<RetainPtr<IFX_SeekableStream>> fileList;
dsinclair521b7502016-11-02 13:02:28 -0700251 SendPreSaveToXFADoc(pContext, &fileList);
Tom Sepez40e9ff32015-11-30 12:39:54 -0800252#endif // PDF_ENABLE_XFA
Tom Sepez1b246282015-11-25 15:15:31 -0800253
Tom Sepez7a73eff2016-02-08 13:39:53 -0800254 if (flags < FPDF_INCREMENTAL || flags > FPDF_REMOVE_SECURITY)
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700255 flags = 0;
Lei Zhanga6d9f0e2015-06-13 00:48:38 -0700256
Dan Sinclairae4656e2017-05-09 12:36:41 -0400257 CPDF_Creator fileMaker(pPDFDoc,
258 pdfium::MakeRetain<FSDK_FileWriteAdapter>(pFileWrite));
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700259 if (bSetVersion)
Dan Sinclairae4656e2017-05-09 12:36:41 -0400260 fileMaker.SetFileVersion(fileVerion);
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700261 if (flags == FPDF_REMOVE_SECURITY) {
262 flags = 0;
Dan Sinclairae4656e2017-05-09 12:36:41 -0400263 fileMaker.RemoveSecurity();
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700264 }
Tom Sepez1b246282015-11-25 15:15:31 -0800265
Dan Sinclairae4656e2017-05-09 12:36:41 -0400266 bool bRet = fileMaker.Create(flags);
Tom Sepez51da0932015-11-25 16:05:49 -0800267#ifdef PDF_ENABLE_XFA
dsinclair521b7502016-11-02 13:02:28 -0700268 SendPostSaveToXFADoc(pContext);
Tom Sepez40e9ff32015-11-30 12:39:54 -0800269#endif // PDF_ENABLE_XFA
Nico Weber9d8ec5a2015-08-04 13:00:21 -0700270 return bRet;
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700271}
272
Tom Sepez7a73eff2016-02-08 13:39:53 -0800273} // namespace
274
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400275FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_SaveAsCopy(FPDF_DOCUMENT document,
276 FPDF_FILEWRITE* pFileWrite,
277 FPDF_DWORD flags) {
tsepez4cf55152016-11-02 14:37:54 -0700278 return FPDF_Doc_Save(document, pFileWrite, flags, false, 0);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700279}
280
Dan Sinclair00d2ad12017-08-10 14:13:02 -0400281FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
282FPDF_SaveWithVersion(FPDF_DOCUMENT document,
283 FPDF_FILEWRITE* pFileWrite,
284 FPDF_DWORD flags,
285 int fileVersion) {
tsepez4cf55152016-11-02 14:37:54 -0700286 return FPDF_Doc_Save(document, pFileWrite, flags, true, fileVersion);
John Abd-El-Malek3f3b45c2014-05-23 17:28:10 -0700287}