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/src/foxitlib.h"
8#include "xfa/src/fxfa/src/common/xfa_utils.h"
9#include "xfa/src/fxfa/src/common/xfa_object.h"
10#include "xfa/src/fxfa/src/common/xfa_document.h"
11#include "xfa/src/fxfa/src/common/xfa_parser.h"
12#include "xfa/src/fxfa/src/common/xfa_script.h"
13#include "xfa/src/fxfa/src/common/xfa_docdata.h"
14#include "xfa/src/fxfa/src/common/xfa_doclayout.h"
15#include "xfa/src/fxfa/src/common/xfa_localemgr.h"
16#include "xfa/src/fxfa/src/common/xfa_fm2jsapi.h"
17#define XFA_HASHCODE_Group 0xf7f75fcd
18class CXFA_TraverseStrategy_DDGroup {
19 public:
20  static inline CXFA_Node* GetFirstChild(CXFA_Node* pDDGroupNode) {
21    return pDDGroupNode->GetFirstChildByName(XFA_HASHCODE_Group);
22  }
23  static inline CXFA_Node* GetNextSibling(CXFA_Node* pDDGroupNode) {
24    return pDDGroupNode->GetNextSameNameSibling(XFA_HASHCODE_Group);
25  }
26  static inline CXFA_Node* GetParent(CXFA_Node* pDDGroupNode) {
27    return pDDGroupNode->GetNodeItem(XFA_NODEITEM_Parent);
28  }
29};
30void XFA_DataDescription_UpdateDataRelation(CXFA_Node* pDataNode,
31                                            CXFA_Node* pDataDescriptionNode) {
32  FXSYS_assert(pDataDescriptionNode);
33  for (CXFA_Node* pDataChild = pDataNode->GetNodeItem(XFA_NODEITEM_FirstChild);
34       pDataChild;
35       pDataChild = pDataChild->GetNodeItem(XFA_NODEITEM_NextSibling)) {
36    FX_DWORD dwNameHash = pDataChild->GetNameHash();
37    XFA_ELEMENT eType = pDataChild->GetClassID();
38    if (!dwNameHash) {
39      continue;
40    }
41    CXFA_NodeIteratorTemplate<CXFA_Node, CXFA_TraverseStrategy_DDGroup>
42        sIterator(pDataDescriptionNode);
43    for (CXFA_Node* pDDGroupNode = sIterator.GetCurrent(); pDDGroupNode;
44         pDDGroupNode = sIterator.MoveToNext()) {
45      if (pDDGroupNode != pDataDescriptionNode) {
46        if (pDDGroupNode->GetClassID() != XFA_ELEMENT_DataGroup) {
47          continue;
48        }
49        CFX_WideString wsNamespace;
50        if (!pDDGroupNode->TryNamespace(wsNamespace) ||
51            wsNamespace != FX_WSTRC(L"http://ns.adobe.com/data-description/")) {
52          continue;
53        }
54      }
55      CXFA_Node* pDDNode = pDDGroupNode->GetFirstChildByName(dwNameHash);
56      if (!pDDNode) {
57        continue;
58      }
59      if (pDDNode->GetClassID() != eType) {
60        break;
61      }
62      pDataChild->SetDataDescriptionNode(pDDNode);
63      XFA_DataDescription_UpdateDataRelation(pDataChild, pDDNode);
64      break;
65    }
66  }
67}
68CXFA_Node* XFA_DataDescription_MaybeCreateDataNode(
69    CXFA_Document* pDocument,
70    CXFA_Node* pDataParent,
71    XFA_ELEMENT eNodeType,
72    const CFX_WideStringC& wsName) {
73  if (!pDataParent) {
74    return NULL;
75  }
76  CXFA_Node* pParentDDNode = pDataParent->GetDataDescriptionNode();
77  if (!pParentDDNode) {
78    CXFA_Node* pDataNode =
79        pDocument->CreateNode(XFA_XDPPACKET_Datasets, eNodeType);
80    FXSYS_assert(pDataNode);
81    pDataNode->SetCData(XFA_ATTRIBUTE_Name, wsName);
82    pDataNode->CreateXMLMappingNode();
83    pDataParent->InsertChild(pDataNode);
84    pDataNode->SetFlag(XFA_NODEFLAG_Initialized, TRUE, FALSE);
85    return pDataNode;
86  } else {
87    CXFA_NodeIteratorTemplate<CXFA_Node, CXFA_TraverseStrategy_DDGroup>
88        sIterator(pParentDDNode);
89    for (CXFA_Node* pDDGroupNode = sIterator.GetCurrent(); pDDGroupNode;
90         pDDGroupNode = sIterator.MoveToNext()) {
91      if (pDDGroupNode != pParentDDNode) {
92        if (pDDGroupNode->GetClassID() != XFA_ELEMENT_DataGroup) {
93          continue;
94        }
95        CFX_WideString wsNamespace;
96        if (!pDDGroupNode->TryNamespace(wsNamespace) ||
97            wsNamespace != FX_WSTRC(L"http://ns.adobe.com/data-description/")) {
98          continue;
99        }
100      }
101      CXFA_Node* pDDNode = pDDGroupNode->GetFirstChildByName(wsName);
102      if (!pDDNode) {
103        continue;
104      }
105      if (pDDNode->GetClassID() != eNodeType) {
106        break;
107      }
108      CXFA_Node* pDataNode =
109          pDocument->CreateNode(XFA_XDPPACKET_Datasets, eNodeType);
110      FXSYS_assert(pDataNode);
111      pDataNode->SetCData(XFA_ATTRIBUTE_Name, wsName);
112      pDataNode->CreateXMLMappingNode();
113      if (eNodeType == XFA_ELEMENT_DataValue &&
114          pDDNode->GetEnum(XFA_ATTRIBUTE_Contains) ==
115              XFA_ATTRIBUTEENUM_MetaData) {
116        pDataNode->SetEnum(XFA_ATTRIBUTE_Contains, XFA_ATTRIBUTEENUM_MetaData);
117      }
118      pDataParent->InsertChild(pDataNode);
119      pDataNode->SetDataDescriptionNode(pDDNode);
120      pDataNode->SetFlag(XFA_NODEFLAG_Initialized, TRUE, FALSE);
121      return pDataNode;
122    }
123    return NULL;
124  }
125}
126