1 // Copyright 2016 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/parser/xfa_basic_data.h"
8 
9 #include <utility>
10 
11 #include "fxjs/xfa/cjx_boolean.h"
12 #include "fxjs/xfa/cjx_container.h"
13 #include "fxjs/xfa/cjx_datawindow.h"
14 #include "fxjs/xfa/cjx_delta.h"
15 #include "fxjs/xfa/cjx_desc.h"
16 #include "fxjs/xfa/cjx_draw.h"
17 #include "fxjs/xfa/cjx_encrypt.h"
18 #include "fxjs/xfa/cjx_eventpseudomodel.h"
19 #include "fxjs/xfa/cjx_exclgroup.h"
20 #include "fxjs/xfa/cjx_extras.h"
21 #include "fxjs/xfa/cjx_field.h"
22 #include "fxjs/xfa/cjx_form.h"
23 #include "fxjs/xfa/cjx_handler.h"
24 #include "fxjs/xfa/cjx_hostpseudomodel.h"
25 #include "fxjs/xfa/cjx_instancemanager.h"
26 #include "fxjs/xfa/cjx_layoutpseudomodel.h"
27 #include "fxjs/xfa/cjx_logpseudomodel.h"
28 #include "fxjs/xfa/cjx_manifest.h"
29 #include "fxjs/xfa/cjx_model.h"
30 #include "fxjs/xfa/cjx_node.h"
31 #include "fxjs/xfa/cjx_occur.h"
32 #include "fxjs/xfa/cjx_packet.h"
33 #include "fxjs/xfa/cjx_script.h"
34 #include "fxjs/xfa/cjx_signaturepseudomodel.h"
35 #include "fxjs/xfa/cjx_source.h"
36 #include "fxjs/xfa/cjx_subform.h"
37 #include "fxjs/xfa/cjx_textnode.h"
38 #include "fxjs/xfa/cjx_tree.h"
39 #include "fxjs/xfa/cjx_treelist.h"
40 #include "fxjs/xfa/cjx_wsdlconnection.h"
41 #include "fxjs/xfa/cjx_xfa.h"
42 #include "xfa/fxfa/fxfa_basic.h"
43 
44 namespace {
45 
46 struct PacketRecord {
47   XFA_PacketType packet_type;
48   uint32_t hash;
49   uint32_t flags;
50   const wchar_t* name;
51   const wchar_t* uri;
52 };
53 
54 const PacketRecord g_PacketTable[] = {
55 #undef PCKT____
56 #define PCKT____(a, b, c, d, e, f)                                          \
57   {XFA_PacketType::c, a, XFA_XDPPACKET_FLAGS_##e | XFA_XDPPACKET_FLAGS_##f, \
58    L##b, d},
59 #include "xfa/fxfa/parser/packets.inc"
60 #undef PCKT____
61 };
62 
63 struct ElementRecord {
64   uint32_t hash;  // Hashed as wide string.
65   XFA_Element element;
66   XFA_Element parent;
67   const char* name;
68 };
69 
70 const ElementRecord g_ElementTable[] = {
71 #undef ELEM____
72 #define ELEM____(a, b, c, d) {a, XFA_Element::c, XFA_Element::d, b},
73 #include "xfa/fxfa/parser/elements.inc"
74 #undef ELEM____
75 };
76 
77 struct AttributeRecord {
78   uint32_t hash;  // Hashed as wide string.
79   XFA_Attribute attribute;
80   XFA_ScriptType script_type;
81   const char* name;
82 };
83 
84 const AttributeRecord g_AttributeTable[] = {
85 #undef ATTR____
86 #define ATTR____(a, b, c, d) {a, XFA_Attribute::c, XFA_ScriptType::d, b},
87 #include "xfa/fxfa/parser/attributes.inc"
88 #undef ATTR____
89 };
90 
91 struct AttributeValueRecord {
92   uint32_t uHash;  // |pName| hashed as WideString.
93   XFA_AttributeValue eName;
94   const char* pName;
95 };
96 
97 const AttributeValueRecord g_AttributeValueTable[] = {
98 #undef VALUE____
99 #define VALUE____(a, b, c) {a, XFA_AttributeValue::c, b},
100 #include "xfa/fxfa/parser/attribute_values.inc"
101 #undef VALUE____
102 };
103 
104 struct ElementAttributeRecord {
105   XFA_Element element;
106   XFA_Attribute attribute;
107   XFA_ATTRIBUTE_CALLBACK callback;
108 };
109 
110 const ElementAttributeRecord g_ElementAttributeTable[] = {
111 #undef ELEM_ATTR____
112 #define ELEM_ATTR____(a, b, c) {XFA_Element::a, XFA_Attribute::b, c##_static},
113 #include "xfa/fxfa/parser/element_attributes.inc"
114 #undef ELEM_ATTR____
115 };
116 
117 }  // namespace
118 
XFA_GetPacketByIndex(XFA_PacketType ePacket)119 XFA_PACKETINFO XFA_GetPacketByIndex(XFA_PacketType ePacket) {
120   const PacketRecord* pRecord = &g_PacketTable[static_cast<uint8_t>(ePacket)];
121   return {pRecord->name, pRecord->packet_type, pRecord->uri, pRecord->flags};
122 }
123 
XFA_GetPacketByName(WideStringView wsName)124 Optional<XFA_PACKETINFO> XFA_GetPacketByName(WideStringView wsName) {
125   uint32_t hash = FX_HashCode_GetW(wsName, false);
126   auto* elem = std::lower_bound(
127       std::begin(g_PacketTable), std::end(g_PacketTable), hash,
128       [](const PacketRecord& a, uint32_t hash) { return a.hash < hash; });
129   if (elem != std::end(g_PacketTable) && elem->name == wsName)
130     return XFA_GetPacketByIndex(elem->packet_type);
131   return {};
132 }
133 
XFA_ElementToName(XFA_Element elem)134 ByteStringView XFA_ElementToName(XFA_Element elem) {
135   return g_ElementTable[static_cast<size_t>(elem)].name;
136 }
137 
XFA_GetElementByName(WideStringView name)138 XFA_Element XFA_GetElementByName(WideStringView name) {
139   uint32_t hash = FX_HashCode_GetW(name, false);
140   auto* elem = std::lower_bound(
141       std::begin(g_ElementTable), std::end(g_ElementTable), hash,
142       [](const ElementRecord& a, uint32_t hash) { return a.hash < hash; });
143   if (elem != std::end(g_ElementTable) && name.EqualsASCII(elem->name))
144     return elem->element;
145   return XFA_Element::Unknown;
146 }
147 
XFA_AttributeToName(XFA_Attribute attr)148 ByteStringView XFA_AttributeToName(XFA_Attribute attr) {
149   return g_AttributeTable[static_cast<size_t>(attr)].name;
150 }
151 
XFA_GetAttributeByName(WideStringView name)152 Optional<XFA_ATTRIBUTEINFO> XFA_GetAttributeByName(WideStringView name) {
153   uint32_t hash = FX_HashCode_GetW(name, false);
154   auto* elem = std::lower_bound(
155       std::begin(g_AttributeTable), std::end(g_AttributeTable), hash,
156       [](const AttributeRecord& a, uint32_t hash) { return a.hash < hash; });
157   if (elem != std::end(g_AttributeTable) && name.EqualsASCII(elem->name)) {
158     XFA_ATTRIBUTEINFO result;
159     result.attribute = elem->attribute;
160     result.eValueType = elem->script_type;
161     return result;
162   }
163   return {};
164 }
165 
XFA_AttributeValueToName(XFA_AttributeValue item)166 ByteStringView XFA_AttributeValueToName(XFA_AttributeValue item) {
167   return g_AttributeValueTable[static_cast<int32_t>(item)].pName;
168 }
169 
XFA_GetAttributeValueByName(WideStringView name)170 Optional<XFA_AttributeValue> XFA_GetAttributeValueByName(WideStringView name) {
171   auto* it = std::lower_bound(std::begin(g_AttributeValueTable),
172                               std::end(g_AttributeValueTable),
173                               FX_HashCode_GetW(name, false),
174                               [](const AttributeValueRecord& arg,
175                                  uint32_t hash) { return arg.uHash < hash; });
176   if (it != std::end(g_AttributeValueTable) && name.EqualsASCII(it->pName))
177     return it->eName;
178 
179   return {};
180 }
181 
XFA_GetScriptAttributeByName(XFA_Element element,WideStringView attribute_name)182 Optional<XFA_SCRIPTATTRIBUTEINFO> XFA_GetScriptAttributeByName(
183     XFA_Element element,
184     WideStringView attribute_name) {
185   Optional<XFA_ATTRIBUTEINFO> attr = XFA_GetAttributeByName(attribute_name);
186   if (!attr.has_value())
187     return {};
188 
189   while (element != XFA_Element::Unknown) {
190     auto compound_key = std::make_pair(element, attr.value().attribute);
191     auto* it = std::lower_bound(
192         std::begin(g_ElementAttributeTable), std::end(g_ElementAttributeTable),
193         compound_key,
194         [](const ElementAttributeRecord& arg,
195            const std::pair<XFA_Element, XFA_Attribute>& key) {
196           return std::make_pair(arg.element, arg.attribute) < key;
197         });
198     if (it != std::end(g_ElementAttributeTable) &&
199         compound_key == std::make_pair(it->element, it->attribute)) {
200       XFA_SCRIPTATTRIBUTEINFO result;
201       result.attribute = attr.value().attribute;
202       result.eValueType = attr.value().eValueType;
203       result.callback = it->callback;
204       return result;
205     }
206     element = g_ElementTable[static_cast<size_t>(element)].parent;
207   }
208   return {};
209 }
210