• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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