summaryrefslogtreecommitdiff
path: root/xfa/fxfa/app/xfa_ffdoc.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'xfa/fxfa/app/xfa_ffdoc.cpp')
-rw-r--r--xfa/fxfa/app/xfa_ffdoc.cpp431
1 files changed, 431 insertions, 0 deletions
diff --git a/xfa/fxfa/app/xfa_ffdoc.cpp b/xfa/fxfa/app/xfa_ffdoc.cpp
new file mode 100644
index 0000000000..e33dd4fa47
--- /dev/null
+++ b/xfa/fxfa/app/xfa_ffdoc.cpp
@@ -0,0 +1,431 @@
+// Copyright 2014 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "xfa/fxfa/app/xfa_ffdoc.h"
+
+#include "core/include/fpdfapi/cpdf_array.h"
+#include "core/include/fpdfapi/cpdf_document.h"
+#include "core/include/fpdfdoc/fpdf_doc.h"
+#include "core/include/fxcrt/fx_ext.h"
+#include "xfa/fgas/crt/fgas_algorithm.h"
+#include "xfa/fxfa/app/xfa_ffapp.h"
+#include "xfa/fxfa/app/xfa_ffdocview.h"
+#include "xfa/fxfa/app/xfa_ffnotify.h"
+#include "xfa/fxfa/app/xfa_ffwidget.h"
+#include "xfa/fxfa/app/xfa_fontmgr.h"
+#include "xfa/fxfa/parser/xfa_docdata.h"
+#include "xfa/fxfa/parser/xfa_parser.h"
+#include "xfa/include/fwl/core/fwl_note.h"
+
+CXFA_FFDoc::CXFA_FFDoc(CXFA_FFApp* pApp, IXFA_DocProvider* pDocProvider)
+ : m_pDocProvider(pDocProvider),
+ m_pDocument(nullptr),
+ m_pStream(nullptr),
+ m_pApp(pApp),
+ m_pNotify(nullptr),
+ m_pPDFDoc(nullptr),
+ m_dwDocType(XFA_DOCTYPE_Static),
+ m_bOwnStream(TRUE) {}
+CXFA_FFDoc::~CXFA_FFDoc() {
+ CloseDoc();
+}
+FX_DWORD CXFA_FFDoc::GetDocType() {
+ return m_dwDocType;
+}
+int32_t CXFA_FFDoc::StartLoad() {
+ m_pNotify = new CXFA_FFNotify(this);
+ IXFA_DocParser* pDocParser = IXFA_DocParser::Create(m_pNotify);
+ int32_t iStatus = pDocParser->StartParse(m_pStream);
+ m_pDocument = pDocParser->GetDocument();
+ return iStatus;
+}
+FX_BOOL XFA_GetPDFContentsFromPDFXML(IFDE_XMLNode* pPDFElement,
+ uint8_t*& pByteBuffer,
+ int32_t& iBufferSize) {
+ IFDE_XMLElement* pDocumentElement = NULL;
+ for (IFDE_XMLNode* pXMLNode =
+ pPDFElement->GetNodeItem(IFDE_XMLNode::FirstChild);
+ pXMLNode; pXMLNode = pXMLNode->GetNodeItem(IFDE_XMLNode::NextSibling)) {
+ if (pXMLNode->GetType() == FDE_XMLNODE_Element) {
+ CFX_WideString wsTagName;
+ IFDE_XMLElement* pXMLElement = (IFDE_XMLElement*)pXMLNode;
+ pXMLElement->GetTagName(wsTagName);
+ if (wsTagName.Equal(FX_WSTRC(L"document"))) {
+ pDocumentElement = pXMLElement;
+ break;
+ }
+ }
+ }
+ if (!pDocumentElement) {
+ return FALSE;
+ }
+ IFDE_XMLElement* pChunkElement = NULL;
+ for (IFDE_XMLNode* pXMLNode =
+ pDocumentElement->GetNodeItem(IFDE_XMLNode::FirstChild);
+ pXMLNode; pXMLNode = pXMLNode->GetNodeItem(IFDE_XMLNode::NextSibling)) {
+ if (pXMLNode->GetType() == FDE_XMLNODE_Element) {
+ CFX_WideString wsTagName;
+ IFDE_XMLElement* pXMLElement = (IFDE_XMLElement*)pXMLNode;
+ pXMLElement->GetTagName(wsTagName);
+ if (wsTagName.Equal(FX_WSTRC(L"chunk"))) {
+ pChunkElement = pXMLElement;
+ break;
+ }
+ }
+ }
+ if (!pChunkElement) {
+ return FALSE;
+ }
+ CFX_WideString wsPDFContent;
+ pChunkElement->GetTextData(wsPDFContent);
+ iBufferSize = FX_Base64DecodeW(wsPDFContent, wsPDFContent.GetLength(), NULL);
+ pByteBuffer = FX_Alloc(uint8_t, iBufferSize + 1);
+ pByteBuffer[iBufferSize] = '0'; // FIXME: I bet this is wrong.
+ FX_Base64DecodeW(wsPDFContent, wsPDFContent.GetLength(), pByteBuffer);
+ return TRUE;
+}
+void XFA_XPDPacket_MergeRootNode(CXFA_Node* pOriginRoot, CXFA_Node* pNewRoot) {
+ CXFA_Node* pChildNode = pNewRoot->GetNodeItem(XFA_NODEITEM_FirstChild);
+ while (pChildNode) {
+ CXFA_Node* pOriginChild =
+ pOriginRoot->GetFirstChildByName(pChildNode->GetNameHash());
+ if (pOriginChild) {
+ pChildNode = pChildNode->GetNodeItem(XFA_NODEITEM_NextSibling);
+ } else {
+ CXFA_Node* pNextSibling =
+ pChildNode->GetNodeItem(XFA_NODEITEM_NextSibling);
+ pNewRoot->RemoveChild(pChildNode);
+ pOriginRoot->InsertChild(pChildNode);
+ pChildNode = pNextSibling;
+ pNextSibling = NULL;
+ }
+ }
+}
+int32_t CXFA_FFDoc::DoLoad(IFX_Pause* pPause) {
+ int32_t iStatus = m_pDocument->GetParser()->DoParse(pPause);
+ if (iStatus == XFA_PARSESTATUS_Done && !m_pPDFDoc) {
+ CXFA_Node* pPDFNode = ToNode(m_pDocument->GetXFAObject(XFA_HASHCODE_Pdf));
+ if (!pPDFNode) {
+ return XFA_PARSESTATUS_SyntaxErr;
+ }
+ IFDE_XMLNode* pPDFXML = pPDFNode->GetXMLMappingNode();
+ if (pPDFXML->GetType() != FDE_XMLNODE_Element) {
+ return XFA_PARSESTATUS_SyntaxErr;
+ }
+ int32_t iBufferSize = 0;
+ uint8_t* pByteBuffer = NULL;
+ IFX_FileRead* pXFAReader = NULL;
+ if (XFA_GetPDFContentsFromPDFXML(pPDFXML, pByteBuffer, iBufferSize)) {
+ pXFAReader = FX_CreateMemoryStream(pByteBuffer, iBufferSize, TRUE);
+ } else {
+ CFX_WideString wsHref;
+ ((IFDE_XMLElement*)pPDFXML)->GetString(L"href", wsHref);
+ if (!wsHref.IsEmpty()) {
+ pXFAReader = GetDocProvider()->OpenLinkedFile(this, wsHref);
+ }
+ }
+ if (!pXFAReader) {
+ return XFA_PARSESTATUS_SyntaxErr;
+ }
+ CPDF_Document* pPDFDocument =
+ GetDocProvider()->OpenPDF(this, pXFAReader, TRUE);
+ FXSYS_assert(!m_pPDFDoc);
+ if (!OpenDoc(pPDFDocument)) {
+ return XFA_PARSESTATUS_SyntaxErr;
+ }
+ IXFA_Parser* pParser = IXFA_Parser::Create(m_pDocument, TRUE);
+ if (!pParser) {
+ return XFA_PARSESTATUS_SyntaxErr;
+ }
+ CXFA_Node* pRootNode = NULL;
+ if (pParser->StartParse(m_pStream) == XFA_PARSESTATUS_Ready &&
+ pParser->DoParse(NULL) == XFA_PARSESTATUS_Done) {
+ pRootNode = pParser->GetRootNode();
+ }
+ if (pRootNode && m_pDocument->GetRoot()) {
+ XFA_XPDPacket_MergeRootNode(m_pDocument->GetRoot(), pRootNode);
+ iStatus = XFA_PARSESTATUS_Done;
+ } else {
+ iStatus = XFA_PARSESTATUS_StatusErr;
+ }
+ pParser->Release();
+ pParser = NULL;
+ }
+ return iStatus;
+}
+void CXFA_FFDoc::StopLoad() {
+ m_pApp->GetXFAFontMgr()->LoadDocFonts(this);
+ m_dwDocType = XFA_DOCTYPE_Static;
+ CXFA_Node* pConfig = ToNode(m_pDocument->GetXFAObject(XFA_HASHCODE_Config));
+ if (!pConfig) {
+ return;
+ }
+ CXFA_Node* pAcrobat = pConfig->GetFirstChildByClass(XFA_ELEMENT_Acrobat);
+ if (!pAcrobat) {
+ return;
+ }
+ CXFA_Node* pAcrobat7 = pAcrobat->GetFirstChildByClass(XFA_ELEMENT_Acrobat7);
+ if (!pAcrobat7) {
+ return;
+ }
+ CXFA_Node* pDynamicRender =
+ pAcrobat7->GetFirstChildByClass(XFA_ELEMENT_DynamicRender);
+ if (!pDynamicRender) {
+ return;
+ }
+ CFX_WideString wsType;
+ if (pDynamicRender->TryContent(wsType) && wsType == FX_WSTRC(L"required")) {
+ m_dwDocType = XFA_DOCTYPE_Dynamic;
+ }
+}
+IXFA_DocView* CXFA_FFDoc::CreateDocView(FX_DWORD dwView) {
+ CXFA_FFDocView* pDocView =
+ (CXFA_FFDocView*)m_mapTypeToDocView.GetValueAt((void*)(uintptr_t)dwView);
+ if (!pDocView) {
+ pDocView = new CXFA_FFDocView(this);
+ m_mapTypeToDocView.SetAt((void*)(uintptr_t)dwView, pDocView);
+ }
+ return pDocView;
+}
+CXFA_FFDocView* CXFA_FFDoc::GetDocView(IXFA_DocLayout* pLayout) {
+ FX_POSITION ps = m_mapTypeToDocView.GetStartPosition();
+ while (ps) {
+ void* pType;
+ CXFA_FFDocView* pDocView;
+ m_mapTypeToDocView.GetNextAssoc(ps, pType, (void*&)pDocView);
+ if (pDocView->GetXFALayout() == pLayout) {
+ return pDocView;
+ }
+ }
+ return NULL;
+}
+CXFA_FFDocView* CXFA_FFDoc::GetDocView() {
+ FX_POSITION ps = m_mapTypeToDocView.GetStartPosition();
+ if (ps) {
+ void* pType;
+ CXFA_FFDocView* pDocView;
+ m_mapTypeToDocView.GetNextAssoc(ps, pType, (void*&)pDocView);
+ return pDocView;
+ }
+ return NULL;
+}
+FX_BOOL CXFA_FFDoc::OpenDoc(IFX_FileRead* pStream, FX_BOOL bTakeOverFile) {
+ m_bOwnStream = bTakeOverFile;
+ m_pStream = pStream;
+ return TRUE;
+}
+FX_BOOL CXFA_FFDoc::OpenDoc(CPDF_Document* pPDFDoc) {
+ if (pPDFDoc == NULL) {
+ return FALSE;
+ }
+ CPDF_Dictionary* pRoot = pPDFDoc->GetRoot();
+ if (pRoot == NULL) {
+ return FALSE;
+ }
+ CPDF_Dictionary* pAcroForm = pRoot->GetDictBy("AcroForm");
+ if (pAcroForm == NULL) {
+ return FALSE;
+ }
+ CPDF_Object* pElementXFA = pAcroForm->GetElementValue("XFA");
+ if (pElementXFA == NULL) {
+ return FALSE;
+ }
+ CFX_ArrayTemplate<CPDF_Stream*> xfaStreams;
+ if (pElementXFA->IsArray()) {
+ CPDF_Array* pXFAArray = (CPDF_Array*)pElementXFA;
+ FX_DWORD count = pXFAArray->GetCount() / 2;
+ for (FX_DWORD i = 0; i < count; i++) {
+ if (CPDF_Stream* pStream = pXFAArray->GetStreamAt(i * 2 + 1))
+ xfaStreams.Add(pStream);
+ }
+ } else if (pElementXFA->IsStream()) {
+ xfaStreams.Add((CPDF_Stream*)pElementXFA);
+ }
+ if (xfaStreams.GetSize() < 1) {
+ return FALSE;
+ }
+ IFX_FileRead* pFileRead = new CXFA_FileRead(xfaStreams);
+ m_pPDFDoc = pPDFDoc;
+ if (m_pStream) {
+ m_pStream->Release();
+ m_pStream = NULL;
+ }
+ m_pStream = pFileRead;
+ m_bOwnStream = TRUE;
+ return TRUE;
+}
+FX_BOOL CXFA_FFDoc::CloseDoc() {
+ FX_POSITION psClose = m_mapTypeToDocView.GetStartPosition();
+ while (psClose) {
+ void* pType;
+ CXFA_FFDocView* pDocView;
+ m_mapTypeToDocView.GetNextAssoc(psClose, pType, (void*&)pDocView);
+ pDocView->RunDocClose();
+ }
+ if (m_pDocument) {
+ m_pDocument->ClearLayoutData();
+ }
+ FX_POSITION ps = m_mapTypeToDocView.GetStartPosition();
+ while (ps) {
+ void* pType;
+ CXFA_FFDocView* pDocView;
+ m_mapTypeToDocView.GetNextAssoc(ps, pType, (void*&)pDocView);
+ delete pDocView;
+ }
+ m_mapTypeToDocView.RemoveAll();
+ if (m_pDocument) {
+ IXFA_Parser* pParser = m_pDocument->GetParser();
+ pParser->Release();
+ m_pDocument = NULL;
+ }
+ if (m_pNotify) {
+ delete m_pNotify;
+ m_pNotify = NULL;
+ }
+ m_pApp->GetXFAFontMgr()->ReleaseDocFonts(this);
+ if (m_dwDocType != XFA_DOCTYPE_XDP && m_pStream && m_bOwnStream) {
+ m_pStream->Release();
+ m_pStream = NULL;
+ }
+ ps = m_mapNamedImages.GetStartPosition();
+ while (ps) {
+ void* pName;
+ FX_IMAGEDIB_AND_DPI* pImage = NULL;
+ m_mapNamedImages.GetNextAssoc(ps, pName, (void*&)pImage);
+ if (pImage) {
+ delete pImage->pDibSource;
+ pImage->pDibSource = NULL;
+ FX_Free(pImage);
+ pImage = NULL;
+ }
+ }
+ m_mapNamedImages.RemoveAll();
+ IFWL_NoteDriver* pNoteDriver = FWL_GetApp()->GetNoteDriver();
+ pNoteDriver->ClearEventTargets(FALSE);
+ return TRUE;
+}
+void CXFA_FFDoc::SetDocType(FX_DWORD dwType) {
+ m_dwDocType = dwType;
+}
+CPDF_Document* CXFA_FFDoc::GetPDFDoc() {
+ return m_pPDFDoc;
+}
+
+CFX_DIBitmap* CXFA_FFDoc::GetPDFNamedImage(const CFX_WideStringC& wsName,
+ int32_t& iImageXDpi,
+ int32_t& iImageYDpi) {
+ if (!m_pPDFDoc)
+ return nullptr;
+
+ FX_DWORD dwHash =
+ FX_HashCode_String_GetW(wsName.GetPtr(), wsName.GetLength(), FALSE);
+ FX_IMAGEDIB_AND_DPI* imageDIBDpi = nullptr;
+ if (m_mapNamedImages.Lookup((void*)(uintptr_t)dwHash, (void*&)imageDIBDpi)) {
+ iImageXDpi = imageDIBDpi->iImageXDpi;
+ iImageYDpi = imageDIBDpi->iImageYDpi;
+ return static_cast<CFX_DIBitmap*>(imageDIBDpi->pDibSource);
+ }
+
+ CPDF_Dictionary* pRoot = m_pPDFDoc->GetRoot();
+ if (!pRoot)
+ return nullptr;
+
+ CPDF_Dictionary* pNames = pRoot->GetDictBy("Names");
+ if (!pNames)
+ return nullptr;
+
+ CPDF_Dictionary* pXFAImages = pNames->GetDictBy("XFAImages");
+ if (!pXFAImages)
+ return nullptr;
+
+ CPDF_NameTree nametree(pXFAImages);
+ CFX_ByteString bsName = PDF_EncodeText(wsName.GetPtr(), wsName.GetLength());
+ CPDF_Object* pObject = nametree.LookupValue(bsName);
+ if (!pObject) {
+ int32_t iCount = nametree.GetCount();
+ for (int32_t i = 0; i < iCount; i++) {
+ CFX_ByteString bsTemp;
+ CPDF_Object* pTempObject = nametree.LookupValue(i, bsTemp);
+ if (bsTemp == bsName) {
+ pObject = pTempObject;
+ break;
+ }
+ }
+ }
+
+ if (!pObject || !pObject->IsStream())
+ return nullptr;
+
+ if (!imageDIBDpi) {
+ imageDIBDpi = FX_Alloc(FX_IMAGEDIB_AND_DPI, 1);
+ imageDIBDpi->pDibSource = nullptr;
+ imageDIBDpi->iImageXDpi = 0;
+ imageDIBDpi->iImageYDpi = 0;
+ CPDF_StreamAcc streamAcc;
+ streamAcc.LoadAllData((CPDF_Stream*)pObject);
+ IFX_FileRead* pImageFileRead = FX_CreateMemoryStream(
+ (uint8_t*)streamAcc.GetData(), streamAcc.GetSize());
+ imageDIBDpi->pDibSource = XFA_LoadImageFromBuffer(
+ pImageFileRead, FXCODEC_IMAGE_UNKNOWN, iImageXDpi, iImageYDpi);
+ imageDIBDpi->iImageXDpi = iImageXDpi;
+ imageDIBDpi->iImageYDpi = iImageYDpi;
+ pImageFileRead->Release();
+ }
+ m_mapNamedImages.SetAt((void*)(uintptr_t)dwHash, imageDIBDpi);
+ return (CFX_DIBitmap*)imageDIBDpi->pDibSource;
+}
+
+IFDE_XMLElement* CXFA_FFDoc::GetPackageData(const CFX_WideStringC& wsPackage) {
+ FX_DWORD packetHash =
+ FX_HashCode_String_GetW(wsPackage.GetPtr(), wsPackage.GetLength());
+ CXFA_Node* pNode = ToNode(m_pDocument->GetXFAObject(packetHash));
+ if (!pNode) {
+ return NULL;
+ }
+ IFDE_XMLNode* pXMLNode = pNode->GetXMLMappingNode();
+ return (pXMLNode && pXMLNode->GetType() == FDE_XMLNODE_Element)
+ ? (IFDE_XMLElement*)pXMLNode
+ : NULL;
+}
+FX_BOOL CXFA_FFDoc::SavePackage(const CFX_WideStringC& wsPackage,
+ IFX_FileWrite* pFile,
+ IXFA_ChecksumContext* pCSContext) {
+ IXFA_PacketExport* pExport = IXFA_PacketExport::Create(m_pDocument);
+ if (!pExport) {
+ return FALSE;
+ }
+ FX_DWORD packetHash =
+ FX_HashCode_String_GetW(wsPackage.GetPtr(), wsPackage.GetLength());
+ CXFA_Node* pNode = NULL;
+ if (packetHash == XFA_HASHCODE_Xfa) {
+ pNode = m_pDocument->GetRoot();
+ } else {
+ pNode = ToNode(m_pDocument->GetXFAObject(packetHash));
+ }
+ FX_BOOL bFlags = FALSE;
+ if (pNode) {
+ CFX_ByteString bsChecksum;
+ if (pCSContext) {
+ pCSContext->GetChecksum(bsChecksum);
+ }
+ bFlags = pExport->Export(pFile, pNode, 0, bsChecksum.GetLength()
+ ? (const FX_CHAR*)bsChecksum
+ : NULL);
+ } else {
+ bFlags = pExport->Export(pFile);
+ }
+ pExport->Release();
+ return bFlags;
+}
+FX_BOOL CXFA_FFDoc::ImportData(IFX_FileRead* pStream, FX_BOOL bXDP) {
+ FX_BOOL bRet = FALSE;
+ IXFA_PacketImport* pImport = IXFA_PacketImport::Create(m_pDocument);
+ if (pImport) {
+ bRet = pImport->ImportData(pStream);
+ pImport->Release();
+ }
+ return bRet;
+}