blob: 24a8a04c03e624fa794f6ca230b57c0aa7107e24 [file] [log] [blame]
Dan Sinclair1770c022016-03-14 14:14:16 -04001// 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
Dan Sinclair80c48782017-03-23 12:11:20 -04007#include "xfa/fxfa/cxfa_ffdoc.h"
Dan Sinclair1770c022016-03-14 14:14:16 -04008
tsepez084174a2016-04-25 12:37:27 -07009#include <algorithm>
Dan Sinclair85c8e7f2016-11-21 13:50:32 -050010#include <memory>
11#include <vector>
tsepez084174a2016-04-25 12:37:27 -070012
dsinclair488b7ad2016-10-04 11:55:50 -070013#include "core/fpdfapi/parser/cpdf_array.h"
14#include "core/fpdfapi/parser/cpdf_document.h"
15#include "core/fpdfapi/parser/fpdf_parser_decode.h"
dsinclair1727aee2016-09-29 13:12:56 -070016#include "core/fpdfdoc/cpdf_nametree.h"
Dan Sinclair283a0432017-04-20 14:11:21 -040017#include "core/fxcrt/cfx_memorystream.h"
Ryan Harrisonccf206a2017-11-14 16:05:53 +000018#include "core/fxcrt/cfx_seekablemultistream.h"
Dan Sinclaircfb19442017-04-20 13:13:04 -040019#include "core/fxcrt/fx_extension.h"
dsinclaira52ab742016-09-29 13:59:29 -070020#include "core/fxcrt/fx_memory.h"
Dan Sinclair0d86ecb2017-04-19 09:19:57 -040021#include "core/fxcrt/xml/cfx_xmlelement.h"
22#include "core/fxcrt/xml/cfx_xmlnode.h"
Lei Zhangd859d572018-01-17 20:44:26 +000023#include "fxjs/xfa/cjx_object.h"
tsepeza9caab92016-12-14 05:57:10 -080024#include "third_party/base/ptr_util.h"
dsinclair447b1f32016-12-08 10:06:32 -080025#include "xfa/fwl/cfwl_notedriver.h"
Dan Sinclair80c48782017-03-23 12:11:20 -040026#include "xfa/fxfa/cxfa_ffapp.h"
27#include "xfa/fxfa/cxfa_ffdocview.h"
Dan Sinclair24ef6332017-07-24 10:52:57 -040028#include "xfa/fxfa/cxfa_ffnotify.h"
Dan Sinclair80c48782017-03-23 12:11:20 -040029#include "xfa/fxfa/cxfa_ffwidget.h"
30#include "xfa/fxfa/cxfa_fontmgr.h"
Dan Sinclairdf4f30e2017-12-14 20:51:03 +000031#include "xfa/fxfa/parser/cxfa_acrobat.h"
32#include "xfa/fxfa/parser/cxfa_acrobat7.h"
dsinclair3a7cc732016-07-21 12:04:34 -070033#include "xfa/fxfa/parser/cxfa_dataexporter.h"
34#include "xfa/fxfa/parser/cxfa_dataimporter.h"
dsinclair16280242016-07-21 12:03:47 -070035#include "xfa/fxfa/parser/cxfa_document.h"
Dan Sinclair876efaa2018-04-12 13:39:28 +000036#include "xfa/fxfa/parser/cxfa_document_parser.h"
Dan Sinclairdf4f30e2017-12-14 20:51:03 +000037#include "xfa/fxfa/parser/cxfa_dynamicrender.h"
Dan Sinclairefcae5d2017-03-29 14:47:46 -040038#include "xfa/fxfa/parser/cxfa_node.h"
Dan Sinclair1770c022016-03-14 14:14:16 -040039
dsinclairfc2cdf82016-05-19 18:07:11 -070040namespace {
41
42struct FX_BASE64DATA {
43 uint32_t data1 : 2;
44 uint32_t data2 : 6;
45 uint32_t data3 : 4;
46 uint32_t data4 : 4;
47 uint32_t data5 : 6;
48 uint32_t data6 : 2;
49 uint32_t data7 : 8;
50};
51
52const uint8_t kStartValuesRemoved = 43;
53const uint8_t kDecoderMapSize = 80;
54const uint8_t g_FXBase64DecoderMap[kDecoderMapSize] = {
55 0x3E, 0xFF, 0xFF, 0xFF, 0x3F, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A,
56 0x3B, 0x3C, 0x3D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x01,
57 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D,
58 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
59 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
60 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B,
61 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33,
62};
63
64uint8_t base64DecoderValue(uint8_t val) {
65 if (val < kStartValuesRemoved || val >= kStartValuesRemoved + kDecoderMapSize)
66 return 0xFF;
67 return g_FXBase64DecoderMap[val - kStartValuesRemoved];
68}
69
Dan Sinclair812e96c2017-03-13 16:43:37 -040070void Base64DecodePiece(const char src[4],
dsinclairfc2cdf82016-05-19 18:07:11 -070071 int32_t iChars,
72 FX_BASE64DATA& dst,
73 int32_t& iBytes) {
74 ASSERT(iChars > 0 && iChars < 5);
75 iBytes = 1;
76 dst.data2 = base64DecoderValue(static_cast<uint8_t>(src[0]));
77 if (iChars > 1) {
78 uint8_t b = base64DecoderValue(static_cast<uint8_t>(src[1]));
79 dst.data1 = b >> 4;
80 dst.data4 = b;
81 if (iChars > 2) {
82 iBytes = 2;
83 b = base64DecoderValue(static_cast<uint8_t>(src[2]));
84 dst.data3 = b >> 2;
85 dst.data6 = b;
86 if (iChars > 3) {
87 iBytes = 3;
88 dst.data5 = base64DecoderValue(static_cast<uint8_t>(src[3]));
89 } else {
90 dst.data5 = 0;
91 }
92 } else {
93 dst.data3 = 0;
94 }
95 } else {
96 dst.data1 = 0;
97 }
98}
99
Dan Sinclair812e96c2017-03-13 16:43:37 -0400100int32_t Base64DecodeW(const wchar_t* pSrc, int32_t iSrcLen, uint8_t* pDst) {
dsinclairfc2cdf82016-05-19 18:07:11 -0700101 ASSERT(pSrc);
102 if (iSrcLen < 1) {
103 return 0;
104 }
105 while (iSrcLen > 0 && pSrc[iSrcLen - 1] == '=') {
106 iSrcLen--;
107 }
108 if (iSrcLen < 1) {
109 return 0;
110 }
111 if (!pDst) {
112 int32_t iDstLen = iSrcLen / 4 * 3;
113 iSrcLen %= 4;
114 if (iSrcLen == 1) {
115 iDstLen += 1;
116 } else if (iSrcLen == 2) {
117 iDstLen += 1;
118 } else if (iSrcLen == 3) {
119 iDstLen += 2;
120 }
121 return iDstLen;
122 }
Dan Sinclair812e96c2017-03-13 16:43:37 -0400123 char srcData[4];
dsinclairfc2cdf82016-05-19 18:07:11 -0700124 FX_BASE64DATA dstData;
125 int32_t iChars = 4, iBytes;
126 uint8_t* pDstEnd = pDst;
127 while (iSrcLen > 0) {
128 if (iSrcLen > 3) {
Dan Sinclair812e96c2017-03-13 16:43:37 -0400129 srcData[0] = (char)*pSrc++;
130 srcData[1] = (char)*pSrc++;
131 srcData[2] = (char)*pSrc++;
132 srcData[3] = (char)*pSrc++;
dsinclairfc2cdf82016-05-19 18:07:11 -0700133 iSrcLen -= 4;
134 } else {
135 *((uint32_t*)&dstData) = 0;
136 *((uint32_t*)srcData) = 0;
Dan Sinclair812e96c2017-03-13 16:43:37 -0400137 srcData[0] = (char)*pSrc++;
dsinclairfc2cdf82016-05-19 18:07:11 -0700138 if (iSrcLen > 1) {
Dan Sinclair812e96c2017-03-13 16:43:37 -0400139 srcData[1] = (char)*pSrc++;
dsinclairfc2cdf82016-05-19 18:07:11 -0700140 }
141 if (iSrcLen > 2) {
Dan Sinclair812e96c2017-03-13 16:43:37 -0400142 srcData[2] = (char)*pSrc++;
dsinclairfc2cdf82016-05-19 18:07:11 -0700143 }
144 iChars = iSrcLen;
145 iSrcLen = 0;
146 }
147 Base64DecodePiece(srcData, iChars, dstData, iBytes);
148 *pDstEnd++ = ((uint8_t*)&dstData)[0];
149 if (iBytes > 1) {
150 *pDstEnd++ = ((uint8_t*)&dstData)[1];
151 }
152 if (iBytes > 2) {
153 *pDstEnd++ = ((uint8_t*)&dstData)[2];
154 }
155 }
156 return pDstEnd - pDst;
157}
158
159} // namespace
160
dsinclaira440bb32016-09-14 07:01:54 -0700161CXFA_FFDoc::CXFA_FFDoc(CXFA_FFApp* pApp, IXFA_DocEnvironment* pDocEnvironment)
Lei Zhang8509d3e2017-12-04 06:13:55 +0000162 : m_pDocEnvironment(pDocEnvironment), m_pApp(pApp) {}
dsinclaira1b07722016-07-11 08:20:58 -0700163
Dan Sinclair1770c022016-03-14 14:14:16 -0400164CXFA_FFDoc::~CXFA_FFDoc() {
165 CloseDoc();
166}
dsinclaira1b07722016-07-11 08:20:58 -0700167
Dan Sinclair62110c92018-04-12 13:40:49 +0000168bool CXFA_FFDoc::ParseDoc(CPDF_Object* pElementXFA) {
169 std::vector<CPDF_Stream*> xfaStreams;
170 if (pElementXFA->IsArray()) {
171 CPDF_Array* pXFAArray = (CPDF_Array*)pElementXFA;
172 for (size_t i = 0; i < pXFAArray->GetCount() / 2; i++) {
173 if (CPDF_Stream* pStream = pXFAArray->GetStreamAt(i * 2 + 1))
174 xfaStreams.push_back(pStream);
175 }
176 } else if (pElementXFA->IsStream()) {
177 xfaStreams.push_back(pElementXFA->AsStream());
178 }
179 if (xfaStreams.empty())
Dan Sinclair2efb11c2018-04-12 13:21:48 +0000180 return false;
181
Dan Sinclair62110c92018-04-12 13:40:49 +0000182 auto stream = pdfium::MakeRetain<CFX_SeekableMultiStream>(xfaStreams);
Dan Sinclair0cad1162018-04-12 13:23:08 +0000183
Dan Sinclair0cad1162018-04-12 13:23:08 +0000184 // Note, we don't pass the document into the constructor as currently that
185 // triggers different behaviour in the parser.
Dan Sinclair876efaa2018-04-12 13:39:28 +0000186 CXFA_DocumentParser parser;
Dan Sinclair0cad1162018-04-12 13:23:08 +0000187 parser.SetFactory(m_pDocument.get());
Dan Sinclair62110c92018-04-12 13:40:49 +0000188 if (!parser.Parse(stream, XFA_PacketType::Xdp))
Dan Sinclair0cad1162018-04-12 13:23:08 +0000189 return false;
190
191 m_pXMLRoot = parser.GetXMLRoot();
192 m_pDocument->SetRoot(parser.GetRootNode());
193 return true;
194}
195
Dan Sinclair0d86ecb2017-04-19 09:19:57 -0400196bool XFA_GetPDFContentsFromPDFXML(CFX_XMLNode* pPDFElement,
tsepezd19e9122016-11-02 15:43:18 -0700197 uint8_t*& pByteBuffer,
198 int32_t& iBufferSize) {
Dan Sinclair0d86ecb2017-04-19 09:19:57 -0400199 CFX_XMLElement* pDocumentElement = nullptr;
Dan Sinclairfa3765c2018-02-13 21:44:33 +0000200 for (CFX_XMLNode* pXMLNode = pPDFElement->GetFirstChild(); pXMLNode;
201 pXMLNode = pXMLNode->GetNextSibling()) {
Dan Sinclair0d86ecb2017-04-19 09:19:57 -0400202 if (pXMLNode->GetType() == FX_XMLNODE_Element) {
203 CFX_XMLElement* pXMLElement = static_cast<CFX_XMLElement*>(pXMLNode);
Ryan Harrison275e2602017-09-18 14:23:18 -0400204 WideString wsTagName = pXMLElement->GetName();
dan sinclair65c7c232017-02-02 14:05:30 -0800205 if (wsTagName == L"document") {
Dan Sinclair1770c022016-03-14 14:14:16 -0400206 pDocumentElement = pXMLElement;
207 break;
208 }
209 }
210 }
211 if (!pDocumentElement) {
tsepezd19e9122016-11-02 15:43:18 -0700212 return false;
Dan Sinclair1770c022016-03-14 14:14:16 -0400213 }
Dan Sinclair0d86ecb2017-04-19 09:19:57 -0400214 CFX_XMLElement* pChunkElement = nullptr;
Dan Sinclairfa3765c2018-02-13 21:44:33 +0000215 for (CFX_XMLNode* pXMLNode = pDocumentElement->GetFirstChild(); pXMLNode;
216 pXMLNode = pXMLNode->GetNextSibling()) {
Dan Sinclair0d86ecb2017-04-19 09:19:57 -0400217 if (pXMLNode->GetType() == FX_XMLNODE_Element) {
218 CFX_XMLElement* pXMLElement = static_cast<CFX_XMLElement*>(pXMLNode);
Ryan Harrison275e2602017-09-18 14:23:18 -0400219 WideString wsTagName = pXMLElement->GetName();
dan sinclair65c7c232017-02-02 14:05:30 -0800220 if (wsTagName == L"chunk") {
Dan Sinclair1770c022016-03-14 14:14:16 -0400221 pChunkElement = pXMLElement;
222 break;
223 }
224 }
225 }
226 if (!pChunkElement) {
tsepezd19e9122016-11-02 15:43:18 -0700227 return false;
Dan Sinclair1770c022016-03-14 14:14:16 -0400228 }
Ryan Harrison275e2602017-09-18 14:23:18 -0400229 WideString wsPDFContent = pChunkElement->GetTextData();
tsepezbd9748d2016-04-13 21:40:19 -0700230 iBufferSize =
dsinclairfc2cdf82016-05-19 18:07:11 -0700231 Base64DecodeW(wsPDFContent.c_str(), wsPDFContent.GetLength(), nullptr);
Dan Sinclair1770c022016-03-14 14:14:16 -0400232 pByteBuffer = FX_Alloc(uint8_t, iBufferSize + 1);
233 pByteBuffer[iBufferSize] = '0'; // FIXME: I bet this is wrong.
dsinclairfc2cdf82016-05-19 18:07:11 -0700234 Base64DecodeW(wsPDFContent.c_str(), wsPDFContent.GetLength(), pByteBuffer);
tsepezd19e9122016-11-02 15:43:18 -0700235 return true;
Dan Sinclair1770c022016-03-14 14:14:16 -0400236}
237void XFA_XPDPacket_MergeRootNode(CXFA_Node* pOriginRoot, CXFA_Node* pNewRoot) {
Dan Sinclair18a60692018-01-10 16:30:56 +0000238 CXFA_Node* pChildNode = pNewRoot->GetFirstChild();
Dan Sinclair1770c022016-03-14 14:14:16 -0400239 while (pChildNode) {
240 CXFA_Node* pOriginChild =
241 pOriginRoot->GetFirstChildByName(pChildNode->GetNameHash());
242 if (pOriginChild) {
Dan Sinclair18a60692018-01-10 16:30:56 +0000243 pChildNode = pChildNode->GetNextSibling();
Dan Sinclair1770c022016-03-14 14:14:16 -0400244 } else {
Dan Sinclair18a60692018-01-10 16:30:56 +0000245 CXFA_Node* pNextSibling = pChildNode->GetNextSibling();
Dan Sinclair185832c2017-11-04 03:31:29 +0000246 pNewRoot->RemoveChild(pChildNode, true);
247 pOriginRoot->InsertChild(pChildNode, nullptr);
Dan Sinclair1770c022016-03-14 14:14:16 -0400248 pChildNode = pNextSibling;
dsinclairfc2cdf82016-05-19 18:07:11 -0700249 pNextSibling = nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -0400250 }
251 }
252}
dsinclair89f8fa82016-09-14 06:11:08 -0700253
Dan Sinclair3d060222017-03-22 15:29:20 -0400254CXFA_FFDocView* CXFA_FFDoc::CreateDocView() {
255 if (!m_DocView)
256 m_DocView = pdfium::MakeUnique<CXFA_FFDocView>(this);
tsepez084174a2016-04-25 12:37:27 -0700257
Dan Sinclair3d060222017-03-22 15:29:20 -0400258 return m_DocView.get();
Dan Sinclair1770c022016-03-14 14:14:16 -0400259}
tsepez084174a2016-04-25 12:37:27 -0700260
dsinclairdf4bc592016-03-31 20:34:43 -0700261CXFA_FFDocView* CXFA_FFDoc::GetDocView(CXFA_LayoutProcessor* pLayout) {
Dan Sinclair3d060222017-03-22 15:29:20 -0400262 return m_DocView && m_DocView->GetXFALayout() == pLayout ? m_DocView.get()
263 : nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -0400264}
tsepez084174a2016-04-25 12:37:27 -0700265
Dan Sinclair1770c022016-03-14 14:14:16 -0400266CXFA_FFDocView* CXFA_FFDoc::GetDocView() {
Dan Sinclair3d060222017-03-22 15:29:20 -0400267 return m_DocView.get();
Dan Sinclair1770c022016-03-14 14:14:16 -0400268}
tsepez084174a2016-04-25 12:37:27 -0700269
tsepezd19e9122016-11-02 15:43:18 -0700270bool CXFA_FFDoc::OpenDoc(CPDF_Document* pPDFDoc) {
dsinclairfc2cdf82016-05-19 18:07:11 -0700271 if (!pPDFDoc)
tsepezd19e9122016-11-02 15:43:18 -0700272 return false;
dsinclairfc2cdf82016-05-19 18:07:11 -0700273
Lei Zhang01581062017-08-30 14:19:26 -0700274 const CPDF_Dictionary* pRoot = pPDFDoc->GetRoot();
dsinclairfc2cdf82016-05-19 18:07:11 -0700275 if (!pRoot)
tsepezd19e9122016-11-02 15:43:18 -0700276 return false;
dsinclairfc2cdf82016-05-19 18:07:11 -0700277
dsinclair38fd8442016-09-15 10:15:32 -0700278 CPDF_Dictionary* pAcroForm = pRoot->GetDictFor("AcroForm");
dsinclairfc2cdf82016-05-19 18:07:11 -0700279 if (!pAcroForm)
tsepezd19e9122016-11-02 15:43:18 -0700280 return false;
dsinclairfc2cdf82016-05-19 18:07:11 -0700281
dsinclair38fd8442016-09-15 10:15:32 -0700282 CPDF_Object* pElementXFA = pAcroForm->GetDirectObjectFor("XFA");
dsinclairfc2cdf82016-05-19 18:07:11 -0700283 if (!pElementXFA)
tsepezd19e9122016-11-02 15:43:18 -0700284 return false;
dsinclairfc2cdf82016-05-19 18:07:11 -0700285
Dan Sinclair62110c92018-04-12 13:40:49 +0000286 m_pPDFDoc = pPDFDoc;
287
288 m_pNotify = pdfium::MakeUnique<CXFA_FFNotify>(this);
289 m_pDocument = pdfium::MakeUnique<CXFA_Document>(m_pNotify.get());
290 if (!ParseDoc(pElementXFA))
tsepezd19e9122016-11-02 15:43:18 -0700291 return false;
tsepez74b8c6e2016-10-12 09:38:41 -0700292
Dan Sinclair62110c92018-04-12 13:40:49 +0000293 // At this point we've got an XFA document and we want to always return
294 // true to signify the load succeeded.
295
296 m_pPDFFontMgr = pdfium::MakeUnique<CFGAS_PDFFontMgr>(
297 GetPDFDoc(), GetApp()->GetFDEFontMgr());
298
299 m_FormType = FormType::kXFAForeground;
300 CXFA_Node* pConfig = ToNode(m_pDocument->GetXFAObject(XFA_HASHCODE_Config));
301 if (!pConfig)
302 return true;
303
304 CXFA_Acrobat* pAcrobat =
305 pConfig->GetFirstChildByClass<CXFA_Acrobat>(XFA_Element::Acrobat);
306 if (!pAcrobat)
307 return true;
308
309 CXFA_Acrobat7* pAcrobat7 =
310 pAcrobat->GetFirstChildByClass<CXFA_Acrobat7>(XFA_Element::Acrobat7);
311 if (!pAcrobat7)
312 return true;
313
314 CXFA_DynamicRender* pDynamicRender =
315 pAcrobat7->GetFirstChildByClass<CXFA_DynamicRender>(
316 XFA_Element::DynamicRender);
317 if (!pDynamicRender)
318 return true;
319
320 WideString wsType = pDynamicRender->JSObject()->GetContent(false);
321 if (wsType == L"required")
322 m_FormType = FormType::kXFAFull;
323
tsepezd19e9122016-11-02 15:43:18 -0700324 return true;
Dan Sinclair1770c022016-03-14 14:14:16 -0400325}
dsinclaira1b07722016-07-11 08:20:58 -0700326
Tom Sepezcc205132017-05-16 14:01:47 -0700327void CXFA_FFDoc::CloseDoc() {
328 if (m_DocView) {
Dan Sinclair3d060222017-03-22 15:29:20 -0400329 m_DocView->RunDocClose();
Tom Sepezcc205132017-05-16 14:01:47 -0700330 m_DocView.reset();
331 }
Dan Sinclair0cad1162018-04-12 13:23:08 +0000332 if (m_pDocument) {
333 m_pDocument->ReleaseXMLNodesIfNeeded();
334 m_pDocument->ClearLayoutData();
335 }
tsepez084174a2016-04-25 12:37:27 -0700336
Dan Sinclair0cad1162018-04-12 13:23:08 +0000337 m_pDocument.reset();
338 m_pXMLRoot.reset();
Tom Sepezcc205132017-05-16 14:01:47 -0700339 m_pNotify.reset();
Dan Sinclaira44a4802017-09-21 10:45:18 -0400340 m_pPDFFontMgr.reset();
tsepez084174a2016-04-25 12:37:27 -0700341 m_HashToDibDpiMap.clear();
dsinclair20855382016-10-31 07:29:34 -0700342 m_pApp->ClearEventTargets();
Dan Sinclair1770c022016-03-14 14:14:16 -0400343}
Dan Sinclaircdba7472017-03-23 09:17:10 -0400344
Dan Sinclair0b950422017-09-21 15:49:49 -0400345RetainPtr<CFX_DIBitmap> CXFA_FFDoc::GetPDFNamedImage(
Ryan Harrison275e2602017-09-18 14:23:18 -0400346 const WideStringView& wsName,
Tom Sepezf0799fe2017-03-28 09:31:32 -0700347 int32_t& iImageXDpi,
348 int32_t& iImageYDpi) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400349 if (!m_pPDFDoc)
350 return nullptr;
351
tsepezb6853cf2016-04-25 11:23:43 -0700352 uint32_t dwHash = FX_HashCode_GetW(wsName, false);
tsepez084174a2016-04-25 12:37:27 -0700353 auto it = m_HashToDibDpiMap.find(dwHash);
354 if (it != m_HashToDibDpiMap.end()) {
355 iImageXDpi = it->second.iImageXDpi;
356 iImageYDpi = it->second.iImageYDpi;
Tom Sepezf0799fe2017-03-28 09:31:32 -0700357 return it->second.pDibSource.As<CFX_DIBitmap>();
Dan Sinclair1770c022016-03-14 14:14:16 -0400358 }
359
Lei Zhang01581062017-08-30 14:19:26 -0700360 const CPDF_Dictionary* pRoot = m_pPDFDoc->GetRoot();
Dan Sinclair1770c022016-03-14 14:14:16 -0400361 if (!pRoot)
362 return nullptr;
363
dsinclair38fd8442016-09-15 10:15:32 -0700364 CPDF_Dictionary* pNames = pRoot->GetDictFor("Names");
Dan Sinclair1770c022016-03-14 14:14:16 -0400365 if (!pNames)
366 return nullptr;
367
dsinclair38fd8442016-09-15 10:15:32 -0700368 CPDF_Dictionary* pXFAImages = pNames->GetDictFor("XFAImages");
Dan Sinclair1770c022016-03-14 14:14:16 -0400369 if (!pXFAImages)
370 return nullptr;
371
372 CPDF_NameTree nametree(pXFAImages);
Ryan Harrison275e2602017-09-18 14:23:18 -0400373 CPDF_Object* pObject = nametree.LookupValue(WideString(wsName));
Dan Sinclair1770c022016-03-14 14:14:16 -0400374 if (!pObject) {
Wei Lie1aebd42016-04-11 10:02:09 -0700375 for (size_t i = 0; i < nametree.GetCount(); i++) {
Ryan Harrison275e2602017-09-18 14:23:18 -0400376 WideString wsTemp;
Jane Liu67ccef72017-07-19 13:10:50 -0400377 CPDF_Object* pTempObject = nametree.LookupValueAndName(i, &wsTemp);
378 if (wsTemp == wsName) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400379 pObject = pTempObject;
380 break;
381 }
382 }
383 }
384
tsepez084174a2016-04-25 12:37:27 -0700385 CPDF_Stream* pStream = ToStream(pObject);
386 if (!pStream)
Dan Sinclair1770c022016-03-14 14:14:16 -0400387 return nullptr;
388
Tom Sepezafd0d1f2017-04-04 14:37:18 -0700389 auto pAcc = pdfium::MakeRetain<CPDF_StreamAcc>(pStream);
Lei Zhang07401ba2017-12-11 22:12:08 +0000390 pAcc->LoadAllDataFiltered();
tsepez084174a2016-04-25 12:37:27 -0700391
Dan Sinclair0b950422017-09-21 15:49:49 -0400392 RetainPtr<IFX_SeekableStream> pImageFileRead =
Dan Sinclair283a0432017-04-20 14:11:21 -0400393 pdfium::MakeRetain<CFX_MemoryStream>(
394 const_cast<uint8_t*>(pAcc->GetData()), pAcc->GetSize(), false);
tsepez084174a2016-04-25 12:37:27 -0700395
Dan Sinclair0b950422017-09-21 15:49:49 -0400396 RetainPtr<CFX_DIBitmap> pDibSource = XFA_LoadImageFromBuffer(
tsepez084174a2016-04-25 12:37:27 -0700397 pImageFileRead, FXCODEC_IMAGE_UNKNOWN, iImageXDpi, iImageYDpi);
398 m_HashToDibDpiMap[dwHash] = {pDibSource, iImageXDpi, iImageYDpi};
tsepez084174a2016-04-25 12:37:27 -0700399 return pDibSource;
Dan Sinclair1770c022016-03-14 14:14:16 -0400400}
401
Dan Sinclairf96dfed2017-11-08 19:57:00 +0000402bool CXFA_FFDoc::SavePackage(CXFA_Node* pNode,
Dan Sinclaire1a41af2018-04-12 13:13:43 +0000403 const RetainPtr<IFX_SeekableStream>& pFile) {
404 ASSERT(pNode || GetXFADoc()->GetRoot());
dsinclairdf4bc592016-03-31 20:34:43 -0700405
Dan Sinclaire1a41af2018-04-12 13:13:43 +0000406 CXFA_DataExporter exporter;
407 return exporter.Export(pFile, pNode ? pNode : GetXFADoc()->GetRoot());
tsepez38579042016-05-16 17:05:38 -0700408}
409
Dan Sinclair0b950422017-09-21 15:49:49 -0400410bool CXFA_FFDoc::ImportData(const RetainPtr<IFX_SeekableStream>& pStream,
Dan Sinclair4fcdf052017-04-18 11:55:27 -0400411 bool bXDP) {
Dan Sinclair0cad1162018-04-12 13:23:08 +0000412 auto importer = pdfium::MakeUnique<CXFA_DataImporter>(m_pDocument.get());
dsinclairdf4bc592016-03-31 20:34:43 -0700413 return importer->ImportData(pStream);
Dan Sinclair1770c022016-03-14 14:14:16 -0400414}