blob: 0a4e597c93c863889f794fccb9025311f7bcac33 [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
dsinclaira52ab742016-09-29 13:59:29 -07007#include "core/fxcrt/fx_ext.h"
dsinclairdf4bc592016-03-31 20:34:43 -07008#include "xfa/fxfa/app/xfa_ffnotify.h"
dsinclairc1515ef2016-07-20 06:16:06 -07009#include "xfa/fxfa/parser/cscript_datawindow.h"
10#include "xfa/fxfa/parser/cscript_eventpseudomodel.h"
11#include "xfa/fxfa/parser/cscript_hostpseudomodel.h"
12#include "xfa/fxfa/parser/cscript_layoutpseudomodel.h"
13#include "xfa/fxfa/parser/cscript_logpseudomodel.h"
14#include "xfa/fxfa/parser/cscript_signaturepseudomodel.h"
dsinclair16280242016-07-21 12:03:47 -070015#include "xfa/fxfa/parser/cxfa_document.h"
dsinclair34f86b02016-07-11 08:42:33 -070016#include "xfa/fxfa/parser/cxfa_document_parser.h"
dsinclair0b851ff2016-07-21 12:03:01 -070017#include "xfa/fxfa/parser/cxfa_layoutprocessor.h"
Dan Sinclairec1843d2017-03-28 16:04:41 -040018#include "xfa/fxfa/parser/cxfa_localemgr.h"
dsinclair31f87402016-07-20 06:34:45 -070019#include "xfa/fxfa/parser/cxfa_scriptcontext.h"
Dan Sinclair1770c022016-03-14 14:14:16 -040020#include "xfa/fxfa/parser/xfa_object.h"
dsinclair31f87402016-07-20 06:34:45 -070021#include "xfa/fxfa/parser/xfa_resolvenode_rs.h"
Dan Sinclair1770c022016-03-14 14:14:16 -040022#include "xfa/fxfa/parser/xfa_utils.h"
23
dsinclair16280242016-07-21 12:03:47 -070024namespace {
25
26void MergeNodeRecurse(CXFA_Document* pDocument,
27 CXFA_Node* pDestNodeParent,
28 CXFA_Node* pProtoNode) {
29 CXFA_Node* pExistingNode = nullptr;
30 for (CXFA_Node* pFormChild =
31 pDestNodeParent->GetNodeItem(XFA_NODEITEM_FirstChild);
32 pFormChild;
33 pFormChild = pFormChild->GetNodeItem(XFA_NODEITEM_NextSibling)) {
34 if (pFormChild->GetElementType() == pProtoNode->GetElementType() &&
35 pFormChild->GetNameHash() == pProtoNode->GetNameHash() &&
36 pFormChild->IsUnusedNode()) {
37 pFormChild->ClearFlag(XFA_NodeFlag_UnusedNode);
38 pExistingNode = pFormChild;
39 break;
40 }
41 }
42
43 if (pExistingNode) {
44 pExistingNode->SetTemplateNode(pProtoNode);
45 for (CXFA_Node* pTemplateChild =
46 pProtoNode->GetNodeItem(XFA_NODEITEM_FirstChild);
47 pTemplateChild; pTemplateChild = pTemplateChild->GetNodeItem(
48 XFA_NODEITEM_NextSibling)) {
49 MergeNodeRecurse(pDocument, pExistingNode, pTemplateChild);
50 }
51 return;
52 }
tsepezd19e9122016-11-02 15:43:18 -070053 CXFA_Node* pNewNode = pProtoNode->Clone(true);
dsinclair16280242016-07-21 12:03:47 -070054 pNewNode->SetTemplateNode(pProtoNode);
55 pDestNodeParent->InsertChild(pNewNode, nullptr);
56}
57
58void MergeNode(CXFA_Document* pDocument,
59 CXFA_Node* pDestNode,
60 CXFA_Node* pProtoNode) {
61 {
62 CXFA_NodeIterator sIterator(pDestNode);
63 for (CXFA_Node* pNode = sIterator.GetCurrent(); pNode;
64 pNode = sIterator.MoveToNext()) {
65 pNode->SetFlag(XFA_NodeFlag_UnusedNode, true);
66 }
67 }
68 pDestNode->SetTemplateNode(pProtoNode);
69 for (CXFA_Node* pTemplateChild =
70 pProtoNode->GetNodeItem(XFA_NODEITEM_FirstChild);
71 pTemplateChild;
72 pTemplateChild = pTemplateChild->GetNodeItem(XFA_NODEITEM_NextSibling)) {
73 MergeNodeRecurse(pDocument, pDestNode, pTemplateChild);
74 }
75 {
76 CXFA_NodeIterator sIterator(pDestNode);
77 for (CXFA_Node* pNode = sIterator.GetCurrent(); pNode;
78 pNode = sIterator.MoveToNext()) {
79 pNode->ClearFlag(XFA_NodeFlag_UnusedNode);
80 }
81 }
82}
83
84} // namespace
85
dsinclairdf4bc592016-03-31 20:34:43 -070086CXFA_Document::CXFA_Document(CXFA_DocumentParser* pParser)
Dan Sinclair1770c022016-03-14 14:14:16 -040087 : m_pParser(pParser),
Dan Sinclair1770c022016-03-14 14:14:16 -040088 m_pRootNode(nullptr),
Dan Sinclair1770c022016-03-14 14:14:16 -040089 m_eCurVersionMode(XFA_VERSION_DEFAULT),
90 m_dwDocFlags(0) {
91 ASSERT(m_pParser);
92}
dsinclair16280242016-07-21 12:03:47 -070093
Dan Sinclair1770c022016-03-14 14:14:16 -040094CXFA_Document::~CXFA_Document() {
95 delete m_pRootNode;
96 PurgeNodes();
97}
thestig495bda12016-04-28 17:29:19 -070098
Dan Sinclair10def512017-02-06 15:31:38 -050099CXFA_LayoutProcessor* CXFA_Document::GetLayoutProcessor() {
100 if (!m_pLayoutProcessor)
Tom Sepez742fa8c2017-03-21 17:08:48 -0700101 m_pLayoutProcessor = pdfium::MakeUnique<CXFA_LayoutProcessor>(this);
102 return m_pLayoutProcessor.get();
Dan Sinclair10def512017-02-06 15:31:38 -0500103}
104
105CXFA_LayoutProcessor* CXFA_Document::GetDocLayout() {
106 return GetLayoutProcessor();
107}
108
Dan Sinclair1770c022016-03-14 14:14:16 -0400109void CXFA_Document::ClearLayoutData() {
Tom Sepez742fa8c2017-03-21 17:08:48 -0700110 m_pLayoutProcessor.reset();
111 m_pScriptContext.reset();
112 m_pLocalMgr.reset();
113 m_pScriptDataWindow.reset();
114 m_pScriptEvent.reset();
115 m_pScriptHost.reset();
116 m_pScriptLog.reset();
117 m_pScriptLayout.reset();
118 m_pScriptSignature.reset();
Dan Sinclair1770c022016-03-14 14:14:16 -0400119}
thestig495bda12016-04-28 17:29:19 -0700120
Dan Sinclair1770c022016-03-14 14:14:16 -0400121void CXFA_Document::SetRoot(CXFA_Node* pNewRoot) {
dsinclair16280242016-07-21 12:03:47 -0700122 if (m_pRootNode)
Dan Sinclair1770c022016-03-14 14:14:16 -0400123 AddPurgeNode(m_pRootNode);
dsinclair16280242016-07-21 12:03:47 -0700124
Dan Sinclair1770c022016-03-14 14:14:16 -0400125 m_pRootNode = pNewRoot;
126 RemovePurgeNode(pNewRoot);
127}
dsinclaircbfef572016-05-18 13:16:12 -0700128
dsinclaira1b07722016-07-11 08:20:58 -0700129CFDE_XMLDoc* CXFA_Document::GetXMLDoc() const {
130 return m_pParser->GetXMLDoc();
131}
132
dsinclairdf4bc592016-03-31 20:34:43 -0700133CXFA_FFNotify* CXFA_Document::GetNotify() const {
Dan Sinclair1770c022016-03-14 14:14:16 -0400134 return m_pParser->GetNotify();
135}
dsinclaircbfef572016-05-18 13:16:12 -0700136
137CXFA_Object* CXFA_Document::GetXFAObject(XFA_HashCode dwNodeNameHash) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400138 switch (dwNodeNameHash) {
139 case XFA_HASHCODE_Data: {
140 CXFA_Node* pDatasetsNode = ToNode(GetXFAObject(XFA_HASHCODE_Datasets));
dsinclair16280242016-07-21 12:03:47 -0700141 if (!pDatasetsNode)
dsinclair85d1f2c2016-06-23 12:40:16 -0700142 return nullptr;
dsinclair16280242016-07-21 12:03:47 -0700143
Dan Sinclair1770c022016-03-14 14:14:16 -0400144 for (CXFA_Node* pDatasetsChild =
dsinclair56a8b192016-06-21 14:15:25 -0700145 pDatasetsNode->GetFirstChildByClass(XFA_Element::DataGroup);
Dan Sinclair1770c022016-03-14 14:14:16 -0400146 pDatasetsChild;
dsinclair56a8b192016-06-21 14:15:25 -0700147 pDatasetsChild = pDatasetsChild->GetNextSameClassSibling(
148 XFA_Element::DataGroup)) {
dsinclair16280242016-07-21 12:03:47 -0700149 if (pDatasetsChild->GetNameHash() != XFA_HASHCODE_Data)
Dan Sinclair1770c022016-03-14 14:14:16 -0400150 continue;
dsinclair16280242016-07-21 12:03:47 -0700151
Dan Sinclair1770c022016-03-14 14:14:16 -0400152 CFX_WideString wsNamespaceURI;
dsinclair16280242016-07-21 12:03:47 -0700153 if (!pDatasetsChild->TryNamespace(wsNamespaceURI))
Dan Sinclair1770c022016-03-14 14:14:16 -0400154 continue;
dsinclair16280242016-07-21 12:03:47 -0700155
Dan Sinclair1770c022016-03-14 14:14:16 -0400156 CFX_WideString wsDatasetsURI;
dsinclair16280242016-07-21 12:03:47 -0700157 if (!pDatasetsNode->TryNamespace(wsDatasetsURI))
Dan Sinclair1770c022016-03-14 14:14:16 -0400158 continue;
dsinclair16280242016-07-21 12:03:47 -0700159 if (wsNamespaceURI == wsDatasetsURI)
Dan Sinclair1770c022016-03-14 14:14:16 -0400160 return pDatasetsChild;
Dan Sinclair1770c022016-03-14 14:14:16 -0400161 }
dsinclair85d1f2c2016-06-23 12:40:16 -0700162 return nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -0400163 }
Dan Sinclair1770c022016-03-14 14:14:16 -0400164 case XFA_HASHCODE_Record: {
165 CXFA_Node* pData = ToNode(GetXFAObject(XFA_HASHCODE_Data));
dsinclair85d1f2c2016-06-23 12:40:16 -0700166 return pData ? pData->GetFirstChildByClass(XFA_Element::DataGroup)
167 : nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -0400168 }
169 case XFA_HASHCODE_DataWindow: {
dsinclair85d1f2c2016-06-23 12:40:16 -0700170 if (!m_pScriptDataWindow)
Tom Sepez742fa8c2017-03-21 17:08:48 -0700171 m_pScriptDataWindow = pdfium::MakeUnique<CScript_DataWindow>(this);
172 return m_pScriptDataWindow.get();
Dan Sinclair1770c022016-03-14 14:14:16 -0400173 }
174 case XFA_HASHCODE_Event: {
dsinclair85d1f2c2016-06-23 12:40:16 -0700175 if (!m_pScriptEvent)
Tom Sepez742fa8c2017-03-21 17:08:48 -0700176 m_pScriptEvent = pdfium::MakeUnique<CScript_EventPseudoModel>(this);
177 return m_pScriptEvent.get();
Dan Sinclair1770c022016-03-14 14:14:16 -0400178 }
179 case XFA_HASHCODE_Host: {
dsinclair85d1f2c2016-06-23 12:40:16 -0700180 if (!m_pScriptHost)
Tom Sepez742fa8c2017-03-21 17:08:48 -0700181 m_pScriptHost = pdfium::MakeUnique<CScript_HostPseudoModel>(this);
182 return m_pScriptHost.get();
Dan Sinclair1770c022016-03-14 14:14:16 -0400183 }
184 case XFA_HASHCODE_Log: {
dsinclair85d1f2c2016-06-23 12:40:16 -0700185 if (!m_pScriptLog)
Tom Sepez742fa8c2017-03-21 17:08:48 -0700186 m_pScriptLog = pdfium::MakeUnique<CScript_LogPseudoModel>(this);
187 return m_pScriptLog.get();
Dan Sinclair1770c022016-03-14 14:14:16 -0400188 }
189 case XFA_HASHCODE_Signature: {
dsinclair85d1f2c2016-06-23 12:40:16 -0700190 if (!m_pScriptSignature)
Tom Sepez742fa8c2017-03-21 17:08:48 -0700191 m_pScriptSignature =
192 pdfium::MakeUnique<CScript_SignaturePseudoModel>(this);
193 return m_pScriptSignature.get();
Dan Sinclair1770c022016-03-14 14:14:16 -0400194 }
195 case XFA_HASHCODE_Layout: {
dsinclair85d1f2c2016-06-23 12:40:16 -0700196 if (!m_pScriptLayout)
Tom Sepez742fa8c2017-03-21 17:08:48 -0700197 m_pScriptLayout = pdfium::MakeUnique<CScript_LayoutPseudoModel>(this);
198 return m_pScriptLayout.get();
Dan Sinclair1770c022016-03-14 14:14:16 -0400199 }
200 default:
201 return m_pRootNode->GetFirstChildByName(dwNodeNameHash);
202 }
203}
dsinclair16280242016-07-21 12:03:47 -0700204
dsinclair56a8b192016-06-21 14:15:25 -0700205CXFA_Node* CXFA_Document::CreateNode(uint32_t dwPacket, XFA_Element eElement) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400206 return CreateNode(XFA_GetPacketByID(dwPacket), eElement);
207}
tsepezaadedf92016-05-12 10:08:06 -0700208
Dan Sinclair1770c022016-03-14 14:14:16 -0400209CXFA_Node* CXFA_Document::CreateNode(const XFA_PACKETINFO* pPacket,
dsinclair56a8b192016-06-21 14:15:25 -0700210 XFA_Element eElement) {
tsepezaadedf92016-05-12 10:08:06 -0700211 if (!pPacket)
212 return nullptr;
213
Dan Sinclair1770c022016-03-14 14:14:16 -0400214 const XFA_ELEMENTINFO* pElement = XFA_GetElementByID(eElement);
215 if (pElement && (pElement->dwPackets & pPacket->eName)) {
dsinclairc1df5d42016-07-18 06:36:51 -0700216 CXFA_Node* pNode =
217 new CXFA_Node(this, pPacket->eName, pElement->eObjectType,
218 pElement->eName, pElement->pName);
tsepezaadedf92016-05-12 10:08:06 -0700219 AddPurgeNode(pNode);
Dan Sinclair1770c022016-03-14 14:14:16 -0400220 return pNode;
221 }
tsepezaadedf92016-05-12 10:08:06 -0700222
223 return nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -0400224}
tsepezaadedf92016-05-12 10:08:06 -0700225
Dan Sinclair1770c022016-03-14 14:14:16 -0400226void CXFA_Document::AddPurgeNode(CXFA_Node* pNode) {
tsepezaadedf92016-05-12 10:08:06 -0700227 m_PurgeNodes.insert(pNode);
Dan Sinclair1770c022016-03-14 14:14:16 -0400228}
tsepezaadedf92016-05-12 10:08:06 -0700229
tsepezd19e9122016-11-02 15:43:18 -0700230bool CXFA_Document::RemovePurgeNode(CXFA_Node* pNode) {
tsepezaadedf92016-05-12 10:08:06 -0700231 return !!m_PurgeNodes.erase(pNode);
Dan Sinclair1770c022016-03-14 14:14:16 -0400232}
tsepezaadedf92016-05-12 10:08:06 -0700233
Dan Sinclair1770c022016-03-14 14:14:16 -0400234void CXFA_Document::PurgeNodes() {
tsepezaadedf92016-05-12 10:08:06 -0700235 for (CXFA_Node* pNode : m_PurgeNodes)
Dan Sinclair1770c022016-03-14 14:14:16 -0400236 delete pNode;
tsepezaadedf92016-05-12 10:08:06 -0700237
238 m_PurgeNodes.clear();
Dan Sinclair1770c022016-03-14 14:14:16 -0400239}
tsepezaadedf92016-05-12 10:08:06 -0700240
tsepezd19e9122016-11-02 15:43:18 -0700241void CXFA_Document::SetFlag(uint32_t dwFlag, bool bOn) {
dsinclair16280242016-07-21 12:03:47 -0700242 if (bOn)
Dan Sinclair1770c022016-03-14 14:14:16 -0400243 m_dwDocFlags |= dwFlag;
dsinclair16280242016-07-21 12:03:47 -0700244 else
Dan Sinclair1770c022016-03-14 14:14:16 -0400245 m_dwDocFlags &= ~dwFlag;
Dan Sinclair1770c022016-03-14 14:14:16 -0400246}
dsinclair16280242016-07-21 12:03:47 -0700247
tsepezd19e9122016-11-02 15:43:18 -0700248bool CXFA_Document::IsInteractive() {
dsinclair16280242016-07-21 12:03:47 -0700249 if (m_dwDocFlags & XFA_DOCFLAG_HasInteractive)
tsepez7d89e722016-05-04 13:38:11 -0700250 return !!(m_dwDocFlags & XFA_DOCFLAG_Interactive);
dsinclair16280242016-07-21 12:03:47 -0700251
Dan Sinclair1770c022016-03-14 14:14:16 -0400252 CXFA_Node* pConfig = ToNode(GetXFAObject(XFA_HASHCODE_Config));
dsinclair16280242016-07-21 12:03:47 -0700253 if (!pConfig)
tsepezd19e9122016-11-02 15:43:18 -0700254 return false;
dsinclair16280242016-07-21 12:03:47 -0700255
Dan Sinclair1770c022016-03-14 14:14:16 -0400256 CFX_WideString wsInteractive;
dsinclair56a8b192016-06-21 14:15:25 -0700257 CXFA_Node* pPresent = pConfig->GetFirstChildByClass(XFA_Element::Present);
dsinclair16280242016-07-21 12:03:47 -0700258 if (!pPresent)
tsepezd19e9122016-11-02 15:43:18 -0700259 return false;
dsinclair16280242016-07-21 12:03:47 -0700260
dsinclair56a8b192016-06-21 14:15:25 -0700261 CXFA_Node* pPDF = pPresent->GetFirstChildByClass(XFA_Element::Pdf);
dsinclair16280242016-07-21 12:03:47 -0700262 if (!pPDF)
tsepezd19e9122016-11-02 15:43:18 -0700263 return false;
dsinclair16280242016-07-21 12:03:47 -0700264
dsinclairb94d7c92016-09-21 12:07:00 -0700265 CXFA_Node* pFormFiller = pPDF->GetChild(0, XFA_Element::Interactive);
266 if (pFormFiller) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400267 m_dwDocFlags |= XFA_DOCFLAG_HasInteractive;
dan sinclair65c7c232017-02-02 14:05:30 -0800268 if (pFormFiller->TryContent(wsInteractive) && wsInteractive == L"1") {
Dan Sinclair1770c022016-03-14 14:14:16 -0400269 m_dwDocFlags |= XFA_DOCFLAG_Interactive;
tsepezd19e9122016-11-02 15:43:18 -0700270 return true;
Dan Sinclair1770c022016-03-14 14:14:16 -0400271 }
272 }
tsepezd19e9122016-11-02 15:43:18 -0700273 return false;
Dan Sinclair1770c022016-03-14 14:14:16 -0400274}
dsinclair16280242016-07-21 12:03:47 -0700275
Dan Sinclair1770c022016-03-14 14:14:16 -0400276CXFA_LocaleMgr* CXFA_Document::GetLocalMgr() {
277 if (!m_pLocalMgr) {
Tom Sepez742fa8c2017-03-21 17:08:48 -0700278 m_pLocalMgr = pdfium::MakeUnique<CXFA_LocaleMgr>(
279 ToNode(GetXFAObject(XFA_HASHCODE_LocaleSet)),
280 GetNotify()->GetAppProvider()->GetLanguage());
Dan Sinclair1770c022016-03-14 14:14:16 -0400281 }
Tom Sepez742fa8c2017-03-21 17:08:48 -0700282 return m_pLocalMgr.get();
Dan Sinclair1770c022016-03-14 14:14:16 -0400283}
dsinclair16280242016-07-21 12:03:47 -0700284
dsinclairec3da5b2016-05-25 16:42:05 -0700285CXFA_ScriptContext* CXFA_Document::InitScriptContext(v8::Isolate* pIsolate) {
Tom Sepez742fa8c2017-03-21 17:08:48 -0700286 CXFA_ScriptContext* result = GetScriptContext();
287 result->Initialize(pIsolate);
288 return result;
Dan Sinclair1770c022016-03-14 14:14:16 -0400289}
dsinclair16280242016-07-21 12:03:47 -0700290
dsinclairdf4bc592016-03-31 20:34:43 -0700291CXFA_ScriptContext* CXFA_Document::GetScriptContext() {
292 if (!m_pScriptContext)
Tom Sepez742fa8c2017-03-21 17:08:48 -0700293 m_pScriptContext = pdfium::MakeUnique<CXFA_ScriptContext>(this);
294 return m_pScriptContext.get();
Dan Sinclair1770c022016-03-14 14:14:16 -0400295}
dsinclair16280242016-07-21 12:03:47 -0700296
Dan Sinclair1770c022016-03-14 14:14:16 -0400297XFA_VERSION CXFA_Document::RecognizeXFAVersionNumber(
298 CFX_WideString& wsTemplateNS) {
299 CFX_WideStringC wsTemplateURIPrefix =
300 XFA_GetPacketByIndex(XFA_PACKET_Template)->pURI;
301 FX_STRSIZE nPrefixLength = wsTemplateURIPrefix.GetLength();
tsepezbd9748d2016-04-13 21:40:19 -0700302 if (CFX_WideStringC(wsTemplateNS.c_str(), wsTemplateNS.GetLength()) !=
Dan Sinclair1770c022016-03-14 14:14:16 -0400303 wsTemplateURIPrefix) {
304 return XFA_VERSION_UNKNOWN;
305 }
306 FX_STRSIZE nDotPos = wsTemplateNS.Find('.', nPrefixLength);
dsinclair16280242016-07-21 12:03:47 -0700307 if (nDotPos == (FX_STRSIZE)-1)
Dan Sinclair1770c022016-03-14 14:14:16 -0400308 return XFA_VERSION_UNKNOWN;
dsinclair16280242016-07-21 12:03:47 -0700309
tsepezbd9748d2016-04-13 21:40:19 -0700310 int8_t iMajor = FXSYS_wtoi(
311 wsTemplateNS.Mid(nPrefixLength, nDotPos - nPrefixLength).c_str());
Dan Sinclair1770c022016-03-14 14:14:16 -0400312 int8_t iMinor = FXSYS_wtoi(
tsepezbd9748d2016-04-13 21:40:19 -0700313 wsTemplateNS.Mid(nDotPos + 1, wsTemplateNS.GetLength() - nDotPos - 2)
314 .c_str());
Dan Sinclair1770c022016-03-14 14:14:16 -0400315 XFA_VERSION eVersion = (XFA_VERSION)((int32_t)iMajor * 100 + iMinor);
dsinclair16280242016-07-21 12:03:47 -0700316 if (eVersion < XFA_VERSION_MIN || eVersion > XFA_VERSION_MAX)
Dan Sinclair1770c022016-03-14 14:14:16 -0400317 return XFA_VERSION_UNKNOWN;
dsinclair16280242016-07-21 12:03:47 -0700318
Dan Sinclair1770c022016-03-14 14:14:16 -0400319 m_eCurVersionMode = eVersion;
320 return eVersion;
321}
dsinclair16280242016-07-21 12:03:47 -0700322
Dan Sinclair1770c022016-03-14 14:14:16 -0400323CXFA_Node* CXFA_Document::GetNodeByID(CXFA_Node* pRoot,
324 const CFX_WideStringC& wsID) {
dsinclair16280242016-07-21 12:03:47 -0700325 if (!pRoot || wsID.IsEmpty())
dsinclair85d1f2c2016-06-23 12:40:16 -0700326 return nullptr;
dsinclair16280242016-07-21 12:03:47 -0700327
Dan Sinclair1770c022016-03-14 14:14:16 -0400328 CXFA_NodeIterator sIterator(pRoot);
329 for (CXFA_Node* pNode = sIterator.GetCurrent(); pNode;
330 pNode = sIterator.MoveToNext()) {
331 CFX_WideStringC wsIDVal;
332 if (pNode->TryCData(XFA_ATTRIBUTE_Id, wsIDVal) && !wsIDVal.IsEmpty()) {
dsinclair16280242016-07-21 12:03:47 -0700333 if (wsIDVal == wsID)
Dan Sinclair1770c022016-03-14 14:14:16 -0400334 return pNode;
Dan Sinclair1770c022016-03-14 14:14:16 -0400335 }
336 }
dsinclair85d1f2c2016-06-23 12:40:16 -0700337 return nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -0400338}
dsinclair16280242016-07-21 12:03:47 -0700339
Dan Sinclair1770c022016-03-14 14:14:16 -0400340void CXFA_Document::DoProtoMerge() {
341 CXFA_Node* pTemplateRoot = ToNode(GetXFAObject(XFA_HASHCODE_Template));
dsinclair16280242016-07-21 12:03:47 -0700342 if (!pTemplateRoot)
Dan Sinclair1770c022016-03-14 14:14:16 -0400343 return;
dsinclair16280242016-07-21 12:03:47 -0700344
tsepez6bb3b892017-01-05 12:18:41 -0800345 std::map<uint32_t, CXFA_Node*> mIDMap;
Tom Sepezd4db58f2017-03-02 14:57:59 -0800346 std::unordered_set<CXFA_Node*> sUseNodes;
Dan Sinclair1770c022016-03-14 14:14:16 -0400347 CXFA_NodeIterator sIterator(pTemplateRoot);
348 for (CXFA_Node* pNode = sIterator.GetCurrent(); pNode;
349 pNode = sIterator.MoveToNext()) {
350 CFX_WideStringC wsIDVal;
351 if (pNode->TryCData(XFA_ATTRIBUTE_Id, wsIDVal) && !wsIDVal.IsEmpty()) {
tsepezb6853cf2016-04-25 11:23:43 -0700352 mIDMap[FX_HashCode_GetW(wsIDVal, false)] = pNode;
Dan Sinclair1770c022016-03-14 14:14:16 -0400353 }
354 CFX_WideStringC wsUseVal;
355 if (pNode->TryCData(XFA_ATTRIBUTE_Use, wsUseVal) && !wsUseVal.IsEmpty()) {
tsepezaadedf92016-05-12 10:08:06 -0700356 sUseNodes.insert(pNode);
Dan Sinclair1770c022016-03-14 14:14:16 -0400357 } else if (pNode->TryCData(XFA_ATTRIBUTE_Usehref, wsUseVal) &&
358 !wsUseVal.IsEmpty()) {
tsepezaadedf92016-05-12 10:08:06 -0700359 sUseNodes.insert(pNode);
Dan Sinclair1770c022016-03-14 14:14:16 -0400360 }
361 }
dsinclair16280242016-07-21 12:03:47 -0700362
tsepezaadedf92016-05-12 10:08:06 -0700363 for (CXFA_Node* pUseHrefNode : sUseNodes) {
Dan Sinclair1770c022016-03-14 14:14:16 -0400364 CFX_WideString wsUseVal;
365 CFX_WideStringC wsURI, wsID, wsSOM;
366 if (pUseHrefNode->TryCData(XFA_ATTRIBUTE_Usehref, wsUseVal) &&
367 !wsUseVal.IsEmpty()) {
368 FX_STRSIZE uSharpPos = wsUseVal.Find('#');
369 if (uSharpPos < 0) {
tsepez4d31d0c2016-04-19 14:11:59 -0700370 wsURI = wsUseVal.AsStringC();
Dan Sinclair1770c022016-03-14 14:14:16 -0400371 } else {
tsepezbd9748d2016-04-13 21:40:19 -0700372 wsURI = CFX_WideStringC(wsUseVal.c_str(), uSharpPos);
Dan Sinclair1770c022016-03-14 14:14:16 -0400373 FX_STRSIZE uLen = wsUseVal.GetLength();
374 if (uLen >= uSharpPos + 5 &&
dan sinclair65c7c232017-02-02 14:05:30 -0800375 CFX_WideStringC(wsUseVal.c_str() + uSharpPos, 5) == L"#som(" &&
Dan Sinclair1770c022016-03-14 14:14:16 -0400376 wsUseVal[uLen - 1] == ')') {
tsepezbd9748d2016-04-13 21:40:19 -0700377 wsSOM = CFX_WideStringC(wsUseVal.c_str() + uSharpPos + 5,
Dan Sinclair1770c022016-03-14 14:14:16 -0400378 uLen - 1 - uSharpPos - 5);
379 } else {
tsepezbd9748d2016-04-13 21:40:19 -0700380 wsID = CFX_WideStringC(wsUseVal.c_str() + uSharpPos + 1,
Dan Sinclair1770c022016-03-14 14:14:16 -0400381 uLen - uSharpPos - 1);
382 }
383 }
384 } else if (pUseHrefNode->TryCData(XFA_ATTRIBUTE_Use, wsUseVal) &&
385 !wsUseVal.IsEmpty()) {
dsinclair16280242016-07-21 12:03:47 -0700386 if (wsUseVal[0] == '#')
tsepezbd9748d2016-04-13 21:40:19 -0700387 wsID = CFX_WideStringC(wsUseVal.c_str() + 1, wsUseVal.GetLength() - 1);
dsinclair16280242016-07-21 12:03:47 -0700388 else
tsepezbd9748d2016-04-13 21:40:19 -0700389 wsSOM = CFX_WideStringC(wsUseVal.c_str(), wsUseVal.GetLength());
Dan Sinclair1770c022016-03-14 14:14:16 -0400390 }
dsinclair16280242016-07-21 12:03:47 -0700391
dan sinclair65c7c232017-02-02 14:05:30 -0800392 if (!wsURI.IsEmpty() && wsURI != L".")
Dan Sinclair1770c022016-03-14 14:14:16 -0400393 continue;
dsinclair16280242016-07-21 12:03:47 -0700394
dsinclair85d1f2c2016-06-23 12:40:16 -0700395 CXFA_Node* pProtoNode = nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -0400396 if (!wsSOM.IsEmpty()) {
tsepez736f28a2016-03-25 14:19:51 -0700397 uint32_t dwFlag = XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Attributes |
Dan Sinclair1770c022016-03-14 14:14:16 -0400398 XFA_RESOLVENODE_Properties | XFA_RESOLVENODE_Parent |
399 XFA_RESOLVENODE_Siblings;
400 XFA_RESOLVENODE_RS resoveNodeRS;
401 int32_t iRet = m_pScriptContext->ResolveObjects(pUseHrefNode, wsSOM,
402 resoveNodeRS, dwFlag);
Tom Sepezf8a94392017-03-14 12:13:22 -0700403 if (iRet > 0 && resoveNodeRS.objects.front()->IsNode())
404 pProtoNode = resoveNodeRS.objects.front()->AsNode();
Dan Sinclair1770c022016-03-14 14:14:16 -0400405 } else if (!wsID.IsEmpty()) {
tsepez6bb3b892017-01-05 12:18:41 -0800406 auto it = mIDMap.find(FX_HashCode_GetW(wsID, false));
407 if (it == mIDMap.end())
Dan Sinclair1770c022016-03-14 14:14:16 -0400408 continue;
tsepez6bb3b892017-01-05 12:18:41 -0800409 pProtoNode = it->second;
Dan Sinclair1770c022016-03-14 14:14:16 -0400410 }
dsinclair16280242016-07-21 12:03:47 -0700411 if (!pProtoNode)
Dan Sinclair1770c022016-03-14 14:14:16 -0400412 continue;
dsinclair16280242016-07-21 12:03:47 -0700413
414 MergeNode(this, pUseHrefNode, pProtoNode);
Dan Sinclair1770c022016-03-14 14:14:16 -0400415 }
416}