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