• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 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 AAPT2_DUMP_H
18 #define AAPT2_DUMP_H
19 
20 #include <androidfw/FileStream.h>
21 #include <io/ZipArchive.h>
22 
23 #include "Command.h"
24 #include "Debug.h"
25 #include "LoadedApk.h"
26 #include "dump/DumpManifest.h"
27 
28 namespace aapt {
29 
30 /**
31  * The base command for dumping information about apks. When the command is executed, the command
32  * performs the DumpApkCommand::Dump() operation on each apk provided as a file argument.
33  **/
34 class DumpApkCommand : public Command {
35  public:
DumpApkCommand(const std::string && name,text::Printer * printer,android::IDiagnostics * diag)36   explicit DumpApkCommand(const std::string&& name, text::Printer* printer,
37                           android::IDiagnostics* diag)
38       : Command(name), printer_(printer), diag_(diag) {
39     SetDescription("Dump information about an APK or APC.");
40   }
41 
GetPrinter()42   text::Printer* GetPrinter() {
43     return printer_;
44   }
45 
GetDiagnostics()46   android::IDiagnostics* GetDiagnostics() {
47     return diag_;
48   }
49 
GetPackageName(LoadedApk * apk)50   std::optional<std::string> GetPackageName(LoadedApk* apk) {
51     xml::Element* manifest_el = apk->GetManifest()->root.get();
52     if (!manifest_el) {
53       GetDiagnostics()->Error(android::DiagMessage() << "No AndroidManifest.");
54       return {};
55     }
56 
57     xml::Attribute* attr = manifest_el->FindAttribute({}, "package");
58     if (!attr) {
59       GetDiagnostics()->Error(android::DiagMessage() << "No package name.");
60       return {};
61     }
62     return attr->value;
63   }
64 
65   /** Perform the dump operation on the apk. */
66   virtual int Dump(LoadedApk* apk) = 0;
67 
Action(const std::vector<std::string> & args)68   int Action(const std::vector<std::string>& args) final {
69     if (args.size() < 1) {
70       diag_->Error(android::DiagMessage() << "No dump apk specified.");
71       return 1;
72     }
73 
74     bool error = false;
75     for (auto apk : args) {
76       auto loaded_apk = LoadedApk::LoadApkFromPath(apk, diag_);
77       if (!loaded_apk) {
78         error = true;
79         continue;
80       }
81 
82       error |= Dump(loaded_apk.get());
83     }
84 
85     return error;
86   }
87 
88  private:
89   text::Printer* printer_;
90   android::IDiagnostics* diag_;
91 };
92 
93 /** Command that prints contents of files generated from the compilation stage. */
94 class DumpAPCCommand : public Command {
95  public:
DumpAPCCommand(text::Printer * printer,android::IDiagnostics * diag)96   explicit DumpAPCCommand(text::Printer* printer, android::IDiagnostics* diag)
97       : Command("apc"), printer_(printer), diag_(diag) {
98     SetDescription("Print the contents of the AAPT2 Container (APC) generated fom compilation.");
99     AddOptionalSwitch("--no-values", "Suppresses output of values when displaying resource tables.",
100                       &no_values_);
101     AddOptionalSwitch("-v", "Enables verbose logging.", &verbose_);
102   }
103 
104   int Action(const std::vector<std::string>& args) override;
105 
106  private:
107   text::Printer* printer_;
108   android::IDiagnostics* diag_;
109   bool no_values_ = false;
110   bool verbose_ = false;
111 };
112 
113 /** Easter egg command shown when users enter "badger" instead of "badging". */
114 class DumpBadgerCommand : public Command {
115  public:
DumpBadgerCommand(text::Printer * printer)116   explicit DumpBadgerCommand(text::Printer* printer) : Command("badger"), printer_(printer) {
117   }
118 
119   int Action(const std::vector<std::string>& args) override;
120 
121  private:
122   text::Printer* printer_;
123   const static char kBadgerData[2925];
124 };
125 
126 class DumpBadgingCommand : public DumpApkCommand {
127  public:
DumpBadgingCommand(text::Printer * printer,android::IDiagnostics * diag)128   explicit DumpBadgingCommand(text::Printer* printer, android::IDiagnostics* diag)
129       : DumpApkCommand("badging", printer, diag) {
130     SetDescription("Print information extracted from the manifest of the APK.");
131     AddOptionalSwitch("--include-meta-data", "Include meta-data information.",
132                       &options_.include_meta_data);
133   }
134 
SetIncludeMetaData(bool value)135   void SetIncludeMetaData(bool value) {
136     options_.include_meta_data = value;
137   }
138 
SetOnlyPermissions(bool value)139   void SetOnlyPermissions(bool value) {
140     options_.only_permissions = value;
141   }
142 
Dump(LoadedApk * apk)143   int Dump(LoadedApk* apk) override {
144     return DumpManifest(apk, options_, GetPrinter(), GetDiagnostics());
145   }
146 
147  private:
148   DumpManifestOptions options_;
149 };
150 
151 class DumpConfigsCommand : public DumpApkCommand {
152  public:
DumpConfigsCommand(text::Printer * printer,android::IDiagnostics * diag)153   explicit DumpConfigsCommand(text::Printer* printer, android::IDiagnostics* diag)
154       : DumpApkCommand("configurations", printer, diag) {
155     SetDescription("Print every configuration used by a resource in the APK.");
156   }
157 
158   int Dump(LoadedApk* apk) override;
159 };
160 
161 class DumpPackageNameCommand : public DumpApkCommand {
162  public:
DumpPackageNameCommand(text::Printer * printer,android::IDiagnostics * diag)163   explicit DumpPackageNameCommand(text::Printer* printer, android::IDiagnostics* diag)
164       : DumpApkCommand("packagename", printer, diag) {
165     SetDescription("Print the package name of the APK.");
166   }
167 
168   int Dump(LoadedApk* apk) override;
169 };
170 
171 class DumpPermissionsCommand : public DumpApkCommand {
172  public:
DumpPermissionsCommand(text::Printer * printer,android::IDiagnostics * diag)173   explicit DumpPermissionsCommand(text::Printer* printer, android::IDiagnostics* diag)
174       : DumpApkCommand("permissions", printer, diag) {
175     SetDescription("Print the permissions extracted from the manifest of the APK.");
176   }
177 
Dump(LoadedApk * apk)178   int Dump(LoadedApk* apk) override {
179     DumpManifestOptions options;
180     options.only_permissions = true;
181     return DumpManifest(apk, options, GetPrinter(), GetDiagnostics());
182   }
183 };
184 
185 class DumpStringsCommand : public DumpApkCommand {
186  public:
DumpStringsCommand(text::Printer * printer,android::IDiagnostics * diag)187   explicit DumpStringsCommand(text::Printer* printer, android::IDiagnostics* diag)
188       : DumpApkCommand("strings", printer, diag) {
189     SetDescription("Print the contents of the resource table string pool in the APK.");
190   }
191 
192   int Dump(LoadedApk* apk) override;
193 };
194 
195 /** Prints the graph of parents of a style in an APK. */
196 class DumpStyleParentCommand : public DumpApkCommand {
197  public:
DumpStyleParentCommand(text::Printer * printer,android::IDiagnostics * diag)198   explicit DumpStyleParentCommand(text::Printer* printer, android::IDiagnostics* diag)
199       : DumpApkCommand("styleparents", printer, diag) {
200     SetDescription("Print the parents of a style in an APK.");
201     AddRequiredFlag("--style", "The name of the style to print", &style_);
202   }
203 
204   int Dump(LoadedApk* apk) override;
205 
206  private:
207   std::string style_;
208 };
209 
210 class DumpTableCommand : public DumpApkCommand {
211  public:
DumpTableCommand(text::Printer * printer,android::IDiagnostics * diag)212   explicit DumpTableCommand(text::Printer* printer, android::IDiagnostics* diag)
213       : DumpApkCommand("resources", printer, diag) {
214     SetDescription("Print the contents of the resource table from the APK.");
215     AddOptionalSwitch("--no-values", "Suppresses output of values when displaying resource tables.",
216                       &no_values_);
217     AddOptionalSwitch("-v", "Enables verbose logging.", &verbose_);
218   }
219 
220   int Dump(LoadedApk* apk) override;
221 
222  private:
223   bool no_values_ = false;
224   bool verbose_ = false;
225 };
226 
227 class DumpXmlStringsCommand : public DumpApkCommand {
228  public:
DumpXmlStringsCommand(text::Printer * printer,android::IDiagnostics * diag)229   explicit DumpXmlStringsCommand(text::Printer* printer, android::IDiagnostics* diag)
230       : DumpApkCommand("xmlstrings", printer, diag) {
231     SetDescription("Print the string pool of a compiled xml in an APK.");
232     AddRequiredFlagList("--file", "A compiled xml file to print", &files_);
233   }
234 
235   int Dump(LoadedApk* apk) override;
236 
237  private:
238   std::vector<std::string> files_;
239 };
240 
241 class DumpChunks : public DumpApkCommand {
242  public:
DumpChunks(text::Printer * printer,android::IDiagnostics * diag)243   DumpChunks(text::Printer* printer, android::IDiagnostics* diag)
244       : DumpApkCommand("chunks", printer, diag) {
245     SetDescription("Print the chunk information of the compiled resources.arsc in the APK.");
246   }
247 
248   int Dump(LoadedApk* apk) override;
249 };
250 
251 /** Prints the tree of a compiled xml in an APK. */
252 class DumpXmlTreeCommand : public DumpApkCommand {
253  public:
DumpXmlTreeCommand(text::Printer * printer,android::IDiagnostics * diag)254   explicit DumpXmlTreeCommand(text::Printer* printer, android::IDiagnostics* diag)
255       : DumpApkCommand("xmltree", printer, diag) {
256     SetDescription("Print the tree of a compiled xml in an APK.");
257     AddRequiredFlagList("--file", "A compiled xml file to print", &files_);
258   }
259 
260   int Dump(LoadedApk* apk) override;
261 
262  private:
263   std::vector<std::string> files_;
264 };
265 
266 class DumpOverlayableCommand : public DumpApkCommand {
267  public:
DumpOverlayableCommand(text::Printer * printer,android::IDiagnostics * diag)268   explicit DumpOverlayableCommand(text::Printer* printer, android::IDiagnostics* diag)
269       : DumpApkCommand("overlayable", printer, diag) {
270     SetDescription("Print the <overlayable> resources of an APK.");
271   }
272 
273   int Dump(LoadedApk* apk) override;
274 };
275 
276 /** The default dump command. Performs no action because a subcommand is required. */
277 class DumpCommand : public Command {
278  public:
DumpCommand(text::Printer * printer,android::IDiagnostics * diag)279   explicit DumpCommand(text::Printer* printer, android::IDiagnostics* diag)
280       : Command("dump", "d"), diag_(diag) {
281     AddOptionalSubcommand(util::make_unique<DumpAPCCommand>(printer, diag_));
282     AddOptionalSubcommand(util::make_unique<DumpBadgingCommand>(printer, diag_));
283     AddOptionalSubcommand(util::make_unique<DumpConfigsCommand>(printer, diag_));
284     AddOptionalSubcommand(util::make_unique<DumpPackageNameCommand>(printer, diag_));
285     AddOptionalSubcommand(util::make_unique<DumpPermissionsCommand>(printer, diag_));
286     AddOptionalSubcommand(util::make_unique<DumpStringsCommand>(printer, diag_));
287     AddOptionalSubcommand(util::make_unique<DumpStyleParentCommand>(printer, diag_));
288     AddOptionalSubcommand(util::make_unique<DumpTableCommand>(printer, diag_));
289     AddOptionalSubcommand(util::make_unique<DumpChunks>(printer, diag_));
290     AddOptionalSubcommand(util::make_unique<DumpXmlStringsCommand>(printer, diag_));
291     AddOptionalSubcommand(util::make_unique<DumpXmlTreeCommand>(printer, diag_));
292     AddOptionalSubcommand(util::make_unique<DumpOverlayableCommand>(printer, diag_));
293     AddOptionalSubcommand(util::make_unique<DumpBadgerCommand>(printer), /* hidden */ true);
294   }
295 
Action(const std::vector<std::string> & args)296   int Action(const std::vector<std::string>& args) override {
297     if (args.size() == 0) {
298       diag_->Error(android::DiagMessage() << "no subcommand specified");
299     } else {
300       diag_->Error(android::DiagMessage() << "unknown subcommand '" << args[0] << "'");
301     }
302     Usage(&std::cerr);
303     return 1;
304   }
305 
306  private:
307   android::IDiagnostics* diag_;
308 };
309 
310 }  // namespace aapt
311 
312 #endif  // AAPT2_DUMP_H
313