diff options
Diffstat (limited to 'xfa/src/fxfa/app/xfa_ffdoc.cpp')
-rw-r--r-- | xfa/src/fxfa/app/xfa_ffdoc.cpp | 429 |
1 files changed, 429 insertions, 0 deletions
diff --git a/xfa/src/fxfa/app/xfa_ffdoc.cpp b/xfa/src/fxfa/app/xfa_ffdoc.cpp new file mode 100644 index 0000000000..f088a79fb6 --- /dev/null +++ b/xfa/src/fxfa/app/xfa_ffdoc.cpp @@ -0,0 +1,429 @@ +// 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/src/fxfa/app/xfa_ffdoc.h" + +#include "core/include/fpdfdoc/fpdf_doc.h" +#include "core/include/fxcrt/fx_ext.h" +#include "xfa/include/fwl/core/fwl_note.h" +#include "xfa/src/fgas/include/fx_alg.h" +#include "xfa/src/fxfa/app/xfa_ffapp.h" +#include "xfa/src/fxfa/app/xfa_ffdocview.h" +#include "xfa/src/fxfa/app/xfa_ffnotify.h" +#include "xfa/src/fxfa/app/xfa_ffwidget.h" +#include "xfa/src/fxfa/app/xfa_fontmgr.h" +#include "xfa/src/fxfa/parser/xfa_docdata.h" +#include "xfa/src/fxfa/parser/xfa_parser.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; +} |