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_RESOURCE_PARSER_H
18 #define AAPT_RESOURCE_PARSER_H
19 
20 #include <memory>
21 #include <optional>
22 
23 #include "ResourceTable.h"
24 #include "ResourceValues.h"
25 #include "android-base/macros.h"
26 #include "androidfw/ConfigDescription.h"
27 #include "androidfw/IDiagnostics.h"
28 #include "androidfw/StringPiece.h"
29 #include "androidfw/StringPool.h"
30 #include "xml/XmlPullParser.h"
31 
32 namespace aapt {
33 
34 struct ParsedResource;
35 
36 struct ResourceParserOptions {
37   /**
38    * Whether the default setting for this parser is to allow translation.
39    */
40   bool translatable = true;
41 
42   /**
43    * Whether positional arguments in formatted strings are treated as errors or
44    * warnings.
45    */
46   bool error_on_positional_arguments = true;
47 
48   /**
49    * If true, apply the same visibility rules for styleables as are used for
50    * all other resources.  Otherwise, all styleables will be made public.
51    */
52   bool preserve_visibility_of_styleables = false;
53 
54   // If visibility was forced, we need to use it when creating a new resource and also error if we
55   // try to parse the <public>, <public-group>, <java-symbol> or <symbol> tags.
56   std::optional<Visibility::Level> visibility;
57 };
58 
59 struct FlattenedXmlSubTree {
60   std::string raw_value;
61   android::StyleString style_string;
62   std::vector<UntranslatableSection> untranslatable_sections;
63   xml::IPackageDeclStack* namespace_resolver;
64   android::Source source;
65 };
66 
67 /*
68  * Parses an XML file for resources and adds them to a ResourceTable.
69  */
70 class ResourceParser {
71  public:
72   ResourceParser(android::IDiagnostics* diag, ResourceTable* table, const android::Source& source,
73                  const android::ConfigDescription& config,
74                  const ResourceParserOptions& options = {});
75   bool Parse(xml::XmlPullParser* parser);
76 
77   static std::unique_ptr<Item> ParseXml(const FlattenedXmlSubTree& xmlsub_tree, uint32_t type_mask,
78                                         bool allow_raw_value, ResourceTable& table,
79                                         const android::ConfigDescription& config,
80                                         android::IDiagnostics& diag);
81 
82  private:
83   DISALLOW_COPY_AND_ASSIGN(ResourceParser);
84 
85   std::optional<FlattenedXmlSubTree> CreateFlattenSubTree(xml::XmlPullParser* parser);
86 
87   // Parses the XML subtree as a StyleString (flattened XML representation for strings with
88   // formatting). If parsing fails, false is returned and the out parameters are left in an
89   // unspecified state. Otherwise,
90   // `out_style_string` contains the escaped and whitespace trimmed text.
91   // `out_raw_string` contains the un-escaped text.
92   // `out_untranslatable_sections` contains the sections of the string that should not be
93   // translated.
94   bool FlattenXmlSubtree(xml::XmlPullParser* parser, std::string* out_raw_string,
95                          android::StyleString* out_style_string,
96                          std::vector<UntranslatableSection>* out_untranslatable_sections);
97 
98   /*
99    * Parses the XML subtree and returns an Item.
100    * The type of Item that can be parsed is denoted by the `type_mask`.
101    * If `allow_raw_value` is true and the subtree can not be parsed as a regular
102    * Item, then a
103    * RawString is returned. Otherwise this returns false;
104    */
105   std::unique_ptr<Item> ParseXml(xml::XmlPullParser* parser, const uint32_t type_mask,
106                                  const bool allow_raw_value);
107 
108   bool ParseResources(xml::XmlPullParser* parser);
109   bool ParseResource(xml::XmlPullParser* parser, ParsedResource* out_resource);
110 
111   bool ParseItem(xml::XmlPullParser* parser, ParsedResource* out_resource, uint32_t format);
112   bool ParseString(xml::XmlPullParser* parser, ParsedResource* out_resource);
113   bool ParseMacro(xml::XmlPullParser* parser, ParsedResource* out_resource);
114   bool ParsePublic(xml::XmlPullParser* parser, ParsedResource* out_resource);
115   bool ParsePublicGroup(xml::XmlPullParser* parser, ParsedResource* out_resource);
116   bool ParseStagingPublicGroup(xml::XmlPullParser* parser, ParsedResource* out_resource);
117   bool ParseStagingPublicGroupFinal(xml::XmlPullParser* parser, ParsedResource* out_resource);
118   bool ParseSymbolImpl(xml::XmlPullParser* parser, ParsedResource* out_resource);
119   bool ParseSymbol(xml::XmlPullParser* parser, ParsedResource* out_resource);
120   bool ParseOverlayable(xml::XmlPullParser* parser, ParsedResource* out_resource);
121   bool ParseAddResource(xml::XmlPullParser* parser, ParsedResource* out_resource);
122   bool ParseAttr(xml::XmlPullParser* parser, ParsedResource* out_resource);
123   bool ParseAttrImpl(xml::XmlPullParser* parser, ParsedResource* out_resource, bool weak);
124   std::optional<Attribute::Symbol> ParseEnumOrFlagItem(xml::XmlPullParser* parser,
125                                                        android::StringPiece tag);
126   bool ParseStyle(ResourceType type, xml::XmlPullParser* parser, ParsedResource* out_resource);
127   bool ParseStyleItem(xml::XmlPullParser* parser, Style* style);
128   bool ParseDeclareStyleable(xml::XmlPullParser* parser, ParsedResource* out_resource);
129   bool ParseArray(xml::XmlPullParser* parser, ParsedResource* out_resource);
130   bool ParseIntegerArray(xml::XmlPullParser* parser, ParsedResource* out_resource);
131   bool ParseStringArray(xml::XmlPullParser* parser, ParsedResource* out_resource);
132   bool ParseArrayImpl(xml::XmlPullParser* parser, ParsedResource* out_resource, uint32_t typeMask);
133   bool ParsePlural(xml::XmlPullParser* parser, ParsedResource* out_resource);
134 
135   android::IDiagnostics* diag_;
136   ResourceTable* table_;
137   android::Source source_;
138   android::ConfigDescription config_;
139   ResourceParserOptions options_;
140 };
141 
142 }  // namespace aapt
143 
144 #endif  // AAPT_RESOURCE_PARSER_H
145