| 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 | 
|---|