Home | History | Annotate | Download | only in app
      1 // Copyright 2014 PDFium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
      6 
      7 #include "xfa/src/foxitlib.h"
      8 #include "xfa/src/fxfa/src/common/xfa_common.h"
      9 #include "xfa_ffapp.h"
     10 #include "xfa_ffdoc.h"
     11 #include "xfa_ffdocview.h"
     12 #include "xfa_ffwidget.h"
     13 #include "xfa_ffnotify.h"
     14 #include "xfa_fontmgr.h"
     15 CXFA_FFDoc::CXFA_FFDoc(CXFA_FFApp* pApp, IXFA_DocProvider* pDocProvider)
     16     : m_pDocProvider(pDocProvider),
     17       m_pDocument(nullptr),
     18       m_pStream(nullptr),
     19       m_pApp(pApp),
     20       m_pNotify(nullptr),
     21       m_pPDFDoc(nullptr),
     22       m_dwDocType(XFA_DOCTYPE_Static),
     23       m_bOwnStream(TRUE) {
     24 }
     25 CXFA_FFDoc::~CXFA_FFDoc() {
     26   CloseDoc();
     27 }
     28 FX_DWORD CXFA_FFDoc::GetDocType() {
     29   return m_dwDocType;
     30 }
     31 int32_t CXFA_FFDoc::StartLoad() {
     32   m_pNotify = new CXFA_FFNotify(this);
     33   IXFA_DocParser* pDocParser = IXFA_DocParser::Create(m_pNotify);
     34   int32_t iStatus = pDocParser->StartParse(m_pStream);
     35   m_pDocument = pDocParser->GetDocument();
     36   return iStatus;
     37 }
     38 FX_BOOL XFA_GetPDFContentsFromPDFXML(IFDE_XMLNode* pPDFElement,
     39                                      uint8_t*& pByteBuffer,
     40                                      int32_t& iBufferSize) {
     41   IFDE_XMLElement* pDocumentElement = NULL;
     42   for (IFDE_XMLNode* pXMLNode =
     43            pPDFElement->GetNodeItem(IFDE_XMLNode::FirstChild);
     44        pXMLNode; pXMLNode = pXMLNode->GetNodeItem(IFDE_XMLNode::NextSibling)) {
     45     if (pXMLNode->GetType() == FDE_XMLNODE_Element) {
     46       CFX_WideString wsTagName;
     47       IFDE_XMLElement* pXMLElement = (IFDE_XMLElement*)pXMLNode;
     48       pXMLElement->GetTagName(wsTagName);
     49       if (wsTagName.Equal(FX_WSTRC(L"document"))) {
     50         pDocumentElement = pXMLElement;
     51         break;
     52       }
     53     }
     54   }
     55   if (!pDocumentElement) {
     56     return FALSE;
     57   }
     58   IFDE_XMLElement* pChunkElement = NULL;
     59   for (IFDE_XMLNode* pXMLNode =
     60            pDocumentElement->GetNodeItem(IFDE_XMLNode::FirstChild);
     61        pXMLNode; pXMLNode = pXMLNode->GetNodeItem(IFDE_XMLNode::NextSibling)) {
     62     if (pXMLNode->GetType() == FDE_XMLNODE_Element) {
     63       CFX_WideString wsTagName;
     64       IFDE_XMLElement* pXMLElement = (IFDE_XMLElement*)pXMLNode;
     65       pXMLElement->GetTagName(wsTagName);
     66       if (wsTagName.Equal(FX_WSTRC(L"chunk"))) {
     67         pChunkElement = pXMLElement;
     68         break;
     69       }
     70     }
     71   }
     72   if (!pChunkElement) {
     73     return FALSE;
     74   }
     75   CFX_WideString wsPDFContent;
     76   pChunkElement->GetTextData(wsPDFContent);
     77   iBufferSize = FX_Base64DecodeW(wsPDFContent, wsPDFContent.GetLength(), NULL);
     78   pByteBuffer = FX_Alloc(uint8_t, iBufferSize + 1);
     79   pByteBuffer[iBufferSize] = '0';  // FIXME: I bet this is wrong.
     80   FX_Base64DecodeW(wsPDFContent, wsPDFContent.GetLength(), pByteBuffer);
     81   return TRUE;
     82 }
     83 void XFA_XPDPacket_MergeRootNode(CXFA_Node* pOriginRoot, CXFA_Node* pNewRoot) {
     84   CXFA_Node* pChildNode = pNewRoot->GetNodeItem(XFA_NODEITEM_FirstChild);
     85   while (pChildNode) {
     86     CXFA_Node* pOriginChild =
     87         pOriginRoot->GetFirstChildByName(pChildNode->GetNameHash());
     88     if (pOriginChild) {
     89       pChildNode = pChildNode->GetNodeItem(XFA_NODEITEM_NextSibling);
     90     } else {
     91       CXFA_Node* pNextSibling =
     92           pChildNode->GetNodeItem(XFA_NODEITEM_NextSibling);
     93       pNewRoot->RemoveChild(pChildNode);
     94       pOriginRoot->InsertChild(pChildNode);
     95       pChildNode = pNextSibling;
     96       pNextSibling = NULL;
     97     }
     98   }
     99 }
    100 int32_t CXFA_FFDoc::DoLoad(IFX_Pause* pPause) {
    101   int32_t iStatus = m_pDocument->GetParser()->DoParse(pPause);
    102   if (iStatus == XFA_PARSESTATUS_Done && !m_pPDFDoc) {
    103     CXFA_Node* pPDFNode = (CXFA_Node*)m_pDocument->GetXFANode(XFA_HASHCODE_Pdf);
    104     if (!pPDFNode) {
    105       return XFA_PARSESTATUS_SyntaxErr;
    106     }
    107     IFDE_XMLNode* pPDFXML = pPDFNode->GetXMLMappingNode();
    108     if (pPDFXML->GetType() != FDE_XMLNODE_Element) {
    109       return XFA_PARSESTATUS_SyntaxErr;
    110     }
    111     int32_t iBufferSize = 0;
    112     uint8_t* pByteBuffer = NULL;
    113     IFX_FileRead* pXFAReader = NULL;
    114     if (XFA_GetPDFContentsFromPDFXML(pPDFXML, pByteBuffer, iBufferSize)) {
    115       pXFAReader = FX_CreateMemoryStream(pByteBuffer, iBufferSize, TRUE);
    116       if (!pXFAReader) {
    117         if (pByteBuffer) {
    118           FX_Free(pByteBuffer);
    119           pByteBuffer = NULL;
    120         }
    121         return XFA_PARSESTATUS_SyntaxErr;
    122       }
    123     } else {
    124       CFX_WideString wsHref;
    125       ((IFDE_XMLElement*)pPDFXML)->GetString(L"href", wsHref);
    126       if (!wsHref.IsEmpty()) {
    127         pXFAReader = GetDocProvider()->OpenLinkedFile(this, wsHref);
    128       }
    129     }
    130     if (!pXFAReader) {
    131       return XFA_PARSESTATUS_SyntaxErr;
    132     }
    133     CPDF_Document* pPDFDocument =
    134         GetDocProvider()->OpenPDF(this, pXFAReader, TRUE);
    135     FXSYS_assert(!m_pPDFDoc);
    136     if (!OpenDoc(pPDFDocument)) {
    137       return XFA_PARSESTATUS_SyntaxErr;
    138     }
    139     IXFA_Parser* pParser = IXFA_Parser::Create(m_pDocument, TRUE);
    140     if (!pParser) {
    141       return XFA_PARSESTATUS_SyntaxErr;
    142     }
    143     CXFA_Node* pRootNode = NULL;
    144     if (pParser->StartParse(m_pStream) == XFA_PARSESTATUS_Ready &&
    145         pParser->DoParse(NULL) == XFA_PARSESTATUS_Done) {
    146       pRootNode = pParser->GetRootNode();
    147     }
    148     if (pRootNode && m_pDocument->GetRoot()) {
    149       XFA_XPDPacket_MergeRootNode(m_pDocument->GetRoot(), pRootNode);
    150       iStatus = XFA_PARSESTATUS_Done;
    151     } else {
    152       iStatus = XFA_PARSESTATUS_StatusErr;
    153     }
    154     pParser->Release();
    155     pParser = NULL;
    156   }
    157   return iStatus;
    158 }
    159 void CXFA_FFDoc::StopLoad() {
    160   m_pApp->GetXFAFontMgr()->LoadDocFonts(this);
    161   m_dwDocType = XFA_DOCTYPE_Static;
    162   CXFA_Node* pConfig = (CXFA_Node*)m_pDocument->GetXFANode(XFA_HASHCODE_Config);
    163   if (!pConfig) {
    164     return;
    165   }
    166   CXFA_Node* pAcrobat = pConfig->GetFirstChildByClass(XFA_ELEMENT_Acrobat);
    167   if (!pAcrobat) {
    168     return;
    169   }
    170   CXFA_Node* pAcrobat7 = pAcrobat->GetFirstChildByClass(XFA_ELEMENT_Acrobat7);
    171   if (!pAcrobat7) {
    172     return;
    173   }
    174   CXFA_Node* pDynamicRender =
    175       pAcrobat7->GetFirstChildByClass(XFA_ELEMENT_DynamicRender);
    176   if (!pDynamicRender) {
    177     return;
    178   }
    179   CFX_WideString wsType;
    180   if (pDynamicRender->TryContent(wsType) && wsType == FX_WSTRC(L"required")) {
    181     m_dwDocType = XFA_DOCTYPE_Dynamic;
    182   }
    183 }
    184 IXFA_DocView* CXFA_FFDoc::CreateDocView(FX_DWORD dwView) {
    185   CXFA_FFDocView* pDocView =
    186       (CXFA_FFDocView*)m_mapTypeToDocView.GetValueAt((void*)(uintptr_t)dwView);
    187   if (!pDocView) {
    188     pDocView = new CXFA_FFDocView(this);
    189     m_mapTypeToDocView.SetAt((void*)(uintptr_t)dwView, pDocView);
    190   }
    191   return pDocView;
    192 }
    193 CXFA_FFDocView* CXFA_FFDoc::GetDocView(IXFA_DocLayout* pLayout) {
    194   FX_POSITION ps = m_mapTypeToDocView.GetStartPosition();
    195   while (ps) {
    196     void* pType;
    197     CXFA_FFDocView* pDocView;
    198     m_mapTypeToDocView.GetNextAssoc(ps, pType, (void*&)pDocView);
    199     if (pDocView->GetXFALayout() == pLayout) {
    200       return pDocView;
    201     }
    202   }
    203   return NULL;
    204 }
    205 CXFA_FFDocView* CXFA_FFDoc::GetDocView() {
    206   FX_POSITION ps = m_mapTypeToDocView.GetStartPosition();
    207   if (ps) {
    208     void* pType;
    209     CXFA_FFDocView* pDocView;
    210     m_mapTypeToDocView.GetNextAssoc(ps, pType, (void*&)pDocView);
    211     return pDocView;
    212   }
    213   return NULL;
    214 }
    215 FX_BOOL CXFA_FFDoc::OpenDoc(IFX_FileRead* pStream, FX_BOOL bTakeOverFile) {
    216   m_bOwnStream = bTakeOverFile;
    217   m_pStream = pStream;
    218   return TRUE;
    219 }
    220 FX_BOOL CXFA_FFDoc::OpenDoc(CPDF_Document* pPDFDoc) {
    221   if (pPDFDoc == NULL) {
    222     return FALSE;
    223   }
    224   CPDF_Dictionary* pRoot = pPDFDoc->GetRoot();
    225   if (pRoot == NULL) {
    226     return FALSE;
    227   }
    228   CPDF_Dictionary* pAcroForm = pRoot->GetDict("AcroForm");
    229   if (pAcroForm == NULL) {
    230     return FALSE;
    231   }
    232   CPDF_Object* pElementXFA = pAcroForm->GetElementValue("XFA");
    233   if (pElementXFA == NULL) {
    234     return FALSE;
    235   }
    236   int32_t iObjType = pElementXFA->GetType();
    237   CFX_ArrayTemplate<CPDF_Stream*> xfaStreams;
    238   if (iObjType == PDFOBJ_ARRAY) {
    239     CPDF_Array* pXFAArray = (CPDF_Array*)pElementXFA;
    240     FX_DWORD count = pXFAArray->GetCount() / 2;
    241     for (FX_DWORD i = 0; i < count; i++) {
    242       CPDF_Stream* pStream = pXFAArray->GetStream(i * 2 + 1);
    243       if (pStream != NULL) {
    244         xfaStreams.Add(pStream);
    245       }
    246     }
    247   } else if (iObjType == PDFOBJ_STREAM) {
    248     xfaStreams.Add((CPDF_Stream*)pElementXFA);
    249   }
    250   if (xfaStreams.GetSize() < 1) {
    251     return FALSE;
    252   }
    253   IFX_FileRead* pFileRead = new CXFA_FileRead(xfaStreams);
    254   m_pPDFDoc = pPDFDoc;
    255   if (m_pStream) {
    256     m_pStream->Release();
    257     m_pStream = NULL;
    258   }
    259   m_pStream = pFileRead;
    260   m_bOwnStream = TRUE;
    261   return TRUE;
    262 }
    263 FX_BOOL CXFA_FFDoc::CloseDoc() {
    264   FX_POSITION psClose = m_mapTypeToDocView.GetStartPosition();
    265   while (psClose) {
    266     void* pType;
    267     CXFA_FFDocView* pDocView;
    268     m_mapTypeToDocView.GetNextAssoc(psClose, pType, (void*&)pDocView);
    269     pDocView->RunDocClose();
    270   }
    271   if (m_pDocument) {
    272     m_pDocument->ClearLayoutData();
    273   }
    274   FX_POSITION ps = m_mapTypeToDocView.GetStartPosition();
    275   while (ps) {
    276     void* pType;
    277     CXFA_FFDocView* pDocView;
    278     m_mapTypeToDocView.GetNextAssoc(ps, pType, (void*&)pDocView);
    279     delete pDocView;
    280   }
    281   m_mapTypeToDocView.RemoveAll();
    282   if (m_pDocument) {
    283     IXFA_Parser* pParser = m_pDocument->GetParser();
    284     pParser->Release();
    285     m_pDocument = NULL;
    286   }
    287   if (m_pNotify) {
    288     delete m_pNotify;
    289     m_pNotify = NULL;
    290   }
    291   m_pApp->GetXFAFontMgr()->ReleaseDocFonts(this);
    292   if (m_dwDocType != XFA_DOCTYPE_XDP && m_pStream && m_bOwnStream) {
    293     m_pStream->Release();
    294     m_pStream = NULL;
    295   }
    296   ps = m_mapNamedImages.GetStartPosition();
    297   while (ps) {
    298     void* pName;
    299     FX_IMAGEDIB_AND_DPI* pImage = NULL;
    300     m_mapNamedImages.GetNextAssoc(ps, pName, (void*&)pImage);
    301     if (pImage) {
    302       delete pImage->pDibSource;
    303       pImage->pDibSource = NULL;
    304       FX_Free(pImage);
    305       pImage = NULL;
    306     }
    307   }
    308   m_mapNamedImages.RemoveAll();
    309   IFWL_NoteDriver* pNoteDriver = FWL_GetApp()->GetNoteDriver();
    310   pNoteDriver->ClearEventTargets(FALSE);
    311   return TRUE;
    312 }
    313 void CXFA_FFDoc::SetDocType(FX_DWORD dwType) {
    314   m_dwDocType = dwType;
    315 }
    316 CPDF_Document* CXFA_FFDoc::GetPDFDoc() {
    317   return m_pPDFDoc;
    318 }
    319 #define _FXLIB_NEW_VERSION_
    320 CFX_DIBitmap* CXFA_FFDoc::GetPDFNamedImage(const CFX_WideStringC& wsName,
    321                                            int32_t& iImageXDpi,
    322                                            int32_t& iImageYDpi) {
    323   if (!m_pPDFDoc) {
    324     return NULL;
    325   }
    326   FX_DWORD dwHash =
    327       FX_HashCode_String_GetW(wsName.GetPtr(), wsName.GetLength(), FALSE);
    328   FX_IMAGEDIB_AND_DPI* imageDIBDpi = NULL;
    329   if (m_mapNamedImages.Lookup((void*)(uintptr_t)dwHash, (void*&)imageDIBDpi)) {
    330     iImageXDpi = imageDIBDpi->iImageXDpi;
    331     iImageYDpi = imageDIBDpi->iImageYDpi;
    332     return (CFX_DIBitmap*)imageDIBDpi->pDibSource;
    333   }
    334   CPDF_Dictionary* pRoot = m_pPDFDoc->GetRoot();
    335   if (pRoot == NULL) {
    336     return NULL;
    337   }
    338   CPDF_Dictionary* pNames = pRoot->GetDict("Names");
    339   if (!pNames) {
    340     return NULL;
    341   }
    342   CPDF_Dictionary* pXFAImages = pNames->GetDict("XFAImages");
    343   if (!pXFAImages) {
    344     return NULL;
    345   }
    346   CPDF_NameTree nametree(pXFAImages);
    347 #ifdef _FXLIB_NEW_VERSION_
    348   CFX_ByteString bsName = PDF_EncodeText(wsName.GetPtr(), wsName.GetLength());
    349   CPDF_Object* pObject = nametree.LookupValue(bsName);
    350   if (!pObject) {
    351     int32_t iCount = nametree.GetCount();
    352     for (int32_t i = 0; i < iCount; i++) {
    353       CFX_ByteString bsTemp;
    354       CPDF_Object* pTempObject = nametree.LookupValue(i, bsTemp);
    355       if (bsTemp == bsName) {
    356         pObject = pTempObject;
    357         break;
    358       }
    359     }
    360   }
    361 #else
    362   CPDF_Object* pObject = nametree.LookupValue(wsName);
    363   if (!pObject) {
    364     int32_t iCount = nametree.GetCount();
    365     for (int32_t i = 0; i < iCount; i++) {
    366       CFX_WideString wsTemp;
    367       CPDF_Object* pTempObject = nametree.LookupValue(i, wsTemp);
    368       if (wsTemp == wsName) {
    369         pObject = pTempObject;
    370         break;
    371       }
    372     }
    373   }
    374 #endif
    375   if (!pObject || pObject->GetType() != PDFOBJ_STREAM) {
    376     return NULL;
    377   }
    378   if (!imageDIBDpi) {
    379     imageDIBDpi = FX_Alloc(FX_IMAGEDIB_AND_DPI, 1);
    380     imageDIBDpi->pDibSource = NULL;
    381     imageDIBDpi->iImageXDpi = 0;
    382     imageDIBDpi->iImageYDpi = 0;
    383     CPDF_StreamAcc streamAcc;
    384     streamAcc.LoadAllData((CPDF_Stream*)pObject);
    385     IFX_FileRead* pImageFileRead = FX_CreateMemoryStream(
    386         (uint8_t*)streamAcc.GetData(), streamAcc.GetSize());
    387     imageDIBDpi->pDibSource = XFA_LoadImageFromBuffer(
    388         pImageFileRead, FXCODEC_IMAGE_UNKNOWN, iImageXDpi, iImageYDpi);
    389     imageDIBDpi->iImageXDpi = iImageXDpi;
    390     imageDIBDpi->iImageYDpi = iImageYDpi;
    391     pImageFileRead->Release();
    392   }
    393   m_mapNamedImages.SetAt((void*)(uintptr_t)dwHash, imageDIBDpi);
    394   return (CFX_DIBitmap*)imageDIBDpi->pDibSource;
    395 }
    396 IFDE_XMLElement* CXFA_FFDoc::GetPackageData(const CFX_WideStringC& wsPackage) {
    397   FX_DWORD packetHash =
    398       FX_HashCode_String_GetW(wsPackage.GetPtr(), wsPackage.GetLength());
    399   CXFA_Object* pObject = m_pDocument->GetXFANode(packetHash);
    400   CXFA_Node* pNode =
    401       (pObject && pObject->IsNode()) ? (CXFA_Node*)pObject : NULL;
    402   if (!pNode) {
    403     return NULL;
    404   }
    405   IFDE_XMLNode* pXMLNode = pNode->GetXMLMappingNode();
    406   return (pXMLNode && pXMLNode->GetType() == FDE_XMLNODE_Element)
    407              ? (IFDE_XMLElement*)pXMLNode
    408              : NULL;
    409 }
    410 FX_BOOL CXFA_FFDoc::SavePackage(const CFX_WideStringC& wsPackage,
    411                                 IFX_FileWrite* pFile,
    412                                 IXFA_ChecksumContext* pCSContext) {
    413   IXFA_PacketExport* pExport = IXFA_PacketExport::Create(m_pDocument);
    414   if (!pExport) {
    415     return FALSE;
    416   }
    417   FX_DWORD packetHash =
    418       FX_HashCode_String_GetW(wsPackage.GetPtr(), wsPackage.GetLength());
    419   CXFA_Node* pNode = NULL;
    420   if (packetHash == XFA_HASHCODE_Xfa) {
    421     pNode = m_pDocument->GetRoot();
    422   } else {
    423     CXFA_Object* pObject = m_pDocument->GetXFANode(packetHash);
    424     pNode = (pObject && pObject->IsNode()) ? (CXFA_Node*)pObject : NULL;
    425   }
    426   FX_BOOL bFlags = FALSE;
    427   if (pNode) {
    428     CFX_ByteString bsChecksum;
    429     if (pCSContext) {
    430       pCSContext->GetChecksum(bsChecksum);
    431     }
    432     bFlags = pExport->Export(pFile, pNode, 0, bsChecksum.GetLength()
    433                                                   ? (const FX_CHAR*)bsChecksum
    434                                                   : NULL);
    435   } else {
    436     bFlags = pExport->Export(pFile);
    437   }
    438   pExport->Release();
    439   return bFlags;
    440 }
    441 FX_BOOL CXFA_FFDoc::ImportData(IFX_FileRead* pStream, FX_BOOL bXDP) {
    442   FX_BOOL bRet = FALSE;
    443   IXFA_PacketImport* pImport = IXFA_PacketImport::Create(m_pDocument);
    444   if (pImport) {
    445     bRet = pImport->ImportData(pStream);
    446     pImport->Release();
    447   }
    448   return bRet;
    449 }
    450