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