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#ifndef XFA_FXFA_PARSER_XFA_UTILS_H_
8#define XFA_FXFA_PARSER_XFA_UTILS_H_
9
10#include "xfa/fde/xml/fde_xml.h"
11#include "xfa/fgas/crt/fgas_stream.h"
12#include "xfa/fgas/crt/fgas_utils.h"
13#include "xfa/fxfa/fxfa_basic.h"
14
15class CFDE_XMLElement;
16class CFDE_XMLNode;
17class CXFA_LocaleValue;
18class CXFA_Node;
19class CXFA_WidgetData;
20
21bool XFA_FDEExtension_ResolveNamespaceQualifier(
22    CFDE_XMLElement* pNode,
23    const CFX_WideStringC& wsQualifier,
24    CFX_WideString& wsNamespaceURI);
25
26template <class NodeType, class TraverseStrategy>
27class CXFA_NodeIteratorTemplate {
28 public:
29  explicit CXFA_NodeIteratorTemplate(NodeType* pRootNode = nullptr)
30      : m_pRoot(pRootNode), m_NodeStack(100) {
31    if (pRootNode) {
32      m_NodeStack.Push(pRootNode);
33    }
34  }
35  bool Init(NodeType* pRootNode) {
36    if (!pRootNode) {
37      return false;
38    }
39    m_pRoot = pRootNode;
40    m_NodeStack.RemoveAll(false);
41    m_NodeStack.Push(pRootNode);
42    return true;
43  }
44  void Clear() { m_NodeStack.RemoveAll(false); }
45  void Reset() {
46    Clear();
47    if (m_pRoot) {
48      m_NodeStack.Push(m_pRoot);
49    }
50  }
51  bool SetCurrent(NodeType* pCurNode) {
52    m_NodeStack.RemoveAll(false);
53    if (pCurNode) {
54      CFX_StackTemplate<NodeType*> revStack(100);
55      NodeType* pNode;
56      for (pNode = pCurNode; pNode && pNode != m_pRoot;
57           pNode = TraverseStrategy::GetParent(pNode)) {
58        revStack.Push(pNode);
59      }
60      if (!pNode) {
61        return false;
62      }
63      revStack.Push(m_pRoot);
64      while (revStack.GetSize()) {
65        m_NodeStack.Push(*revStack.GetTopElement());
66        revStack.Pop();
67      }
68    }
69    return true;
70  }
71  NodeType* GetCurrent() const {
72    return m_NodeStack.GetSize() ? *m_NodeStack.GetTopElement() : nullptr;
73  }
74  NodeType* GetRoot() const { return m_pRoot; }
75  NodeType* MoveToPrev() {
76    int32_t nStackLength = m_NodeStack.GetSize();
77    if (nStackLength == 1) {
78      return nullptr;
79    } else if (nStackLength > 1) {
80      NodeType* pCurItem = *m_NodeStack.GetTopElement();
81      m_NodeStack.Pop();
82      NodeType* pParentItem = *m_NodeStack.GetTopElement();
83      NodeType* pParentFirstChildItem =
84          TraverseStrategy::GetFirstChild(pParentItem);
85      if (pCurItem == pParentFirstChildItem) {
86        return pParentItem;
87      }
88      NodeType *pPrevItem = pParentFirstChildItem, *pPrevItemNext = nullptr;
89      for (; pPrevItem; pPrevItem = pPrevItemNext) {
90        pPrevItemNext = TraverseStrategy::GetNextSibling(pPrevItem);
91        if (!pPrevItemNext || pPrevItemNext == pCurItem) {
92          break;
93        }
94      }
95      m_NodeStack.Push(pPrevItem);
96    } else {
97      m_NodeStack.RemoveAll(false);
98      if (m_pRoot) {
99        m_NodeStack.Push(m_pRoot);
100      }
101    }
102    if (m_NodeStack.GetSize() > 0) {
103      NodeType* pChildItem = *m_NodeStack.GetTopElement();
104      while ((pChildItem = TraverseStrategy::GetFirstChild(pChildItem)) !=
105             nullptr) {
106        while (NodeType* pNextItem =
107                   TraverseStrategy::GetNextSibling(pChildItem)) {
108          pChildItem = pNextItem;
109        }
110        m_NodeStack.Push(pChildItem);
111      }
112      return *m_NodeStack.GetTopElement();
113    }
114    return nullptr;
115  }
116  NodeType* MoveToNext() {
117    NodeType** ppNode = nullptr;
118    NodeType* pCurrent = GetCurrent();
119    while (m_NodeStack.GetSize() > 0) {
120      while ((ppNode = m_NodeStack.GetTopElement()) != nullptr) {
121        if (pCurrent != *ppNode) {
122          return *ppNode;
123        }
124        NodeType* pChild = TraverseStrategy::GetFirstChild(*ppNode);
125        if (!pChild) {
126          break;
127        }
128        m_NodeStack.Push(pChild);
129      }
130      while ((ppNode = m_NodeStack.GetTopElement()) != nullptr) {
131        NodeType* pNext = TraverseStrategy::GetNextSibling(*ppNode);
132        m_NodeStack.Pop();
133        if (m_NodeStack.GetSize() == 0) {
134          break;
135        }
136        if (pNext) {
137          m_NodeStack.Push(pNext);
138          break;
139        }
140      }
141    }
142    return nullptr;
143  }
144  NodeType* SkipChildrenAndMoveToNext() {
145    NodeType** ppNode = nullptr;
146    while ((ppNode = m_NodeStack.GetTopElement()) != nullptr) {
147      NodeType* pNext = TraverseStrategy::GetNextSibling(*ppNode);
148      m_NodeStack.Pop();
149      if (m_NodeStack.GetSize() == 0) {
150        break;
151      }
152      if (pNext) {
153        m_NodeStack.Push(pNext);
154        break;
155      }
156    }
157    return GetCurrent();
158  }
159
160 protected:
161  NodeType* m_pRoot;
162  CFX_StackTemplate<NodeType*> m_NodeStack;
163};
164
165CXFA_LocaleValue XFA_GetLocaleValue(CXFA_WidgetData* pWidgetData);
166FX_DOUBLE XFA_ByteStringToDouble(const CFX_ByteStringC& szStringVal);
167int32_t XFA_MapRotation(int32_t nRotation);
168
169bool XFA_RecognizeRichText(CFDE_XMLElement* pRichTextXMLNode);
170void XFA_GetPlainTextFromRichText(CFDE_XMLNode* pXMLNode,
171                                  CFX_WideString& wsPlainText);
172bool XFA_FieldIsMultiListBox(CXFA_Node* pFieldNode);
173
174void XFA_DataExporter_DealWithDataGroupNode(CXFA_Node* pDataNode);
175void XFA_DataExporter_RegenerateFormFile(
176    CXFA_Node* pNode,
177    const CFX_RetainPtr<IFGAS_Stream>& pStream,
178    const FX_CHAR* pChecksum = nullptr,
179    bool bSaveXML = false);
180
181const XFA_NOTSUREATTRIBUTE* XFA_GetNotsureAttribute(
182    XFA_Element eElement,
183    XFA_ATTRIBUTE eAttribute,
184    XFA_ATTRIBUTETYPE eType = XFA_ATTRIBUTETYPE_NOTSURE);
185
186const XFA_SCRIPTATTRIBUTEINFO* XFA_GetScriptAttributeByName(
187    XFA_Element eElement,
188    const CFX_WideStringC& wsAttributeName);
189
190const XFA_PROPERTY* XFA_GetPropertyOfElement(XFA_Element eElement,
191                                             XFA_Element eProperty,
192                                             uint32_t dwPacket);
193const XFA_PROPERTY* XFA_GetElementProperties(XFA_Element eElement,
194                                             int32_t& iCount);
195const uint8_t* XFA_GetElementAttributes(XFA_Element eElement, int32_t& iCount);
196const XFA_ELEMENTINFO* XFA_GetElementByID(XFA_Element eName);
197XFA_Element XFA_GetElementTypeForName(const CFX_WideStringC& wsName);
198CXFA_Measurement XFA_GetAttributeDefaultValue_Measure(XFA_Element eElement,
199                                                      XFA_ATTRIBUTE eAttribute,
200                                                      uint32_t dwPacket);
201bool XFA_GetAttributeDefaultValue(void*& pValue,
202                                  XFA_Element eElement,
203                                  XFA_ATTRIBUTE eAttribute,
204                                  XFA_ATTRIBUTETYPE eType,
205                                  uint32_t dwPacket);
206const XFA_ATTRIBUTEINFO* XFA_GetAttributeByName(const CFX_WideStringC& wsName);
207const XFA_ATTRIBUTEINFO* XFA_GetAttributeByID(XFA_ATTRIBUTE eName);
208const XFA_ATTRIBUTEENUMINFO* XFA_GetAttributeEnumByName(
209    const CFX_WideStringC& wsName);
210const XFA_PACKETINFO* XFA_GetPacketByIndex(XFA_PACKET ePacket);
211const XFA_PACKETINFO* XFA_GetPacketByID(uint32_t dwPacket);
212
213#endif  // XFA_FXFA_PARSER_XFA_UTILS_H_
214