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