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 "AppInfo.h"
18 #include "Logger.h"
19 #include "ManifestParser.h"
20 #include "Source.h"
21 #include "XmlPullParser.h"
22 
23 #include <string>
24 
25 namespace aapt {
26 
parse(const Source & source,std::shared_ptr<XmlPullParser> parser,AppInfo * outInfo)27 bool ManifestParser::parse(const Source& source, std::shared_ptr<XmlPullParser> parser,
28                            AppInfo* outInfo) {
29     SourceLogger logger = { source };
30 
31     int depth = 0;
32     while (XmlPullParser::isGoodEvent(parser->next())) {
33         XmlPullParser::Event event = parser->getEvent();
34         if (event == XmlPullParser::Event::kEndElement) {
35             depth--;
36             continue;
37         } else if (event != XmlPullParser::Event::kStartElement) {
38             continue;
39         }
40 
41         depth++;
42 
43         const std::u16string& element = parser->getElementName();
44         if (depth == 1) {
45             if (element == u"manifest") {
46                 if (!parseManifest(logger, parser, outInfo)) {
47                     return false;
48                 }
49             } else {
50                 logger.error()
51                         << "unexpected top-level element '"
52                         << element
53                         << "'."
54                         << std::endl;
55                 return false;
56             }
57         } else {
58             XmlPullParser::skipCurrentElement(parser.get());
59         }
60     }
61 
62     if (parser->getEvent() == XmlPullParser::Event::kBadDocument) {
63             logger.error(parser->getLineNumber())
64                 << "failed to parse manifest: "
65                 << parser->getLastError()
66                 << "."
67                 << std::endl;
68         return false;
69     }
70     return true;
71 }
72 
parseManifest(SourceLogger & logger,std::shared_ptr<XmlPullParser> parser,AppInfo * outInfo)73 bool ManifestParser::parseManifest(SourceLogger& logger, std::shared_ptr<XmlPullParser> parser,
74                                    AppInfo* outInfo) {
75     auto attrIter = parser->findAttribute(u"", u"package");
76     if (attrIter == parser->endAttributes() || attrIter->value.empty()) {
77         logger.error() << "no 'package' attribute found for element <manifest>." << std::endl;
78         return false;
79     }
80     outInfo->package = attrIter->value;
81     return true;
82 }
83 
84 } // namespace aapt
85