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