Home | History | Annotate | Download | only in aapt2
      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 #include "Logger.h"
     18 #include "Util.h"
     19 #include "XmlDom.h"
     20 #include "XmlPullParser.h"
     21 
     22 #include <cassert>
     23 #include <memory>
     24 #include <stack>
     25 #include <string>
     26 #include <tuple>
     27 
     28 namespace aapt {
     29 namespace xml {
     30 
     31 constexpr char kXmlNamespaceSep = 1;
     32 
     33 struct Stack {
     34     std::unique_ptr<xml::Node> root;
     35     std::stack<xml::Node*> nodeStack;
     36     std::u16string pendingComment;
     37 };
     38 
     39 /**
     40  * Extracts the namespace and name of an expanded element or attribute name.
     41  */
     42 static void splitName(const char* name, std::u16string* outNs, std::u16string* outName) {
     43     const char* p = name;
     44     while (*p != 0 && *p != kXmlNamespaceSep) {
     45         p++;
     46     }
     47 
     48     if (*p == 0) {
     49         outNs->clear();
     50         *outName = util::utf8ToUtf16(name);
     51     } else {
     52         *outNs = util::utf8ToUtf16(StringPiece(name, (p - name)));
     53         *outName = util::utf8ToUtf16(p + 1);
     54     }
     55 }
     56 
     57 static void addToStack(Stack* stack, XML_Parser parser, std::unique_ptr<Node> node) {
     58     node->lineNumber = XML_GetCurrentLineNumber(parser);
     59     node->columnNumber = XML_GetCurrentColumnNumber(parser);
     60 
     61     Node* thisNode = node.get();
     62     if (!stack->nodeStack.empty()) {
     63         stack->nodeStack.top()->addChild(std::move(node));
     64     } else {
     65         stack->root = std::move(node);
     66     }
     67 
     68     if (thisNode->type != NodeType::kText) {
     69         stack->nodeStack.push(thisNode);
     70     }
     71 }
     72 
     73 static void XMLCALL startNamespaceHandler(void* userData, const char* prefix, const char* uri) {
     74     XML_Parser parser = reinterpret_cast<XML_Parser>(userData);
     75     Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser));
     76 
     77     std::unique_ptr<Namespace> ns = util::make_unique<Namespace>();
     78     if (prefix) {
     79         ns->namespacePrefix = util::utf8ToUtf16(prefix);
     80     }
     81 
     82     if (uri) {
     83         ns->namespaceUri = util::utf8ToUtf16(uri);
     84     }
     85 
     86     addToStack(stack, parser, std::move(ns));
     87 }
     88 
     89 static void XMLCALL endNamespaceHandler(void* userData, const char* prefix) {
     90     XML_Parser parser = reinterpret_cast<XML_Parser>(userData);
     91     Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser));
     92 
     93     assert(!stack->nodeStack.empty());
     94     stack->nodeStack.pop();
     95 }
     96 
     97 static bool lessAttribute(const Attribute& lhs, const Attribute& rhs) {
     98     return std::tie(lhs.namespaceUri, lhs.name, lhs.value) <
     99             std::tie(rhs.namespaceUri, rhs.name, rhs.value);
    100 }
    101 
    102 static void XMLCALL startElementHandler(void* userData, const char* name, const char** attrs) {
    103     XML_Parser parser = reinterpret_cast<XML_Parser>(userData);
    104     Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser));
    105 
    106     std::unique_ptr<Element> el = util::make_unique<Element>();
    107     splitName(name, &el->namespaceUri, &el->name);
    108 
    109     while (*attrs) {
    110         Attribute attribute;
    111         splitName(*attrs++, &attribute.namespaceUri, &attribute.name);
    112         attribute.value = util::utf8ToUtf16(*attrs++);
    113 
    114         // Insert in sorted order.
    115         auto iter = std::lower_bound(el->attributes.begin(), el->attributes.end(), attribute,
    116                                      lessAttribute);
    117         el->attributes.insert(iter, std::move(attribute));
    118     }
    119 
    120     el->comment = std::move(stack->pendingComment);
    121     addToStack(stack, parser, std::move(el));
    122 }
    123 
    124 static void XMLCALL endElementHandler(void* userData, const char* name) {
    125     XML_Parser parser = reinterpret_cast<XML_Parser>(userData);
    126     Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser));
    127 
    128     assert(!stack->nodeStack.empty());
    129     stack->nodeStack.top()->comment = std::move(stack->pendingComment);
    130     stack->nodeStack.pop();
    131 }
    132 
    133 static void XMLCALL characterDataHandler(void* userData, const char* s, int len) {
    134     XML_Parser parser = reinterpret_cast<XML_Parser>(userData);
    135     Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser));
    136 
    137     if (!s || len <= 0) {
    138         return;
    139     }
    140 
    141     // See if we can just append the text to a previous text node.
    142     if (!stack->nodeStack.empty()) {
    143         Node* currentParent = stack->nodeStack.top();
    144         if (!currentParent->children.empty()) {
    145             Node* lastChild = currentParent->children.back().get();
    146             if (lastChild->type == NodeType::kText) {
    147                 Text* text = static_cast<Text*>(lastChild);
    148                 text->text += util::utf8ToUtf16(StringPiece(s, len));
    149                 return;
    150             }
    151         }
    152     }
    153 
    154     std::unique_ptr<Text> text = util::make_unique<Text>();
    155     text->text = util::utf8ToUtf16(StringPiece(s, len));
    156     addToStack(stack, parser, std::move(text));
    157 }
    158 
    159 static void XMLCALL commentDataHandler(void* userData, const char* comment) {
    160     XML_Parser parser = reinterpret_cast<XML_Parser>(userData);
    161     Stack* stack = reinterpret_cast<Stack*>(XML_GetUserData(parser));
    162 
    163     if (!stack->pendingComment.empty()) {
    164         stack->pendingComment += '\n';
    165     }
    166     stack->pendingComment += util::utf8ToUtf16(comment);
    167 }
    168 
    169 std::unique_ptr<Node> inflate(std::istream* in, SourceLogger* logger) {
    170     Stack stack;
    171 
    172     XML_Parser parser = XML_ParserCreateNS(nullptr, kXmlNamespaceSep);
    173     XML_SetUserData(parser, &stack);
    174     XML_UseParserAsHandlerArg(parser);
    175     XML_SetElementHandler(parser, startElementHandler, endElementHandler);
    176     XML_SetNamespaceDeclHandler(parser, startNamespaceHandler, endNamespaceHandler);
    177     XML_SetCharacterDataHandler(parser, characterDataHandler);
    178     XML_SetCommentHandler(parser, commentDataHandler);
    179 
    180     char buffer[1024];
    181     while (!in->eof()) {
    182         in->read(buffer, sizeof(buffer) / sizeof(buffer[0]));
    183         if (in->bad() && !in->eof()) {
    184             stack.root = {};
    185             logger->error() << strerror(errno) << std::endl;
    186             break;
    187         }
    188 
    189         if (XML_Parse(parser, buffer, in->gcount(), in->eof()) == XML_STATUS_ERROR) {
    190             stack.root = {};
    191             logger->error(XML_GetCurrentLineNumber(parser))
    192                     << XML_ErrorString(XML_GetErrorCode(parser)) << std::endl;
    193             break;
    194         }
    195     }
    196 
    197     XML_ParserFree(parser);
    198     return std::move(stack.root);
    199 }
    200 
    201 static void copyAttributes(Element* el, android::ResXMLParser* parser) {
    202     const size_t attrCount = parser->getAttributeCount();
    203     if (attrCount > 0) {
    204         el->attributes.reserve(attrCount);
    205         for (size_t i = 0; i < attrCount; i++) {
    206             Attribute attr;
    207             size_t len;
    208             const char16_t* str16 = parser->getAttributeNamespace(i, &len);
    209             if (str16) {
    210                 attr.namespaceUri.assign(str16, len);
    211             }
    212 
    213             str16 = parser->getAttributeName(i, &len);
    214             if (str16) {
    215                 attr.name.assign(str16, len);
    216             }
    217 
    218             str16 = parser->getAttributeStringValue(i, &len);
    219             if (str16) {
    220                 attr.value.assign(str16, len);
    221             }
    222             el->attributes.push_back(std::move(attr));
    223         }
    224     }
    225 }
    226 
    227 std::unique_ptr<Node> inflate(const void* data, size_t dataLen, SourceLogger* logger) {
    228     std::unique_ptr<Node> root;
    229     std::stack<Node*> nodeStack;
    230 
    231     android::ResXMLTree tree;
    232     if (tree.setTo(data, dataLen) != android::NO_ERROR) {
    233         return {};
    234     }
    235 
    236     android::ResXMLParser::event_code_t code;
    237     while ((code = tree.next()) != android::ResXMLParser::BAD_DOCUMENT &&
    238             code != android::ResXMLParser::END_DOCUMENT) {
    239         std::unique_ptr<Node> newNode;
    240         switch (code) {
    241             case android::ResXMLParser::START_NAMESPACE: {
    242                 std::unique_ptr<Namespace> node = util::make_unique<Namespace>();
    243                 size_t len;
    244                 const char16_t* str16 = tree.getNamespacePrefix(&len);
    245                 if (str16) {
    246                     node->namespacePrefix.assign(str16, len);
    247                 }
    248 
    249                 str16 = tree.getNamespaceUri(&len);
    250                 if (str16) {
    251                     node->namespaceUri.assign(str16, len);
    252                 }
    253                 newNode = std::move(node);
    254                 break;
    255             }
    256 
    257             case android::ResXMLParser::START_TAG: {
    258                 std::unique_ptr<Element> node = util::make_unique<Element>();
    259                 size_t len;
    260                 const char16_t* str16 = tree.getElementNamespace(&len);
    261                 if (str16) {
    262                     node->namespaceUri.assign(str16, len);
    263                 }
    264 
    265                 str16 = tree.getElementName(&len);
    266                 if (str16) {
    267                     node->name.assign(str16, len);
    268                 }
    269 
    270                 copyAttributes(node.get(), &tree);
    271 
    272                 newNode = std::move(node);
    273                 break;
    274             }
    275 
    276             case android::ResXMLParser::TEXT: {
    277                 std::unique_ptr<Text> node = util::make_unique<Text>();
    278                 size_t len;
    279                 const char16_t* str16 = tree.getText(&len);
    280                 if (str16) {
    281                     node->text.assign(str16, len);
    282                 }
    283                 newNode = std::move(node);
    284                 break;
    285             }
    286 
    287             case android::ResXMLParser::END_NAMESPACE:
    288             case android::ResXMLParser::END_TAG:
    289                 assert(!nodeStack.empty());
    290                 nodeStack.pop();
    291                 break;
    292 
    293             default:
    294                 assert(false);
    295                 break;
    296         }
    297 
    298         if (newNode) {
    299             newNode->lineNumber = tree.getLineNumber();
    300 
    301             Node* thisNode = newNode.get();
    302             if (!root) {
    303                 assert(nodeStack.empty());
    304                 root = std::move(newNode);
    305             } else {
    306                 assert(!nodeStack.empty());
    307                 nodeStack.top()->addChild(std::move(newNode));
    308             }
    309 
    310             if (thisNode->type != NodeType::kText) {
    311                 nodeStack.push(thisNode);
    312             }
    313         }
    314     }
    315     return std::move(root);
    316 }
    317 
    318 Node::Node(NodeType type) : type(type), parent(nullptr), lineNumber(0), columnNumber(0) {
    319 }
    320 
    321 void Node::addChild(std::unique_ptr<Node> child) {
    322     child->parent = this;
    323     children.push_back(std::move(child));
    324 }
    325 
    326 Namespace::Namespace() : BaseNode(NodeType::kNamespace) {
    327 }
    328 
    329 std::unique_ptr<Node> Namespace::clone() const {
    330     Namespace* ns = new Namespace();
    331     ns->lineNumber = lineNumber;
    332     ns->columnNumber = columnNumber;
    333     ns->comment = comment;
    334     ns->namespacePrefix = namespacePrefix;
    335     ns->namespaceUri = namespaceUri;
    336     for (auto& child : children) {
    337         ns->addChild(child->clone());
    338     }
    339     return std::unique_ptr<Node>(ns);
    340 }
    341 
    342 Element::Element() : BaseNode(NodeType::kElement) {
    343 }
    344 
    345 std::unique_ptr<Node> Element::clone() const {
    346     Element* el = new Element();
    347     el->lineNumber = lineNumber;
    348     el->columnNumber = columnNumber;
    349     el->comment = comment;
    350     el->namespaceUri = namespaceUri;
    351     el->name = name;
    352     el->attributes = attributes;
    353     for (auto& child : children) {
    354         el->addChild(child->clone());
    355     }
    356     return std::unique_ptr<Node>(el);
    357 }
    358 
    359 Attribute* Element::findAttribute(const StringPiece16& ns, const StringPiece16& name) {
    360     for (auto& attr : attributes) {
    361         if (ns == attr.namespaceUri && name == attr.name) {
    362             return &attr;
    363         }
    364     }
    365     return nullptr;
    366 }
    367 
    368 Element* Element::findChild(const StringPiece16& ns, const StringPiece16& name) {
    369     return findChildWithAttribute(ns, name, nullptr);
    370 }
    371 
    372 Element* Element::findChildWithAttribute(const StringPiece16& ns, const StringPiece16& name,
    373                                          const Attribute* reqAttr) {
    374     for (auto& childNode : children) {
    375         Node* child = childNode.get();
    376         while (child->type == NodeType::kNamespace) {
    377             if (child->children.empty()) {
    378                 break;
    379             }
    380             child = child->children[0].get();
    381         }
    382 
    383         if (child->type == NodeType::kElement) {
    384             Element* el = static_cast<Element*>(child);
    385             if (ns == el->namespaceUri && name == el->name) {
    386                 if (!reqAttr) {
    387                     return el;
    388                 }
    389 
    390                 Attribute* attrName = el->findAttribute(reqAttr->namespaceUri, reqAttr->name);
    391                 if (attrName && attrName->value == reqAttr->value) {
    392                     return el;
    393                 }
    394             }
    395         }
    396     }
    397     return nullptr;
    398 }
    399 
    400 std::vector<Element*> Element::getChildElements() {
    401     std::vector<Element*> elements;
    402     for (auto& childNode : children) {
    403         Node* child = childNode.get();
    404         while (child->type == NodeType::kNamespace) {
    405             if (child->children.empty()) {
    406                 break;
    407             }
    408             child = child->children[0].get();
    409         }
    410 
    411         if (child->type == NodeType::kElement) {
    412             elements.push_back(static_cast<Element*>(child));
    413         }
    414     }
    415     return elements;
    416 }
    417 
    418 Text::Text() : BaseNode(NodeType::kText) {
    419 }
    420 
    421 std::unique_ptr<Node> Text::clone() const {
    422     Text* el = new Text();
    423     el->lineNumber = lineNumber;
    424     el->columnNumber = columnNumber;
    425     el->comment = comment;
    426     el->text = text;
    427     return std::unique_ptr<Node>(el);
    428 }
    429 
    430 } // namespace xml
    431 } // namespace aapt
    432