1 /*
2 * Copyright (C) 2014 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 #include <androidfw/ResourceTypes.h>
18 #include <utils/String8.h>
19
20 #include "AaptXml.h"
21
22 using namespace android;
23
24 namespace AaptXml {
25
getStringAttributeAtIndex(const ResXMLTree & tree,ssize_t attrIndex,String8 * outError)26 static String8 getStringAttributeAtIndex(const ResXMLTree& tree, ssize_t attrIndex,
27 String8* outError) {
28 Res_value value;
29 if (tree.getAttributeValue(attrIndex, &value) < 0) {
30 if (outError != NULL) {
31 *outError = "could not find attribute at index";
32 }
33 return String8();
34 }
35
36 if (value.dataType != Res_value::TYPE_STRING) {
37 if (outError != NULL) {
38 *outError = "attribute is not a string value";
39 }
40 return String8();
41 }
42
43 size_t len;
44 const char16_t* str = tree.getAttributeStringValue(attrIndex, &len);
45 return str ? String8(str, len) : String8();
46 }
47
getIntegerAttributeAtIndex(const ResXMLTree & tree,ssize_t attrIndex,int32_t defValue,String8 * outError)48 static int32_t getIntegerAttributeAtIndex(const ResXMLTree& tree, ssize_t attrIndex,
49 int32_t defValue, String8* outError) {
50 Res_value value;
51 if (tree.getAttributeValue(attrIndex, &value) < 0) {
52 if (outError != NULL) {
53 *outError = "could not find attribute at index";
54 }
55 return defValue;
56 }
57
58 if (value.dataType < Res_value::TYPE_FIRST_INT
59 || value.dataType > Res_value::TYPE_LAST_INT) {
60 if (outError != NULL) {
61 *outError = "attribute is not an integer value";
62 }
63 return defValue;
64 }
65 return value.data;
66 }
67
68
indexOfAttribute(const ResXMLTree & tree,uint32_t attrRes)69 ssize_t indexOfAttribute(const ResXMLTree& tree, uint32_t attrRes) {
70 size_t attrCount = tree.getAttributeCount();
71 for (size_t i = 0; i < attrCount; i++) {
72 if (tree.getAttributeNameResID(i) == attrRes) {
73 return (ssize_t)i;
74 }
75 }
76 return -1;
77 }
78
getAttribute(const ResXMLTree & tree,const char * ns,const char * attr,String8 * outError)79 String8 getAttribute(const ResXMLTree& tree, const char* ns,
80 const char* attr, String8* outError) {
81 ssize_t idx = tree.indexOfAttribute(ns, attr);
82 if (idx < 0) {
83 return String8();
84 }
85 return getStringAttributeAtIndex(tree, idx, outError);
86 }
87
getAttribute(const ResXMLTree & tree,uint32_t attrRes,String8 * outError)88 String8 getAttribute(const ResXMLTree& tree, uint32_t attrRes, String8* outError) {
89 ssize_t idx = indexOfAttribute(tree, attrRes);
90 if (idx < 0) {
91 return String8();
92 }
93 return getStringAttributeAtIndex(tree, idx, outError);
94 }
95
getResolvedAttribute(const ResTable & resTable,const ResXMLTree & tree,uint32_t attrRes,String8 * outError)96 String8 getResolvedAttribute(const ResTable& resTable, const ResXMLTree& tree,
97 uint32_t attrRes, String8* outError) {
98 ssize_t idx = indexOfAttribute(tree, attrRes);
99 if (idx < 0) {
100 return String8();
101 }
102
103 Res_value value;
104 if (tree.getAttributeValue(idx, &value) == BAD_TYPE) {
105 if (outError != NULL) {
106 *outError = "attribute value is corrupt";
107 }
108 return String8();
109 }
110
111 // Check if the string is inline in the XML.
112 if (value.dataType == Res_value::TYPE_STRING) {
113 size_t len;
114 const char16_t* str = tree.getAttributeStringValue(idx, &len);
115 return str ? String8(str, len) : String8();
116 }
117
118 // Resolve the reference if there is one.
119 ssize_t block = resTable.resolveReference(&value, 0);
120 if (block < 0) {
121 if (outError != NULL) {
122 *outError = "attribute value reference does not exist";
123 }
124 return String8();
125 }
126
127 if (value.dataType != Res_value::TYPE_STRING) {
128 if (outError != NULL) {
129 *outError = "attribute is not a string value";
130 }
131 return String8();
132 }
133
134 size_t len;
135 const char16_t* str = resTable.valueToString(&value, static_cast<size_t>(block), NULL, &len);
136 return str ? String8(str, len) : String8();
137 }
138
getIntegerAttribute(const ResXMLTree & tree,const char * ns,const char * attr,int32_t defValue,String8 * outError)139 int32_t getIntegerAttribute(const ResXMLTree& tree, const char* ns,
140 const char* attr, int32_t defValue, String8* outError) {
141 ssize_t idx = tree.indexOfAttribute(ns, attr);
142 if (idx < 0) {
143 return defValue;
144 }
145 return getIntegerAttributeAtIndex(tree, idx, defValue, outError);
146 }
147
getIntegerAttribute(const ResXMLTree & tree,uint32_t attrRes,int32_t defValue,String8 * outError)148 int32_t getIntegerAttribute(const ResXMLTree& tree, uint32_t attrRes, int32_t defValue,
149 String8* outError) {
150 ssize_t idx = indexOfAttribute(tree, attrRes);
151 if (idx < 0) {
152 return defValue;
153 }
154 return getIntegerAttributeAtIndex(tree, idx, defValue, outError);
155 }
156
getResolvedIntegerAttribute(const ResTable & resTable,const ResXMLTree & tree,uint32_t attrRes,int32_t defValue,String8 * outError)157 int32_t getResolvedIntegerAttribute(const ResTable& resTable, const ResXMLTree& tree,
158 uint32_t attrRes, int32_t defValue, String8* outError) {
159 ssize_t idx = indexOfAttribute(tree, attrRes);
160 if (idx < 0) {
161 return defValue;
162 }
163 Res_value value;
164 if (tree.getAttributeValue(idx, &value) != NO_ERROR) {
165 if (value.dataType == Res_value::TYPE_REFERENCE) {
166 resTable.resolveReference(&value, 0);
167 }
168 if (value.dataType < Res_value::TYPE_FIRST_INT
169 || value.dataType > Res_value::TYPE_LAST_INT) {
170 if (outError != NULL) {
171 *outError = "attribute is not an integer value";
172 }
173 return defValue;
174 }
175 }
176 return value.data;
177 }
178
getResolvedResourceAttribute(const ResTable & resTable,const ResXMLTree & tree,uint32_t attrRes,Res_value * outValue,String8 * outError)179 void getResolvedResourceAttribute(const ResTable& resTable, const ResXMLTree& tree,
180 uint32_t attrRes, Res_value* outValue, String8* outError) {
181 ssize_t idx = indexOfAttribute(tree, attrRes);
182 if (idx < 0) {
183 if (outError != NULL) {
184 *outError = "attribute could not be found";
185 }
186 return;
187 }
188 if (tree.getAttributeValue(idx, outValue) != NO_ERROR) {
189 if (outValue->dataType == Res_value::TYPE_REFERENCE) {
190 resTable.resolveReference(outValue, 0);
191 }
192 // The attribute was found and was resolved if need be.
193 return;
194 }
195 if (outError != NULL) {
196 *outError = "error getting resolved resource attribute";
197 }
198 }
199
200 } // namespace AaptXml
201