OLD | NEW |
1 // Copyright 2014 PDFium Authors. All rights reserved. | 1 // Copyright 2014 PDFium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com |
6 | 6 |
7 #include "public/fpdf_save.h" | 7 #include "public/fpdf_save.h" |
8 | 8 |
| 9 #ifdef PDF_ENABLE_XFA |
| 10 #include "../include/fpdfxfa/fpdfxfa_app.h" |
| 11 #include "../include/fpdfxfa/fpdfxfa_doc.h" |
| 12 #include "../include/fpdfxfa/fpdfxfa_util.h" |
| 13 #endif |
9 #include "fpdfsdk/include/fsdk_define.h" | 14 #include "fpdfsdk/include/fsdk_define.h" |
10 #include "public/fpdf_edit.h" | 15 #include "public/fpdf_edit.h" |
| 16 #ifdef PDF_ENABLE_XFA |
| 17 #include "public/fpdf_formfill.h" |
| 18 #endif |
11 | 19 |
12 #if _FX_OS_ == _FX_ANDROID_ | 20 #if _FX_OS_ == _FX_ANDROID_ |
13 #include "time.h" | 21 #include "time.h" |
14 #else | 22 #else |
15 #include <ctime> | 23 #include <ctime> |
16 #endif | 24 #endif |
17 | 25 |
18 class CFX_IFileWrite final : public IFX_StreamWrite { | 26 class CFX_IFileWrite final : public IFX_StreamWrite { |
19 public: | 27 public: |
20 CFX_IFileWrite(); | 28 CFX_IFileWrite(); |
(...skipping 24 matching lines...) Expand all Loading... |
45 return FALSE; | 53 return FALSE; |
46 | 54 |
47 m_pFileWriteStruct->WriteBlock(m_pFileWriteStruct, pData, size); | 55 m_pFileWriteStruct->WriteBlock(m_pFileWriteStruct, pData, size); |
48 return TRUE; | 56 return TRUE; |
49 } | 57 } |
50 | 58 |
51 void CFX_IFileWrite::Release() { | 59 void CFX_IFileWrite::Release() { |
52 delete this; | 60 delete this; |
53 } | 61 } |
54 | 62 |
| 63 #ifdef PDF_ENABLE_XFA |
| 64 #define XFA_DATASETS 0 |
| 65 #define XFA_FORMS 1 |
| 66 |
| 67 FX_BOOL _SaveXFADocumentData(CPDFXFA_Document* pDocument, |
| 68 CFX_PtrArray& fileList) { |
| 69 #ifdef PDF_ENABLE_XFA |
| 70 if (!pDocument) |
| 71 return FALSE; |
| 72 if (pDocument->GetDocType() != DOCTYPE_DYNAMIC_XFA && |
| 73 pDocument->GetDocType() != DOCTYPE_STATIC_XFA) |
| 74 return TRUE; |
| 75 if (!CPDFXFA_App::GetInstance()->GetXFAApp()) |
| 76 return TRUE; |
| 77 |
| 78 IXFA_DocView* pXFADocView = pDocument->GetXFADocView(); |
| 79 if (NULL == pXFADocView) |
| 80 return TRUE; |
| 81 |
| 82 IXFA_DocHandler* pXFADocHandler = |
| 83 CPDFXFA_App::GetInstance()->GetXFAApp()->GetDocHandler(); |
| 84 CPDF_Document* pPDFDocument = pDocument->GetPDFDoc(); |
| 85 if (pDocument == NULL) |
| 86 return FALSE; |
| 87 |
| 88 CPDF_Dictionary* pRoot = pPDFDocument->GetRoot(); |
| 89 if (pRoot == NULL) |
| 90 return FALSE; |
| 91 CPDF_Dictionary* pAcroForm = pRoot->GetDict("AcroForm"); |
| 92 if (NULL == pAcroForm) |
| 93 return FALSE; |
| 94 CPDF_Object* pXFA = pAcroForm->GetElement("XFA"); |
| 95 if (pXFA == NULL) |
| 96 return TRUE; |
| 97 if (pXFA->GetType() != PDFOBJ_ARRAY) |
| 98 return FALSE; |
| 99 CPDF_Array* pArray = pXFA->GetArray(); |
| 100 if (NULL == pArray) |
| 101 return FALSE; |
| 102 int size = pArray->GetCount(); |
| 103 int iFormIndex = -1; |
| 104 int iDataSetsIndex = -1; |
| 105 int iTemplate = -1; |
| 106 int iLast = size - 2; |
| 107 for (int i = 0; i < size - 1; i++) { |
| 108 CPDF_Object* pPDFObj = pArray->GetElement(i); |
| 109 if (pPDFObj->GetType() != PDFOBJ_STRING) |
| 110 continue; |
| 111 if (pPDFObj->GetString() == "form") |
| 112 iFormIndex = i + 1; |
| 113 else if (pPDFObj->GetString() == "datasets") |
| 114 iDataSetsIndex = i + 1; |
| 115 else if (pPDFObj->GetString() == FX_BSTRC("template")) |
| 116 iTemplate = i + 1; |
| 117 } |
| 118 IXFA_ChecksumContext* pContext = NULL; |
| 119 #define XFA_USECKSUM |
| 120 #ifdef XFA_USECKSUM |
| 121 // Checksum |
| 122 pContext = XFA_Checksum_Create(); |
| 123 FXSYS_assert(pContext); |
| 124 pContext->StartChecksum(); |
| 125 |
| 126 // template |
| 127 if (iTemplate > -1) { |
| 128 CPDF_Stream* pTemplateStream = pArray->GetStream(iTemplate); |
| 129 CPDF_StreamAcc streamAcc; |
| 130 streamAcc.LoadAllData(pTemplateStream); |
| 131 uint8_t* pData = (uint8_t*)streamAcc.GetData(); |
| 132 FX_DWORD dwSize2 = streamAcc.GetSize(); |
| 133 IFX_FileStream* pTemplate = FX_CreateMemoryStream(pData, dwSize2); |
| 134 pContext->UpdateChecksum((IFX_FileRead*)pTemplate); |
| 135 pTemplate->Release(); |
| 136 } |
| 137 #endif |
| 138 CPDF_Stream* pFormStream = NULL; |
| 139 CPDF_Stream* pDataSetsStream = NULL; |
| 140 if (iFormIndex != -1) { |
| 141 // Get form CPDF_Stream |
| 142 CPDF_Object* pFormPDFObj = pArray->GetElement(iFormIndex); |
| 143 if (pFormPDFObj->GetType() == PDFOBJ_REFERENCE) { |
| 144 CPDF_Object* pFormDircetObj = pFormPDFObj->GetDirect(); |
| 145 if (NULL != pFormDircetObj && |
| 146 pFormDircetObj->GetType() == PDFOBJ_STREAM) { |
| 147 pFormStream = (CPDF_Stream*)pFormDircetObj; |
| 148 } |
| 149 } else if (pFormPDFObj->GetType() == PDFOBJ_STREAM) { |
| 150 pFormStream = (CPDF_Stream*)pFormPDFObj; |
| 151 } |
| 152 } |
| 153 |
| 154 if (iDataSetsIndex != -1) { |
| 155 // Get datasets CPDF_Stream |
| 156 CPDF_Object* pDataSetsPDFObj = pArray->GetElement(iDataSetsIndex); |
| 157 if (pDataSetsPDFObj->GetType() == PDFOBJ_REFERENCE) { |
| 158 CPDF_Reference* pDataSetsRefObj = (CPDF_Reference*)pDataSetsPDFObj; |
| 159 CPDF_Object* pDataSetsDircetObj = pDataSetsRefObj->GetDirect(); |
| 160 if (NULL != pDataSetsDircetObj && |
| 161 pDataSetsDircetObj->GetType() == PDFOBJ_STREAM) { |
| 162 pDataSetsStream = (CPDF_Stream*)pDataSetsDircetObj; |
| 163 } |
| 164 } else if (pDataSetsPDFObj->GetType() == PDFOBJ_STREAM) { |
| 165 pDataSetsStream = (CPDF_Stream*)pDataSetsPDFObj; |
| 166 } |
| 167 } |
| 168 // end |
| 169 // L"datasets" |
| 170 { |
| 171 IFX_FileStream* pDsfileWrite = FX_CreateMemoryStream(); |
| 172 if (NULL == pDsfileWrite) { |
| 173 pContext->Release(); |
| 174 pDsfileWrite->Release(); |
| 175 return FALSE; |
| 176 } |
| 177 if (pXFADocHandler->SavePackage(pXFADocView->GetDoc(), |
| 178 CFX_WideStringC(L"datasets"), |
| 179 pDsfileWrite) && |
| 180 pDsfileWrite->GetSize() > 0) { |
| 181 #ifdef XFA_USECKSUM |
| 182 // Datasets |
| 183 pContext->UpdateChecksum((IFX_FileRead*)pDsfileWrite); |
| 184 pContext->FinishChecksum(); |
| 185 #endif |
| 186 CPDF_Dictionary* pDataDict = new CPDF_Dictionary; |
| 187 if (iDataSetsIndex != -1) { |
| 188 if (pDataSetsStream) |
| 189 pDataSetsStream->InitStreamFromFile(pDsfileWrite, pDataDict); |
| 190 } else { |
| 191 CPDF_Stream* pData = new CPDF_Stream(NULL, 0, NULL); |
| 192 pData->InitStreamFromFile(pDsfileWrite, pDataDict); |
| 193 pPDFDocument->AddIndirectObject(pData); |
| 194 iLast = pArray->GetCount() - 2; |
| 195 pArray->InsertAt(iLast, CPDF_String::Create("datasets")); |
| 196 pArray->InsertAt(iLast + 1, pData, pPDFDocument); |
| 197 } |
| 198 fileList.Add(pDsfileWrite); |
| 199 } |
| 200 } |
| 201 |
| 202 // L"form" |
| 203 { |
| 204 IFX_FileStream* pfileWrite = FX_CreateMemoryStream(); |
| 205 if (NULL == pfileWrite) { |
| 206 pContext->Release(); |
| 207 return FALSE; |
| 208 } |
| 209 if (pXFADocHandler->SavePackage(pXFADocView->GetDoc(), |
| 210 CFX_WideStringC(L"form"), pfileWrite, |
| 211 pContext) && |
| 212 pfileWrite > 0) { |
| 213 CPDF_Dictionary* pDataDict = new CPDF_Dictionary; |
| 214 if (iFormIndex != -1) { |
| 215 if (pFormStream) |
| 216 pFormStream->InitStreamFromFile(pfileWrite, pDataDict); |
| 217 } else { |
| 218 CPDF_Stream* pData = new CPDF_Stream(NULL, 0, NULL); |
| 219 pData->InitStreamFromFile(pfileWrite, pDataDict); |
| 220 pPDFDocument->AddIndirectObject(pData); |
| 221 iLast = pArray->GetCount() - 2; |
| 222 pArray->InsertAt(iLast, CPDF_String::Create("form")); |
| 223 pArray->InsertAt(iLast + 1, pData, pPDFDocument); |
| 224 } |
| 225 fileList.Add(pfileWrite); |
| 226 } |
| 227 } |
| 228 pContext->Release(); |
| 229 #endif // PDF_ENABLE_XFA |
| 230 |
| 231 return TRUE; |
| 232 } |
| 233 |
| 234 FX_BOOL _SendPostSaveToXFADoc(CPDFXFA_Document* pDocument) { |
| 235 if (!pDocument) |
| 236 return FALSE; |
| 237 |
| 238 if (pDocument->GetDocType() != DOCTYPE_DYNAMIC_XFA && |
| 239 pDocument->GetDocType() != DOCTYPE_STATIC_XFA) |
| 240 return TRUE; |
| 241 |
| 242 IXFA_DocView* pXFADocView = pDocument->GetXFADocView(); |
| 243 if (NULL == pXFADocView) |
| 244 return FALSE; |
| 245 IXFA_WidgetHandler* pWidgetHander = pXFADocView->GetWidgetHandler(); |
| 246 |
| 247 CXFA_WidgetAcc* pWidgetAcc = NULL; |
| 248 IXFA_WidgetAccIterator* pWidgetAccIterator = |
| 249 pXFADocView->CreateWidgetAccIterator(); |
| 250 pWidgetAcc = pWidgetAccIterator->MoveToNext(); |
| 251 while (pWidgetAcc) { |
| 252 CXFA_EventParam preParam; |
| 253 preParam.m_eType = XFA_EVENT_PostSave; |
| 254 pWidgetHander->ProcessEvent(pWidgetAcc, &preParam); |
| 255 pWidgetAcc = pWidgetAccIterator->MoveToNext(); |
| 256 } |
| 257 pWidgetAccIterator->Release(); |
| 258 pXFADocView->UpdateDocView(); |
| 259 pDocument->_ClearChangeMark(); |
| 260 return TRUE; |
| 261 } |
| 262 |
| 263 FX_BOOL _SendPreSaveToXFADoc(CPDFXFA_Document* pDocument, |
| 264 CFX_PtrArray& fileList) { |
| 265 if (pDocument->GetDocType() != DOCTYPE_DYNAMIC_XFA && |
| 266 pDocument->GetDocType() != DOCTYPE_STATIC_XFA) |
| 267 return TRUE; |
| 268 IXFA_DocView* pXFADocView = pDocument->GetXFADocView(); |
| 269 if (NULL == pXFADocView) |
| 270 return TRUE; |
| 271 IXFA_WidgetHandler* pWidgetHander = pXFADocView->GetWidgetHandler(); |
| 272 CXFA_WidgetAcc* pWidgetAcc = NULL; |
| 273 IXFA_WidgetAccIterator* pWidgetAccIterator = |
| 274 pXFADocView->CreateWidgetAccIterator(); |
| 275 pWidgetAcc = pWidgetAccIterator->MoveToNext(); |
| 276 while (pWidgetAcc) { |
| 277 CXFA_EventParam preParam; |
| 278 preParam.m_eType = XFA_EVENT_PreSave; |
| 279 pWidgetHander->ProcessEvent(pWidgetAcc, &preParam); |
| 280 pWidgetAcc = pWidgetAccIterator->MoveToNext(); |
| 281 } |
| 282 pWidgetAccIterator->Release(); |
| 283 pXFADocView->UpdateDocView(); |
| 284 return _SaveXFADocumentData(pDocument, fileList); |
| 285 } |
| 286 |
| 287 #endif |
55 FPDF_BOOL _FPDF_Doc_Save(FPDF_DOCUMENT document, | 288 FPDF_BOOL _FPDF_Doc_Save(FPDF_DOCUMENT document, |
56 FPDF_FILEWRITE* pFileWrite, | 289 FPDF_FILEWRITE* pFileWrite, |
57 FPDF_DWORD flags, | 290 FPDF_DWORD flags, |
58 FPDF_BOOL bSetVersion, | 291 FPDF_BOOL bSetVersion, |
59 int fileVerion) { | 292 int fileVerion) { |
60 CPDF_Document* pPDFDoc = CPDFDocumentFromFPDFDocument(document); | 293 CPDF_Document* pPDFDoc = CPDFDocumentFromFPDFDocument(document); |
61 if (!pPDFDoc) | 294 if (!pPDFDoc) |
62 return 0; | 295 return 0; |
63 | 296 |
| 297 #ifdef PDF_ENABLE_XFA |
| 298 CPDFXFA_Document* pDoc = (CPDFXFA_Document*)document; |
| 299 CFX_PtrArray fileList; |
| 300 _SendPreSaveToXFADoc(pDoc, fileList); |
| 301 |
| 302 #endif |
64 if (flags < FPDF_INCREMENTAL || flags > FPDF_REMOVE_SECURITY) { | 303 if (flags < FPDF_INCREMENTAL || flags > FPDF_REMOVE_SECURITY) { |
65 flags = 0; | 304 flags = 0; |
66 } | 305 } |
67 | 306 |
68 CPDF_Creator FileMaker(pPDFDoc); | 307 CPDF_Creator FileMaker(pPDFDoc); |
69 if (bSetVersion) | 308 if (bSetVersion) |
70 FileMaker.SetFileVersion(fileVerion); | 309 FileMaker.SetFileVersion(fileVerion); |
71 if (flags == FPDF_REMOVE_SECURITY) { | 310 if (flags == FPDF_REMOVE_SECURITY) { |
72 flags = 0; | 311 flags = 0; |
73 FileMaker.RemoveSecurity(); | 312 FileMaker.RemoveSecurity(); |
74 } | 313 } |
75 | 314 |
76 CFX_IFileWrite* pStreamWrite = NULL; | 315 CFX_IFileWrite* pStreamWrite = NULL; |
77 FX_BOOL bRet; | 316 FX_BOOL bRet; |
78 pStreamWrite = new CFX_IFileWrite; | 317 pStreamWrite = new CFX_IFileWrite; |
79 pStreamWrite->Init(pFileWrite); | 318 pStreamWrite->Init(pFileWrite); |
80 bRet = FileMaker.Create(pStreamWrite, flags); | 319 bRet = FileMaker.Create(pStreamWrite, flags); |
| 320 #ifdef PDF_ENABLE_XFA |
| 321 _SendPostSaveToXFADoc(pDoc); |
| 322 for (int i = 0; i < fileList.GetSize(); i++) { |
| 323 IFX_FileStream* pFile = (IFX_FileStream*)fileList.GetAt(i); |
| 324 pFile->Release(); |
| 325 } |
| 326 fileList.RemoveAll(); |
| 327 #endif |
81 pStreamWrite->Release(); | 328 pStreamWrite->Release(); |
82 return bRet; | 329 return bRet; |
83 } | 330 } |
84 | 331 |
85 DLLEXPORT FPDF_BOOL STDCALL FPDF_SaveAsCopy(FPDF_DOCUMENT document, | 332 DLLEXPORT FPDF_BOOL STDCALL FPDF_SaveAsCopy(FPDF_DOCUMENT document, |
86 FPDF_FILEWRITE* pFileWrite, | 333 FPDF_FILEWRITE* pFileWrite, |
87 FPDF_DWORD flags) { | 334 FPDF_DWORD flags) { |
88 return _FPDF_Doc_Save(document, pFileWrite, flags, FALSE, 0); | 335 return _FPDF_Doc_Save(document, pFileWrite, flags, FALSE, 0); |
89 } | 336 } |
90 | 337 |
91 DLLEXPORT FPDF_BOOL STDCALL FPDF_SaveWithVersion(FPDF_DOCUMENT document, | 338 DLLEXPORT FPDF_BOOL STDCALL FPDF_SaveWithVersion(FPDF_DOCUMENT document, |
92 FPDF_FILEWRITE* pFileWrite, | 339 FPDF_FILEWRITE* pFileWrite, |
93 FPDF_DWORD flags, | 340 FPDF_DWORD flags, |
94 int fileVersion) { | 341 int fileVersion) { |
95 return _FPDF_Doc_Save(document, pFileWrite, flags, TRUE, fileVersion); | 342 return _FPDF_Doc_Save(document, pFileWrite, flags, TRUE, fileVersion); |
96 } | 343 } |
OLD | NEW |