1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef AAPT_XML_DOM_H
18 #define AAPT_XML_DOM_H
19 
20 #include <memory>
21 #include <string>
22 #include <vector>
23 
24 #include "androidfw/StringPiece.h"
25 
26 #include "Diagnostics.h"
27 #include "Resource.h"
28 #include "ResourceValues.h"
29 #include "io/Io.h"
30 #include "util/Util.h"
31 #include "xml/XmlUtil.h"
32 
33 namespace aapt {
34 namespace xml {
35 
36 class Element;
37 class Visitor;
38 class ConstVisitor;
39 
40 // Base class for all XML nodes.
41 class Node {
42  public:
43   virtual ~Node() = default;
44 
45   Element* parent = nullptr;
46   size_t line_number = 0u;
47   size_t column_number = 0u;
48   std::string comment;
49 
50   virtual void Accept(Visitor* visitor) = 0;
51   virtual void Accept(ConstVisitor* visitor) const = 0;
52 
53   using ElementCloneFunc = std::function<void(const Element&, Element*)>;
54 
55   // Clones the Node subtree, using the given function to decide how to clone an Element.
56   virtual std::unique_ptr<Node> Clone(const ElementCloneFunc& el_cloner) const = 0;
57 };
58 
59 // A namespace declaration (xmlns:prefix="uri").
60 struct NamespaceDecl {
61   std::string prefix;
62   std::string uri;
63   size_t line_number = 0u;
64   size_t column_number = 0u;
65 };
66 
67 struct AaptAttribute {
68   explicit AaptAttribute(const ::aapt::Attribute& attr, const Maybe<ResourceId>& resid = {})
attributeAaptAttribute69       : attribute(attr), id(resid) {
70   }
71 
72   aapt::Attribute attribute;
73   Maybe<ResourceId> id;
74 };
75 
76 // An XML attribute.
77 struct Attribute {
78   std::string namespace_uri;
79   std::string name;
80   std::string value;
81 
82   Maybe<AaptAttribute> compiled_attribute;
83   std::unique_ptr<Item> compiled_value;
84 };
85 
86 // An Element XML node.
87 class Element : public Node {
88  public:
89   // Ordered namespace prefix declarations.
90   std::vector<NamespaceDecl> namespace_decls;
91 
92   std::string namespace_uri;
93   std::string name;
94   std::vector<Attribute> attributes;
95   std::vector<std::unique_ptr<Node>> children;
96 
97   void AppendChild(std::unique_ptr<Node> child);
98   void InsertChild(size_t index, std::unique_ptr<Node> child);
99 
100   Attribute* FindAttribute(const android::StringPiece& ns, const android::StringPiece& name);
101   const Attribute* FindAttribute(const android::StringPiece& ns,
102                                  const android::StringPiece& name) const;
103   Attribute* FindOrCreateAttribute(const android::StringPiece& ns,
104                                    const android::StringPiece& name);
105   void RemoveAttribute(const android::StringPiece& ns,
106                        const android::StringPiece& name);
107 
108   Element* FindChild(const android::StringPiece& ns, const android::StringPiece& name);
109   const Element* FindChild(const android::StringPiece& ns, const android::StringPiece& name) const;
110 
111   Element* FindChildWithAttribute(const android::StringPiece& ns, const android::StringPiece& name,
112                                   const android::StringPiece& attr_ns,
113                                   const android::StringPiece& attr_name,
114                                   const android::StringPiece& attr_value);
115 
116   const Element* FindChildWithAttribute(const android::StringPiece& ns,
117                                         const android::StringPiece& name,
118                                         const android::StringPiece& attr_ns,
119                                         const android::StringPiece& attr_name,
120                                         const android::StringPiece& attr_value) const;
121 
122   std::vector<Element*> GetChildElements();
123 
124   // Due to overriding of subtypes not working with unique_ptr, define a convenience Clone method
125   // that knows cloning an element returns an element.
126   std::unique_ptr<Element> CloneElement(const ElementCloneFunc& el_cloner) const;
127 
128   std::unique_ptr<Node> Clone(const ElementCloneFunc& el_cloner) const override;
129 
130   void Accept(Visitor* visitor) override;
131   void Accept(ConstVisitor* visitor) const override;
132 };
133 
134 // A Text (CDATA) XML node. Can not have any children.
135 class Text : public Node {
136  public:
137   std::string text;
138 
139   std::unique_ptr<Node> Clone(const ElementCloneFunc& el_cloner) const override;
140 
141   void Accept(Visitor* visitor) override;
142   void Accept(ConstVisitor* visitor) const override;
143 };
144 
145 // An XML resource with a source, name, and XML tree.
146 class XmlResource {
147  public:
148   ResourceFile file;
149 
150   // StringPool must come before the xml::Node. Destructors are called in reverse order, and
151   // the xml::Node may have StringPool references that need to be destroyed before the StringPool
152   // is destroyed.
153   StringPool string_pool;
154 
155   std::unique_ptr<xml::Element> root;
156 
157   std::unique_ptr<XmlResource> Clone() const;
158 };
159 
160 // Inflates an XML DOM from an InputStream, logging errors to the logger.
161 std::unique_ptr<XmlResource> Inflate(io::InputStream* in, IDiagnostics* diag, const Source& source);
162 
163 // Inflates an XML DOM from a binary ResXMLTree.
164 std::unique_ptr<XmlResource> Inflate(const void* data, size_t len,
165                                      std::string* out_error = nullptr);
166 
167 Element* FindRootElement(Node* node);
168 
169 // Visitor whose default implementation visits the children nodes of any node.
170 class Visitor {
171  public:
172   virtual ~Visitor() = default;
173 
Visit(Element * el)174   virtual void Visit(Element* el) {
175     VisitChildren(el);
176   }
177 
Visit(Text * text)178   virtual void Visit(Text* text) {
179   }
180 
181  protected:
182   Visitor() = default;
183 
VisitChildren(Element * el)184   void VisitChildren(Element* el) {
185     for (auto& child : el->children) {
186       child->Accept(this);
187     }
188   }
189 
BeforeVisitElement(Element * el)190   virtual void BeforeVisitElement(Element* el) {
191   }
AfterVisitElement(Element * el)192   virtual void AfterVisitElement(Element* el) {
193   }
194 
195  private:
196   DISALLOW_COPY_AND_ASSIGN(Visitor);
197 
198   friend class Element;
199 };
200 
201 class ConstVisitor {
202  public:
203   virtual ~ConstVisitor() = default;
204 
Visit(const Element * el)205   virtual void Visit(const Element* el) {
206     VisitChildren(el);
207   }
208 
Visit(const Text * text)209   virtual void Visit(const Text* text) {
210   }
211 
212  protected:
213   ConstVisitor() = default;
214 
VisitChildren(const Element * el)215   void VisitChildren(const Element* el) {
216     for (const auto& child : el->children) {
217       child->Accept(this);
218     }
219   }
220 
BeforeVisitElement(const Element * el)221   virtual void BeforeVisitElement(const Element* el) {
222   }
223 
AfterVisitElement(const Element * el)224   virtual void AfterVisitElement(const Element* el) {
225   }
226 
227  private:
228   DISALLOW_COPY_AND_ASSIGN(ConstVisitor);
229 
230   friend class Element;
231 };
232 
233 // An XML DOM visitor that will record the package name for a namespace prefix.
234 class PackageAwareVisitor : public Visitor, public IPackageDeclStack {
235  public:
236   using Visitor::Visit;
237 
238   Maybe<ExtractedPackage> TransformPackageAlias(const android::StringPiece& alias) const override;
239 
240  protected:
241   PackageAwareVisitor() = default;
242 
243   void BeforeVisitElement(Element* el) override;
244   void AfterVisitElement(Element* el) override;
245 
246  private:
247   DISALLOW_COPY_AND_ASSIGN(PackageAwareVisitor);
248 
249   struct PackageDecl {
250     std::string prefix;
251     ExtractedPackage package;
252   };
253 
254   std::vector<std::vector<PackageDecl>> package_decls_;
255 };
256 
257 namespace internal {
258 
259 // Base class that overrides the default behaviour and does not descend into child nodes.
260 class NodeCastBase : public ConstVisitor {
261  public:
Visit(const Element * el)262   void Visit(const Element* el) override {
263   }
Visit(const Text * el)264   void Visit(const Text* el) override {
265   }
266 
267  protected:
268   NodeCastBase() = default;
269 
BeforeVisitElement(const Element * el)270   void BeforeVisitElement(const Element* el) override {
271   }
AfterVisitElement(const Element * el)272   void AfterVisitElement(const Element* el) override {
273   }
274 
275  private:
276   DISALLOW_COPY_AND_ASSIGN(NodeCastBase);
277 };
278 
279 template <typename T>
280 class NodeCastImpl : public NodeCastBase {
281  public:
282   using NodeCastBase::Visit;
283 
284   NodeCastImpl() = default;
285 
286   const T* value = nullptr;
287 
Visit(const T * v)288   void Visit(const T* v) override {
289     value = v;
290   }
291 
292  private:
293   DISALLOW_COPY_AND_ASSIGN(NodeCastImpl);
294 };
295 
296 }  // namespace internal
297 
298 template <typename T>
NodeCast(const Node * node)299 const T* NodeCast(const Node* node) {
300   internal::NodeCastImpl<T> visitor;
301   node->Accept(&visitor);
302   return visitor.value;
303 }
304 
305 template <typename T>
NodeCast(Node * node)306 T* NodeCast(Node* node) {
307   return const_cast<T*>(NodeCast<T>(static_cast<const T*>(node)));
308 }
309 
310 }  // namespace xml
311 }  // namespace aapt
312 
313 #endif  // AAPT_XML_DOM_H
314