Index: fpdfsdk/src/fpdfsave.cpp |
diff --git a/fpdfsdk/src/fpdfsave.cpp b/fpdfsdk/src/fpdfsave.cpp |
index 0573e17ba8d6c7decd7023578ea562229fdb86d3..a3a91c7187bbd119dacdc0f50cbbdbbb510494b5 100644 |
--- a/fpdfsdk/src/fpdfsave.cpp |
+++ b/fpdfsdk/src/fpdfsave.cpp |
@@ -6,8 +6,16 @@ |
#include "public/fpdf_save.h" |
+#ifdef PDF_ENABLE_XFA |
+#include "../include/fpdfxfa/fpdfxfa_app.h" |
+#include "../include/fpdfxfa/fpdfxfa_doc.h" |
+#include "../include/fpdfxfa/fpdfxfa_util.h" |
+#endif |
#include "fpdfsdk/include/fsdk_define.h" |
#include "public/fpdf_edit.h" |
+#ifdef PDF_ENABLE_XFA |
+#include "public/fpdf_formfill.h" |
+#endif |
#if _FX_OS_ == _FX_ANDROID_ |
#include "time.h" |
@@ -52,6 +60,231 @@ void CFX_IFileWrite::Release() { |
delete this; |
} |
+#ifdef PDF_ENABLE_XFA |
+#define XFA_DATASETS 0 |
+#define XFA_FORMS 1 |
+ |
+FX_BOOL _SaveXFADocumentData(CPDFXFA_Document* pDocument, |
+ CFX_PtrArray& fileList) { |
+#ifdef PDF_ENABLE_XFA |
+ if (!pDocument) |
+ return FALSE; |
+ if (pDocument->GetDocType() != DOCTYPE_DYNAMIC_XFA && |
+ pDocument->GetDocType() != DOCTYPE_STATIC_XFA) |
+ return TRUE; |
+ if (!CPDFXFA_App::GetInstance()->GetXFAApp()) |
+ return TRUE; |
+ |
+ IXFA_DocView* pXFADocView = pDocument->GetXFADocView(); |
+ if (NULL == pXFADocView) |
+ return TRUE; |
+ |
+ IXFA_DocHandler* pXFADocHandler = |
+ CPDFXFA_App::GetInstance()->GetXFAApp()->GetDocHandler(); |
+ CPDF_Document* pPDFDocument = pDocument->GetPDFDoc(); |
+ if (pDocument == NULL) |
+ return FALSE; |
+ |
+ CPDF_Dictionary* pRoot = pPDFDocument->GetRoot(); |
+ if (pRoot == NULL) |
+ return FALSE; |
+ CPDF_Dictionary* pAcroForm = pRoot->GetDict("AcroForm"); |
+ if (NULL == pAcroForm) |
+ return FALSE; |
+ CPDF_Object* pXFA = pAcroForm->GetElement("XFA"); |
+ if (pXFA == NULL) |
+ return TRUE; |
+ if (pXFA->GetType() != PDFOBJ_ARRAY) |
+ return FALSE; |
+ CPDF_Array* pArray = pXFA->GetArray(); |
+ if (NULL == pArray) |
+ return FALSE; |
+ int size = pArray->GetCount(); |
+ int iFormIndex = -1; |
+ int iDataSetsIndex = -1; |
+ int iTemplate = -1; |
+ int iLast = size - 2; |
+ for (int i = 0; i < size - 1; i++) { |
+ CPDF_Object* pPDFObj = pArray->GetElement(i); |
+ if (pPDFObj->GetType() != PDFOBJ_STRING) |
+ continue; |
+ if (pPDFObj->GetString() == "form") |
+ iFormIndex = i + 1; |
+ else if (pPDFObj->GetString() == "datasets") |
+ iDataSetsIndex = i + 1; |
+ else if (pPDFObj->GetString() == FX_BSTRC("template")) |
+ iTemplate = i + 1; |
+ } |
+ IXFA_ChecksumContext* pContext = NULL; |
+#define XFA_USECKSUM |
+#ifdef XFA_USECKSUM |
+ // Checksum |
+ pContext = XFA_Checksum_Create(); |
+ FXSYS_assert(pContext); |
+ pContext->StartChecksum(); |
+ |
+ // template |
+ if (iTemplate > -1) { |
+ CPDF_Stream* pTemplateStream = pArray->GetStream(iTemplate); |
+ CPDF_StreamAcc streamAcc; |
+ streamAcc.LoadAllData(pTemplateStream); |
+ uint8_t* pData = (uint8_t*)streamAcc.GetData(); |
+ FX_DWORD dwSize2 = streamAcc.GetSize(); |
+ IFX_FileStream* pTemplate = FX_CreateMemoryStream(pData, dwSize2); |
+ pContext->UpdateChecksum((IFX_FileRead*)pTemplate); |
+ pTemplate->Release(); |
+ } |
+#endif |
+ CPDF_Stream* pFormStream = NULL; |
+ CPDF_Stream* pDataSetsStream = NULL; |
+ if (iFormIndex != -1) { |
+ // Get form CPDF_Stream |
+ CPDF_Object* pFormPDFObj = pArray->GetElement(iFormIndex); |
+ if (pFormPDFObj->GetType() == PDFOBJ_REFERENCE) { |
+ CPDF_Object* pFormDircetObj = pFormPDFObj->GetDirect(); |
+ if (NULL != pFormDircetObj && |
+ pFormDircetObj->GetType() == PDFOBJ_STREAM) { |
+ pFormStream = (CPDF_Stream*)pFormDircetObj; |
+ } |
+ } else if (pFormPDFObj->GetType() == PDFOBJ_STREAM) { |
+ pFormStream = (CPDF_Stream*)pFormPDFObj; |
+ } |
+ } |
+ |
+ if (iDataSetsIndex != -1) { |
+ // Get datasets CPDF_Stream |
+ CPDF_Object* pDataSetsPDFObj = pArray->GetElement(iDataSetsIndex); |
+ if (pDataSetsPDFObj->GetType() == PDFOBJ_REFERENCE) { |
+ CPDF_Reference* pDataSetsRefObj = (CPDF_Reference*)pDataSetsPDFObj; |
+ CPDF_Object* pDataSetsDircetObj = pDataSetsRefObj->GetDirect(); |
+ if (NULL != pDataSetsDircetObj && |
+ pDataSetsDircetObj->GetType() == PDFOBJ_STREAM) { |
+ pDataSetsStream = (CPDF_Stream*)pDataSetsDircetObj; |
+ } |
+ } else if (pDataSetsPDFObj->GetType() == PDFOBJ_STREAM) { |
+ pDataSetsStream = (CPDF_Stream*)pDataSetsPDFObj; |
+ } |
+ } |
+ // end |
+ // L"datasets" |
+ { |
+ IFX_FileStream* pDsfileWrite = FX_CreateMemoryStream(); |
+ if (NULL == pDsfileWrite) { |
+ pContext->Release(); |
+ pDsfileWrite->Release(); |
+ return FALSE; |
+ } |
+ if (pXFADocHandler->SavePackage(pXFADocView->GetDoc(), |
+ CFX_WideStringC(L"datasets"), |
+ pDsfileWrite) && |
+ pDsfileWrite->GetSize() > 0) { |
+#ifdef XFA_USECKSUM |
+ // Datasets |
+ pContext->UpdateChecksum((IFX_FileRead*)pDsfileWrite); |
+ pContext->FinishChecksum(); |
+#endif |
+ CPDF_Dictionary* pDataDict = new CPDF_Dictionary; |
+ if (iDataSetsIndex != -1) { |
+ if (pDataSetsStream) |
+ pDataSetsStream->InitStreamFromFile(pDsfileWrite, pDataDict); |
+ } else { |
+ CPDF_Stream* pData = new CPDF_Stream(NULL, 0, NULL); |
+ pData->InitStreamFromFile(pDsfileWrite, pDataDict); |
+ pPDFDocument->AddIndirectObject(pData); |
+ iLast = pArray->GetCount() - 2; |
+ pArray->InsertAt(iLast, CPDF_String::Create("datasets")); |
+ pArray->InsertAt(iLast + 1, pData, pPDFDocument); |
+ } |
+ fileList.Add(pDsfileWrite); |
+ } |
+ } |
+ |
+ // L"form" |
+ { |
+ IFX_FileStream* pfileWrite = FX_CreateMemoryStream(); |
+ if (NULL == pfileWrite) { |
+ pContext->Release(); |
+ return FALSE; |
+ } |
+ if (pXFADocHandler->SavePackage(pXFADocView->GetDoc(), |
+ CFX_WideStringC(L"form"), pfileWrite, |
+ pContext) && |
+ pfileWrite > 0) { |
+ CPDF_Dictionary* pDataDict = new CPDF_Dictionary; |
+ if (iFormIndex != -1) { |
+ if (pFormStream) |
+ pFormStream->InitStreamFromFile(pfileWrite, pDataDict); |
+ } else { |
+ CPDF_Stream* pData = new CPDF_Stream(NULL, 0, NULL); |
+ pData->InitStreamFromFile(pfileWrite, pDataDict); |
+ pPDFDocument->AddIndirectObject(pData); |
+ iLast = pArray->GetCount() - 2; |
+ pArray->InsertAt(iLast, CPDF_String::Create("form")); |
+ pArray->InsertAt(iLast + 1, pData, pPDFDocument); |
+ } |
+ fileList.Add(pfileWrite); |
+ } |
+ } |
+ pContext->Release(); |
+#endif // PDF_ENABLE_XFA |
+ |
+ return TRUE; |
+} |
+ |
+FX_BOOL _SendPostSaveToXFADoc(CPDFXFA_Document* pDocument) { |
+ if (!pDocument) |
+ return FALSE; |
+ |
+ if (pDocument->GetDocType() != DOCTYPE_DYNAMIC_XFA && |
+ pDocument->GetDocType() != DOCTYPE_STATIC_XFA) |
+ return TRUE; |
+ |
+ IXFA_DocView* pXFADocView = pDocument->GetXFADocView(); |
+ if (NULL == pXFADocView) |
+ return FALSE; |
+ IXFA_WidgetHandler* pWidgetHander = pXFADocView->GetWidgetHandler(); |
+ |
+ CXFA_WidgetAcc* pWidgetAcc = NULL; |
+ IXFA_WidgetAccIterator* pWidgetAccIterator = |
+ pXFADocView->CreateWidgetAccIterator(); |
+ pWidgetAcc = pWidgetAccIterator->MoveToNext(); |
+ while (pWidgetAcc) { |
+ CXFA_EventParam preParam; |
+ preParam.m_eType = XFA_EVENT_PostSave; |
+ pWidgetHander->ProcessEvent(pWidgetAcc, &preParam); |
+ pWidgetAcc = pWidgetAccIterator->MoveToNext(); |
+ } |
+ pWidgetAccIterator->Release(); |
+ pXFADocView->UpdateDocView(); |
+ pDocument->_ClearChangeMark(); |
+ return TRUE; |
+} |
+ |
+FX_BOOL _SendPreSaveToXFADoc(CPDFXFA_Document* pDocument, |
+ CFX_PtrArray& fileList) { |
+ if (pDocument->GetDocType() != DOCTYPE_DYNAMIC_XFA && |
+ pDocument->GetDocType() != DOCTYPE_STATIC_XFA) |
+ return TRUE; |
+ IXFA_DocView* pXFADocView = pDocument->GetXFADocView(); |
+ if (NULL == pXFADocView) |
+ return TRUE; |
+ IXFA_WidgetHandler* pWidgetHander = pXFADocView->GetWidgetHandler(); |
+ CXFA_WidgetAcc* pWidgetAcc = NULL; |
+ IXFA_WidgetAccIterator* pWidgetAccIterator = |
+ pXFADocView->CreateWidgetAccIterator(); |
+ pWidgetAcc = pWidgetAccIterator->MoveToNext(); |
+ while (pWidgetAcc) { |
+ CXFA_EventParam preParam; |
+ preParam.m_eType = XFA_EVENT_PreSave; |
+ pWidgetHander->ProcessEvent(pWidgetAcc, &preParam); |
+ pWidgetAcc = pWidgetAccIterator->MoveToNext(); |
+ } |
+ pWidgetAccIterator->Release(); |
+ pXFADocView->UpdateDocView(); |
+ return _SaveXFADocumentData(pDocument, fileList); |
+} |
+ |
+#endif |
FPDF_BOOL _FPDF_Doc_Save(FPDF_DOCUMENT document, |
FPDF_FILEWRITE* pFileWrite, |
FPDF_DWORD flags, |
@@ -61,6 +294,12 @@ FPDF_BOOL _FPDF_Doc_Save(FPDF_DOCUMENT document, |
if (!pPDFDoc) |
return 0; |
+#ifdef PDF_ENABLE_XFA |
+ CPDFXFA_Document* pDoc = (CPDFXFA_Document*)document; |
+ CFX_PtrArray fileList; |
+ _SendPreSaveToXFADoc(pDoc, fileList); |
+ |
+#endif |
if (flags < FPDF_INCREMENTAL || flags > FPDF_REMOVE_SECURITY) { |
flags = 0; |
} |
@@ -78,6 +317,14 @@ FPDF_BOOL _FPDF_Doc_Save(FPDF_DOCUMENT document, |
pStreamWrite = new CFX_IFileWrite; |
pStreamWrite->Init(pFileWrite); |
bRet = FileMaker.Create(pStreamWrite, flags); |
+#ifdef PDF_ENABLE_XFA |
+ _SendPostSaveToXFADoc(pDoc); |
+ for (int i = 0; i < fileList.GetSize(); i++) { |
+ IFX_FileStream* pFile = (IFX_FileStream*)fileList.GetAt(i); |
+ pFile->Release(); |
+ } |
+ fileList.RemoveAll(); |
+#endif |
pStreamWrite->Release(); |
return bRet; |
} |