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/fxfa/xfa_ffdoc.h" 8 9 #include <algorithm> 10 #include <memory> 11 #include <vector> 12 13 #include "core/fpdfapi/parser/cpdf_array.h" 14 #include "core/fpdfapi/parser/cpdf_document.h" 15 #include "core/fpdfapi/parser/fpdf_parser_decode.h" 16 #include "core/fpdfdoc/cpdf_nametree.h" 17 #include "core/fxcrt/fx_ext.h" 18 #include "core/fxcrt/fx_memory.h" 19 #include "third_party/base/ptr_util.h" 20 #include "xfa/fde/xml/fde_xml_imp.h" 21 #include "xfa/fwl/cfwl_notedriver.h" 22 #include "xfa/fxfa/app/xfa_ffnotify.h" 23 #include "xfa/fxfa/parser/cxfa_dataexporter.h" 24 #include "xfa/fxfa/parser/cxfa_dataimporter.h" 25 #include "xfa/fxfa/parser/cxfa_document.h" 26 #include "xfa/fxfa/xfa_checksum.h" 27 #include "xfa/fxfa/xfa_ffapp.h" 28 #include "xfa/fxfa/xfa_ffdocview.h" 29 #include "xfa/fxfa/xfa_ffwidget.h" 30 #include "xfa/fxfa/xfa_fontmgr.h" 31 32 namespace { 33 34 struct FX_BASE64DATA { 35 uint32_t data1 : 2; 36 uint32_t data2 : 6; 37 uint32_t data3 : 4; 38 uint32_t data4 : 4; 39 uint32_t data5 : 6; 40 uint32_t data6 : 2; 41 uint32_t data7 : 8; 42 }; 43 44 const uint8_t kStartValuesRemoved = 43; 45 const uint8_t kDecoderMapSize = 80; 46 const uint8_t g_FXBase64DecoderMap[kDecoderMapSize] = { 47 0x3E, 0xFF, 0xFF, 0xFF, 0x3F, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 48 0x3B, 0x3C, 0x3D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x01, 49 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 50 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 51 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 52 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 53 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 54 }; 55 56 uint8_t base64DecoderValue(uint8_t val) { 57 if (val < kStartValuesRemoved || val >= kStartValuesRemoved + kDecoderMapSize) 58 return 0xFF; 59 return g_FXBase64DecoderMap[val - kStartValuesRemoved]; 60 } 61 62 void Base64DecodePiece(const FX_CHAR src[4], 63 int32_t iChars, 64 FX_BASE64DATA& dst, 65 int32_t& iBytes) { 66 ASSERT(iChars > 0 && iChars < 5); 67 iBytes = 1; 68 dst.data2 = base64DecoderValue(static_cast<uint8_t>(src[0])); 69 if (iChars > 1) { 70 uint8_t b = base64DecoderValue(static_cast<uint8_t>(src[1])); 71 dst.data1 = b >> 4; 72 dst.data4 = b; 73 if (iChars > 2) { 74 iBytes = 2; 75 b = base64DecoderValue(static_cast<uint8_t>(src[2])); 76 dst.data3 = b >> 2; 77 dst.data6 = b; 78 if (iChars > 3) { 79 iBytes = 3; 80 dst.data5 = base64DecoderValue(static_cast<uint8_t>(src[3])); 81 } else { 82 dst.data5 = 0; 83 } 84 } else { 85 dst.data3 = 0; 86 } 87 } else { 88 dst.data1 = 0; 89 } 90 } 91 92 int32_t Base64DecodeW(const FX_WCHAR* pSrc, int32_t iSrcLen, uint8_t* pDst) { 93 ASSERT(pSrc); 94 if (iSrcLen < 1) { 95 return 0; 96 } 97 while (iSrcLen > 0 && pSrc[iSrcLen - 1] == '=') { 98 iSrcLen--; 99 } 100 if (iSrcLen < 1) { 101 return 0; 102 } 103 if (!pDst) { 104 int32_t iDstLen = iSrcLen / 4 * 3; 105 iSrcLen %= 4; 106 if (iSrcLen == 1) { 107 iDstLen += 1; 108 } else if (iSrcLen == 2) { 109 iDstLen += 1; 110 } else if (iSrcLen == 3) { 111 iDstLen += 2; 112 } 113 return iDstLen; 114 } 115 FX_CHAR srcData[4]; 116 FX_BASE64DATA dstData; 117 int32_t iChars = 4, iBytes; 118 uint8_t* pDstEnd = pDst; 119 while (iSrcLen > 0) { 120 if (iSrcLen > 3) { 121 srcData[0] = (FX_CHAR)*pSrc++; 122 srcData[1] = (FX_CHAR)*pSrc++; 123 srcData[2] = (FX_CHAR)*pSrc++; 124 srcData[3] = (FX_CHAR)*pSrc++; 125 iSrcLen -= 4; 126 } else { 127 *((uint32_t*)&dstData) = 0; 128 *((uint32_t*)srcData) = 0; 129 srcData[0] = (FX_CHAR)*pSrc++; 130 if (iSrcLen > 1) { 131 srcData[1] = (FX_CHAR)*pSrc++; 132 } 133 if (iSrcLen > 2) { 134 srcData[2] = (FX_CHAR)*pSrc++; 135 } 136 iChars = iSrcLen; 137 iSrcLen = 0; 138 } 139 Base64DecodePiece(srcData, iChars, dstData, iBytes); 140 *pDstEnd++ = ((uint8_t*)&dstData)[0]; 141 if (iBytes > 1) { 142 *pDstEnd++ = ((uint8_t*)&dstData)[1]; 143 } 144 if (iBytes > 2) { 145 *pDstEnd++ = ((uint8_t*)&dstData)[2]; 146 } 147 } 148 return pDstEnd - pDst; 149 } 150 151 } // namespace 152 153 CXFA_FFDoc::CXFA_FFDoc(CXFA_FFApp* pApp, IXFA_DocEnvironment* pDocEnvironment) 154 : m_pDocEnvironment(pDocEnvironment), 155 m_pDocumentParser(nullptr), 156 m_pApp(pApp), 157 m_pNotify(nullptr), 158 m_pPDFDoc(nullptr), 159 m_dwDocType(XFA_DOCTYPE_Static) {} 160 161 CXFA_FFDoc::~CXFA_FFDoc() { 162 CloseDoc(); 163 } 164 165 uint32_t CXFA_FFDoc::GetDocType() { 166 return m_dwDocType; 167 } 168 169 int32_t CXFA_FFDoc::StartLoad() { 170 m_pNotify = pdfium::MakeUnique<CXFA_FFNotify>(this); 171 m_pDocumentParser = pdfium::MakeUnique<CXFA_DocumentParser>(m_pNotify.get()); 172 return m_pDocumentParser->StartParse(m_pStream, XFA_XDPPACKET_XDP); 173 } 174 175 bool XFA_GetPDFContentsFromPDFXML(CFDE_XMLNode* pPDFElement, 176 uint8_t*& pByteBuffer, 177 int32_t& iBufferSize) { 178 CFDE_XMLElement* pDocumentElement = nullptr; 179 for (CFDE_XMLNode* pXMLNode = 180 pPDFElement->GetNodeItem(CFDE_XMLNode::FirstChild); 181 pXMLNode; pXMLNode = pXMLNode->GetNodeItem(CFDE_XMLNode::NextSibling)) { 182 if (pXMLNode->GetType() == FDE_XMLNODE_Element) { 183 CFX_WideString wsTagName; 184 CFDE_XMLElement* pXMLElement = static_cast<CFDE_XMLElement*>(pXMLNode); 185 pXMLElement->GetTagName(wsTagName); 186 if (wsTagName == L"document") { 187 pDocumentElement = pXMLElement; 188 break; 189 } 190 } 191 } 192 if (!pDocumentElement) { 193 return false; 194 } 195 CFDE_XMLElement* pChunkElement = nullptr; 196 for (CFDE_XMLNode* pXMLNode = 197 pDocumentElement->GetNodeItem(CFDE_XMLNode::FirstChild); 198 pXMLNode; pXMLNode = pXMLNode->GetNodeItem(CFDE_XMLNode::NextSibling)) { 199 if (pXMLNode->GetType() == FDE_XMLNODE_Element) { 200 CFX_WideString wsTagName; 201 CFDE_XMLElement* pXMLElement = static_cast<CFDE_XMLElement*>(pXMLNode); 202 pXMLElement->GetTagName(wsTagName); 203 if (wsTagName == L"chunk") { 204 pChunkElement = pXMLElement; 205 break; 206 } 207 } 208 } 209 if (!pChunkElement) { 210 return false; 211 } 212 CFX_WideString wsPDFContent; 213 pChunkElement->GetTextData(wsPDFContent); 214 iBufferSize = 215 Base64DecodeW(wsPDFContent.c_str(), wsPDFContent.GetLength(), nullptr); 216 pByteBuffer = FX_Alloc(uint8_t, iBufferSize + 1); 217 pByteBuffer[iBufferSize] = '0'; // FIXME: I bet this is wrong. 218 Base64DecodeW(wsPDFContent.c_str(), wsPDFContent.GetLength(), pByteBuffer); 219 return true; 220 } 221 void XFA_XPDPacket_MergeRootNode(CXFA_Node* pOriginRoot, CXFA_Node* pNewRoot) { 222 CXFA_Node* pChildNode = pNewRoot->GetNodeItem(XFA_NODEITEM_FirstChild); 223 while (pChildNode) { 224 CXFA_Node* pOriginChild = 225 pOriginRoot->GetFirstChildByName(pChildNode->GetNameHash()); 226 if (pOriginChild) { 227 pChildNode = pChildNode->GetNodeItem(XFA_NODEITEM_NextSibling); 228 } else { 229 CXFA_Node* pNextSibling = 230 pChildNode->GetNodeItem(XFA_NODEITEM_NextSibling); 231 pNewRoot->RemoveChild(pChildNode); 232 pOriginRoot->InsertChild(pChildNode); 233 pChildNode = pNextSibling; 234 pNextSibling = nullptr; 235 } 236 } 237 } 238 239 int32_t CXFA_FFDoc::DoLoad(IFX_Pause* pPause) { 240 int32_t iStatus = m_pDocumentParser->DoParse(pPause); 241 if (iStatus == XFA_PARSESTATUS_Done && !m_pPDFDoc) 242 return XFA_PARSESTATUS_SyntaxErr; 243 return iStatus; 244 } 245 246 void CXFA_FFDoc::StopLoad() { 247 m_pApp->GetXFAFontMgr()->LoadDocFonts(this); 248 m_dwDocType = XFA_DOCTYPE_Static; 249 CXFA_Node* pConfig = ToNode( 250 m_pDocumentParser->GetDocument()->GetXFAObject(XFA_HASHCODE_Config)); 251 if (!pConfig) { 252 return; 253 } 254 CXFA_Node* pAcrobat = pConfig->GetFirstChildByClass(XFA_Element::Acrobat); 255 if (!pAcrobat) { 256 return; 257 } 258 CXFA_Node* pAcrobat7 = pAcrobat->GetFirstChildByClass(XFA_Element::Acrobat7); 259 if (!pAcrobat7) { 260 return; 261 } 262 CXFA_Node* pDynamicRender = 263 pAcrobat7->GetFirstChildByClass(XFA_Element::DynamicRender); 264 if (!pDynamicRender) { 265 return; 266 } 267 CFX_WideString wsType; 268 if (pDynamicRender->TryContent(wsType) && wsType == L"required") { 269 m_dwDocType = XFA_DOCTYPE_Dynamic; 270 } 271 } 272 273 CXFA_FFDocView* CXFA_FFDoc::CreateDocView(uint32_t dwView) { 274 if (!m_TypeToDocViewMap[dwView]) 275 m_TypeToDocViewMap[dwView] = pdfium::MakeUnique<CXFA_FFDocView>(this); 276 277 return m_TypeToDocViewMap[dwView].get(); 278 } 279 280 CXFA_FFDocView* CXFA_FFDoc::GetDocView(CXFA_LayoutProcessor* pLayout) { 281 for (const auto& pair : m_TypeToDocViewMap) { 282 if (pair.second->GetXFALayout() == pLayout) 283 return pair.second.get(); 284 } 285 return nullptr; 286 } 287 288 CXFA_FFDocView* CXFA_FFDoc::GetDocView() { 289 auto it = m_TypeToDocViewMap.begin(); 290 return it != m_TypeToDocViewMap.end() ? it->second.get() : nullptr; 291 } 292 293 bool CXFA_FFDoc::OpenDoc(const CFX_RetainPtr<IFX_SeekableReadStream>& pStream) { 294 m_pStream = pStream; 295 return true; 296 } 297 bool CXFA_FFDoc::OpenDoc(CPDF_Document* pPDFDoc) { 298 if (!pPDFDoc) 299 return false; 300 301 CPDF_Dictionary* pRoot = pPDFDoc->GetRoot(); 302 if (!pRoot) 303 return false; 304 305 CPDF_Dictionary* pAcroForm = pRoot->GetDictFor("AcroForm"); 306 if (!pAcroForm) 307 return false; 308 309 CPDF_Object* pElementXFA = pAcroForm->GetDirectObjectFor("XFA"); 310 if (!pElementXFA) 311 return false; 312 313 std::vector<CPDF_Stream*> xfaStreams; 314 if (pElementXFA->IsArray()) { 315 CPDF_Array* pXFAArray = (CPDF_Array*)pElementXFA; 316 for (size_t i = 0; i < pXFAArray->GetCount() / 2; i++) { 317 if (CPDF_Stream* pStream = pXFAArray->GetStreamAt(i * 2 + 1)) 318 xfaStreams.push_back(pStream); 319 } 320 } else if (pElementXFA->IsStream()) { 321 xfaStreams.push_back((CPDF_Stream*)pElementXFA); 322 } 323 if (xfaStreams.empty()) 324 return false; 325 326 m_pPDFDoc = pPDFDoc; 327 m_pStream = MakeSeekableReadStream(xfaStreams); 328 return true; 329 } 330 331 bool CXFA_FFDoc::CloseDoc() { 332 for (const auto& pair : m_TypeToDocViewMap) 333 pair.second->RunDocClose(); 334 335 CXFA_Document* doc = 336 m_pDocumentParser ? m_pDocumentParser->GetDocument() : nullptr; 337 if (doc) 338 doc->ClearLayoutData(); 339 340 m_TypeToDocViewMap.clear(); 341 342 m_pNotify.reset(nullptr); 343 m_pApp->GetXFAFontMgr()->ReleaseDocFonts(this); 344 345 for (const auto& pair : m_HashToDibDpiMap) 346 delete pair.second.pDibSource; 347 348 m_HashToDibDpiMap.clear(); 349 m_pApp->ClearEventTargets(); 350 return true; 351 } 352 void CXFA_FFDoc::SetDocType(uint32_t dwType) { 353 m_dwDocType = dwType; 354 } 355 CPDF_Document* CXFA_FFDoc::GetPDFDoc() { 356 return m_pPDFDoc; 357 } 358 359 CFX_DIBitmap* CXFA_FFDoc::GetPDFNamedImage(const CFX_WideStringC& wsName, 360 int32_t& iImageXDpi, 361 int32_t& iImageYDpi) { 362 if (!m_pPDFDoc) 363 return nullptr; 364 365 uint32_t dwHash = FX_HashCode_GetW(wsName, false); 366 auto it = m_HashToDibDpiMap.find(dwHash); 367 if (it != m_HashToDibDpiMap.end()) { 368 iImageXDpi = it->second.iImageXDpi; 369 iImageYDpi = it->second.iImageYDpi; 370 return static_cast<CFX_DIBitmap*>(it->second.pDibSource); 371 } 372 373 CPDF_Dictionary* pRoot = m_pPDFDoc->GetRoot(); 374 if (!pRoot) 375 return nullptr; 376 377 CPDF_Dictionary* pNames = pRoot->GetDictFor("Names"); 378 if (!pNames) 379 return nullptr; 380 381 CPDF_Dictionary* pXFAImages = pNames->GetDictFor("XFAImages"); 382 if (!pXFAImages) 383 return nullptr; 384 385 CPDF_NameTree nametree(pXFAImages); 386 CFX_ByteString bsName = PDF_EncodeText(wsName.c_str(), wsName.GetLength()); 387 CPDF_Object* pObject = nametree.LookupValue(bsName); 388 if (!pObject) { 389 for (size_t i = 0; i < nametree.GetCount(); i++) { 390 CFX_ByteString bsTemp; 391 CPDF_Object* pTempObject = nametree.LookupValue(i, bsTemp); 392 if (bsTemp == bsName) { 393 pObject = pTempObject; 394 break; 395 } 396 } 397 } 398 399 CPDF_Stream* pStream = ToStream(pObject); 400 if (!pStream) 401 return nullptr; 402 403 CPDF_StreamAcc streamAcc; 404 streamAcc.LoadAllData(pStream); 405 406 CFX_RetainPtr<IFX_SeekableReadStream> pImageFileRead = 407 IFX_MemoryStream::Create((uint8_t*)streamAcc.GetData(), 408 streamAcc.GetSize()); 409 410 CFX_DIBitmap* pDibSource = XFA_LoadImageFromBuffer( 411 pImageFileRead, FXCODEC_IMAGE_UNKNOWN, iImageXDpi, iImageYDpi); 412 m_HashToDibDpiMap[dwHash] = {pDibSource, iImageXDpi, iImageYDpi}; 413 return pDibSource; 414 } 415 416 bool CXFA_FFDoc::SavePackage( 417 XFA_HashCode code, 418 const CFX_RetainPtr<IFX_SeekableWriteStream>& pFile, 419 CXFA_ChecksumContext* pCSContext) { 420 CXFA_Document* doc = m_pDocumentParser->GetDocument(); 421 std::unique_ptr<CXFA_DataExporter> pExport(new CXFA_DataExporter(doc)); 422 CXFA_Node* pNode = code == XFA_HASHCODE_Xfa ? doc->GetRoot() 423 : ToNode(doc->GetXFAObject(code)); 424 if (!pNode) 425 return !!pExport->Export(pFile); 426 427 CFX_ByteString bsChecksum; 428 if (pCSContext) 429 bsChecksum = pCSContext->GetChecksum(); 430 431 return !!pExport->Export( 432 pFile, pNode, 0, bsChecksum.GetLength() ? bsChecksum.c_str() : nullptr); 433 } 434 435 bool CXFA_FFDoc::ImportData( 436 const CFX_RetainPtr<IFX_SeekableReadStream>& pStream, 437 bool bXDP) { 438 auto importer = 439 pdfium::MakeUnique<CXFA_DataImporter>(m_pDocumentParser->GetDocument()); 440 return importer->ImportData(pStream); 441 } 442