blob: 0a1e021aef6b24e230b8c3085cf510eb754f8848 [file] [log] [blame]
Adam Lesinski59e04c62016-02-04 15:59:23 -08001/*
2 * Copyright (C) 2016 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
Ryan Mitchell833a1a62018-07-10 13:51:36 -070017#include "Dump.h"
18
Adam Lesinski93190b72017-11-03 15:20:17 -070019#include <cinttypes>
Adam Lesinskice5e56e2016-10-21 17:56:45 -070020#include <vector>
21
Adam Lesinski93190b72017-11-03 15:20:17 -070022#include "android-base/stringprintf.h"
MÃ¥rten Kongstad24c9aa62018-06-20 08:46:41 +020023#include "androidfw/ConfigDescription.h"
Adam Lesinskid5083f62017-01-16 15:07:21 -080024#include "androidfw/StringPiece.h"
25
Adam Lesinski59e04c62016-02-04 15:59:23 -080026#include "Debug.h"
27#include "Diagnostics.h"
Ryan Mitchell5d275512018-07-19 14:29:00 -070028#include "LoadedApk.h"
29#include "Util.h"
Adam Lesinski00451162017-10-03 07:44:08 -070030#include "format/Container.h"
Adam Lesinski46708052017-09-29 14:49:15 -070031#include "format/binary/BinaryResourceParser.h"
Ryan Mitchell5d275512018-07-19 14:29:00 -070032#include "format/binary/XmlFlattener.h"
Adam Lesinski46708052017-09-29 14:49:15 -070033#include "format/proto/ProtoDeserialize.h"
Adam Lesinski00451162017-10-03 07:44:08 -070034#include "io/FileStream.h"
Adam Lesinski64587af2016-02-18 18:33:06 -080035#include "io/ZipArchive.h"
Adam Lesinski59e04c62016-02-04 15:59:23 -080036#include "process/IResourceTableConsumer.h"
Adam Lesinski93190b72017-11-03 15:20:17 -070037#include "text/Printer.h"
Adam Lesinski59e04c62016-02-04 15:59:23 -080038#include "util/Files.h"
Adam Lesinskid5083f62017-01-16 15:07:21 -080039
Adam Lesinski93190b72017-11-03 15:20:17 -070040using ::aapt::text::Printer;
Adam Lesinski4ffea042017-08-10 15:37:28 -070041using ::android::StringPiece;
Adam Lesinski93190b72017-11-03 15:20:17 -070042using ::android::base::StringPrintf;
Adam Lesinski59e04c62016-02-04 15:59:23 -080043
Adam Lesinski59e04c62016-02-04 15:59:23 -080044namespace aapt {
45
Adam Lesinski00451162017-10-03 07:44:08 -070046static const char* ResourceFileTypeToString(const ResourceFile::Type& type) {
47 switch (type) {
48 case ResourceFile::Type::kPng:
49 return "PNG";
50 case ResourceFile::Type::kBinaryXml:
51 return "BINARY_XML";
52 case ResourceFile::Type::kProtoXml:
53 return "PROTO_XML";
54 default:
55 break;
Adam Lesinskicacb28f2016-10-19 12:18:14 -070056 }
Adam Lesinski00451162017-10-03 07:44:08 -070057 return "UNKNOWN";
Adam Lesinski59e04c62016-02-04 15:59:23 -080058}
59
Adam Lesinski00451162017-10-03 07:44:08 -070060static void DumpCompiledFile(const ResourceFile& file, const Source& source, off64_t offset,
Adam Lesinski93190b72017-11-03 15:20:17 -070061 size_t len, Printer* printer) {
62 printer->Print("Resource: ");
63 printer->Println(file.name.to_string());
64
65 printer->Print("Config: ");
66 printer->Println(file.config.to_string());
67
68 printer->Print("Source: ");
69 printer->Println(file.source.to_string());
70
71 printer->Print("Type: ");
72 printer->Println(ResourceFileTypeToString(file.type));
73
74 printer->Println(StringPrintf("Data: offset=%" PRIi64 " length=%zd", offset, len));
Adam Lesinski00451162017-10-03 07:44:08 -070075}
76
Adam Lesinski00451162017-10-03 07:44:08 -070077namespace {
78
Adam Lesinski59e04c62016-02-04 15:59:23 -080079class DumpContext : public IAaptContext {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070080 public:
Adam Lesinskib522f042017-04-21 16:57:59 -070081 PackageType GetPackageType() override {
82 // Doesn't matter.
83 return PackageType::kApp;
84 }
85
Adam Lesinskid0f492d2017-04-03 18:12:45 -070086 IDiagnostics* GetDiagnostics() override {
87 return &diagnostics_;
88 }
Adam Lesinski59e04c62016-02-04 15:59:23 -080089
Adam Lesinskice5e56e2016-10-21 17:56:45 -070090 NameMangler* GetNameMangler() override {
Adam Lesinski00451162017-10-03 07:44:08 -070091 UNIMPLEMENTED(FATAL);
Adam Lesinskicacb28f2016-10-19 12:18:14 -070092 return nullptr;
93 }
Adam Lesinski59e04c62016-02-04 15:59:23 -080094
Adam Lesinskice5e56e2016-10-21 17:56:45 -070095 const std::string& GetCompilationPackage() override {
Adam Lesinskicacb28f2016-10-19 12:18:14 -070096 static std::string empty;
97 return empty;
98 }
Adam Lesinski59e04c62016-02-04 15:59:23 -080099
Adam Lesinskid0f492d2017-04-03 18:12:45 -0700100 uint8_t GetPackageId() override {
101 return 0;
102 }
Adam Lesinski59e04c62016-02-04 15:59:23 -0800103
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700104 SymbolTable* GetExternalSymbols() override {
Adam Lesinski00451162017-10-03 07:44:08 -0700105 UNIMPLEMENTED(FATAL);
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700106 return nullptr;
107 }
Adam Lesinski59e04c62016-02-04 15:59:23 -0800108
Adam Lesinskid0f492d2017-04-03 18:12:45 -0700109 bool IsVerbose() override {
110 return verbose_;
111 }
Adam Lesinski355f2852016-02-13 20:26:45 -0800112
Adam Lesinskid0f492d2017-04-03 18:12:45 -0700113 void SetVerbose(bool val) {
114 verbose_ = val;
115 }
Adam Lesinski355f2852016-02-13 20:26:45 -0800116
Adam Lesinskid0f492d2017-04-03 18:12:45 -0700117 int GetMinSdkVersion() override {
118 return 0;
119 }
Adam Lesinskifb6312f2016-06-28 14:40:32 -0700120
Udam Sainib228df32019-06-18 16:50:34 -0700121 const std::set<std::string>& GetSplitNameDependencies() override {
122 UNIMPLEMENTED(FATAL) << "Split Name Dependencies should not be necessary";
123 static std::set<std::string> empty;
124 return empty;
125 }
126
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700127 private:
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700128 StdErrDiagnostics diagnostics_;
129 bool verbose_ = false;
Adam Lesinski59e04c62016-02-04 15:59:23 -0800130};
131
Adam Lesinski00451162017-10-03 07:44:08 -0700132} // namespace
133
Ryan Mitchell5d275512018-07-19 14:29:00 -0700134int DumpAPCCommand::Action(const std::vector<std::string>& args) {
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700135 DumpContext context;
Ryan Mitchell5d275512018-07-19 14:29:00 -0700136 DebugPrintTableOptions print_options;
137 print_options.show_sources = true;
138 print_options.show_values = !no_values_;
139
140 if (args.size() < 1) {
Ryan Mitchell214846d2018-09-19 16:57:01 -0700141 diag_->Error(DiagMessage() << "No dump container specified");
Ryan Mitchell5d275512018-07-19 14:29:00 -0700142 return 1;
143 }
144
Ryan Mitchell214846d2018-09-19 16:57:01 -0700145 bool error = false;
Ryan Mitchell5d275512018-07-19 14:29:00 -0700146 for (auto container : args) {
147 io::FileInputStream input(container);
148 if (input.HadError()) {
149 context.GetDiagnostics()->Error(DiagMessage(container)
Ryan Mitchell214846d2018-09-19 16:57:01 -0700150 << "failed to open file: " << input.GetError());
151 error = true;
152 continue;
Ryan Mitchell5d275512018-07-19 14:29:00 -0700153 }
154
155 // Try as a compiled file.
156 ContainerReader reader(&input);
157 if (reader.HadError()) {
158 context.GetDiagnostics()->Error(DiagMessage(container)
Ryan Mitchell214846d2018-09-19 16:57:01 -0700159 << "failed to read container: " << reader.GetError());
160 error = true;
161 continue;
Ryan Mitchell5d275512018-07-19 14:29:00 -0700162 }
163
Ryan Mitchell214846d2018-09-19 16:57:01 -0700164 printer_->Println("AAPT2 Container (APC)");
Ryan Mitchell5d275512018-07-19 14:29:00 -0700165 ContainerReaderEntry* entry;
166 std::string error;
167 while ((entry = reader.Next()) != nullptr) {
168 if (entry->Type() == ContainerEntryType::kResTable) {
Ryan Mitchell214846d2018-09-19 16:57:01 -0700169 printer_->Println("kResTable");
Ryan Mitchell5d275512018-07-19 14:29:00 -0700170
171 pb::ResourceTable pb_table;
172 if (!entry->GetResTable(&pb_table)) {
173 context.GetDiagnostics()->Error(DiagMessage(container)
Ryan Mitchell214846d2018-09-19 16:57:01 -0700174 << "failed to parse proto table: " << entry->GetError());
175 error = true;
Ryan Mitchell5d275512018-07-19 14:29:00 -0700176 continue;
177 }
178
179 ResourceTable table;
180 error.clear();
181 if (!DeserializeTableFromPb(pb_table, nullptr /*files*/, &table, &error)) {
182 context.GetDiagnostics()->Error(DiagMessage(container)
Ryan Mitchell214846d2018-09-19 16:57:01 -0700183 << "failed to parse table: " << error);
184 error = true;
Ryan Mitchell5d275512018-07-19 14:29:00 -0700185 continue;
186 }
187
Ryan Mitchell214846d2018-09-19 16:57:01 -0700188 printer_->Indent();
189 Debug::PrintTable(table, print_options, printer_);
190 printer_->Undent();
Ryan Mitchell5d275512018-07-19 14:29:00 -0700191 } else if (entry->Type() == ContainerEntryType::kResFile) {
Ryan Mitchell214846d2018-09-19 16:57:01 -0700192 printer_->Println("kResFile");
Ryan Mitchell5d275512018-07-19 14:29:00 -0700193 pb::internal::CompiledFile pb_compiled_file;
194 off64_t offset;
195 size_t length;
196 if (!entry->GetResFileOffsets(&pb_compiled_file, &offset, &length)) {
Ryan Mitchell214846d2018-09-19 16:57:01 -0700197 context.GetDiagnostics()->Error(DiagMessage(container)
198 << "failed to parse compiled proto file: "
199 << entry->GetError());
200 error = true;
Ryan Mitchell5d275512018-07-19 14:29:00 -0700201 continue;
202 }
203
204 ResourceFile file;
205 if (!DeserializeCompiledFileFromPb(pb_compiled_file, &file, &error)) {
206 context.GetDiagnostics()->Warn(DiagMessage(container)
Ryan Mitchell214846d2018-09-19 16:57:01 -0700207 << "failed to parse compiled file: " << error);
208 error = true;
Ryan Mitchell5d275512018-07-19 14:29:00 -0700209 continue;
210 }
211
Ryan Mitchell214846d2018-09-19 16:57:01 -0700212 printer_->Indent();
213 DumpCompiledFile(file, Source(container), offset, length, printer_);
214 printer_->Undent();
Ryan Mitchell5d275512018-07-19 14:29:00 -0700215 }
Pierre Lecesneaadf27e2017-05-05 14:58:21 +0100216 }
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700217 }
Ryan Mitchell5d275512018-07-19 14:29:00 -0700218
Ryan Mitchell214846d2018-09-19 16:57:01 -0700219 return (error) ? 1 : 0;
Adam Lesinski59e04c62016-02-04 15:59:23 -0800220}
221
Ryan Mitchell214846d2018-09-19 16:57:01 -0700222int DumpBadgerCommand::Action(const std::vector<std::string>& args) {
223 printer_->Print(StringPrintf("%s", kBadgerData));
224 printer_->Print("Did you mean \"aapt2 dump badging\"?\n");
225 return 1;
226}
Ryan Mitchell5d275512018-07-19 14:29:00 -0700227
Ryan Mitchell214846d2018-09-19 16:57:01 -0700228int DumpConfigsCommand::Dump(LoadedApk* apk) {
229 ResourceTable* table = apk->GetResourceTable();
Ryan Mitchellfc225b22018-08-21 14:52:51 -0700230 if (!table) {
Ryan Mitchell214846d2018-09-19 16:57:01 -0700231 GetDiagnostics()->Error(DiagMessage() << "Failed to retrieve resource table");
Ryan Mitchellfc225b22018-08-21 14:52:51 -0700232 return 1;
233 }
234
Ryan Mitchell5d275512018-07-19 14:29:00 -0700235 // Comparison function used to order configurations
MÃ¥rten Kongstad24c9aa62018-06-20 08:46:41 +0200236 auto compare = [](android::ConfigDescription c1, android::ConfigDescription c2) -> bool {
Ryan Mitchell214846d2018-09-19 16:57:01 -0700237 return c1.compare(c2) < 0;
Ryan Mitchell5d275512018-07-19 14:29:00 -0700238 };
239
240 // Insert the configurations into a set in order to keep every configuarion seen
MÃ¥rten Kongstad24c9aa62018-06-20 08:46:41 +0200241 std::set<android::ConfigDescription, decltype(compare)> configs(compare);
Ryan Mitchellfc225b22018-08-21 14:52:51 -0700242 for (auto& package : table->packages) {
Ryan Mitchell5d275512018-07-19 14:29:00 -0700243 for (auto& type : package->types) {
244 for (auto& entry : type->entries) {
245 for (auto& value : entry->values) {
246 configs.insert(value->config);
247 }
248 }
249 }
250 }
251
252 // Print the configurations in order
253 for (auto& config : configs) {
Ryan Mitchell214846d2018-09-19 16:57:01 -0700254 GetPrinter()->Print(StringPrintf("%s\n", config.to_string().data()));
Ryan Mitchell5d275512018-07-19 14:29:00 -0700255 }
Ryan Mitchell5d275512018-07-19 14:29:00 -0700256 return 0;
257}
258
Ryan Mitchell214846d2018-09-19 16:57:01 -0700259int DumpPackageNameCommand::Dump(LoadedApk* apk) {
Ryan Mitchell4382e442021-07-14 12:53:01 -0700260 auto package_name = GetPackageName(apk);
261 if (!package_name.has_value()) {
Ryan Mitchell5d275512018-07-19 14:29:00 -0700262 return 1;
263 }
Ryan Mitchell4382e442021-07-14 12:53:01 -0700264 GetPrinter()->Println(*package_name);
Ryan Mitchell5d275512018-07-19 14:29:00 -0700265 return 0;
266}
267
Ryan Mitchell214846d2018-09-19 16:57:01 -0700268int DumpStringsCommand::Dump(LoadedApk* apk) {
269 ResourceTable* table = apk->GetResourceTable();
270 if (!table) {
271 GetDiagnostics()->Error(DiagMessage() << "Failed to retrieve resource table");
Ryan Mitchell5d275512018-07-19 14:29:00 -0700272 return 1;
273 }
274
Ryan Mitchell214846d2018-09-19 16:57:01 -0700275 // Load the run-time xml string pool using the flattened data
276 BigBuffer buffer(4096);
277 StringPool::FlattenUtf8(&buffer, table->string_pool, GetDiagnostics());
278 auto data = buffer.to_string();
279 android::ResStringPool pool(data.data(), data.size(), false);
280 Debug::DumpResStringPool(&pool, GetPrinter());
281 return 0;
282}
283
Aurimas Liutikas13e6a1d2018-09-25 16:11:40 -0700284int DumpStyleParentCommand::Dump(LoadedApk* apk) {
Ryan Mitchell4382e442021-07-14 12:53:01 -0700285 auto package_name = GetPackageName(apk);
286 if (!package_name.has_value()) {
Aurimas Liutikas13e6a1d2018-09-25 16:11:40 -0700287 return 1;
288 }
289
Ryan Mitchell4382e442021-07-14 12:53:01 -0700290 const auto target_style = ResourceName(*package_name, ResourceType::kStyle, style_);
Aurimas Liutikas13e6a1d2018-09-25 16:11:40 -0700291 const auto table = apk->GetResourceTable();
292
293 if (!table) {
294 GetDiagnostics()->Error(DiagMessage() << "Failed to retrieve resource table");
295 return 1;
296 }
297
Ryan Mitchell4382e442021-07-14 12:53:01 -0700298 std::optional<ResourceTable::SearchResult> target = table->FindResource(target_style);
Aurimas Liutikas13e6a1d2018-09-25 16:11:40 -0700299 if (!target) {
300 GetDiagnostics()->Error(
301 DiagMessage() << "Target style \"" << target_style.entry << "\" does not exist");
302 return 1;
303 }
304
305 Debug::PrintStyleGraph(table, target_style);
306 return 0;
307}
308
Ryan Mitchell214846d2018-09-19 16:57:01 -0700309int DumpTableCommand::Dump(LoadedApk* apk) {
310 if (apk->GetApkFormat() == ApkFormat::kProto) {
311 GetPrinter()->Println("Proto APK");
312 } else {
313 GetPrinter()->Println("Binary APK");
314 }
315
316 ResourceTable* table = apk->GetResourceTable();
317 if (!table) {
318 GetDiagnostics()->Error(DiagMessage() << "Failed to retrieve resource table");
319 return 1;
320 }
Ryan Mitchell5d275512018-07-19 14:29:00 -0700321
322 DebugPrintTableOptions print_options;
323 print_options.show_sources = true;
324 print_options.show_values = !no_values_;
Ryan Mitchell214846d2018-09-19 16:57:01 -0700325 Debug::PrintTable(*table, print_options, GetPrinter());
Ryan Mitchell5d275512018-07-19 14:29:00 -0700326 return 0;
327}
328
Ryan Mitchell214846d2018-09-19 16:57:01 -0700329int DumpXmlStringsCommand::Dump(LoadedApk* apk) {
Ryan Mitchell5d275512018-07-19 14:29:00 -0700330 DumpContext context;
Ryan Mitchell214846d2018-09-19 16:57:01 -0700331 bool error = false;
Ryan Mitchell5d275512018-07-19 14:29:00 -0700332 for (auto xml_file : files_) {
333 android::ResXMLTree tree;
334
Ryan Mitchell214846d2018-09-19 16:57:01 -0700335 if (apk->GetApkFormat() == ApkFormat::kProto) {
336 auto xml = apk->LoadXml(xml_file, GetDiagnostics());
Ryan Mitchell5d275512018-07-19 14:29:00 -0700337 if (!xml) {
Ryan Mitchell214846d2018-09-19 16:57:01 -0700338 error = true;
339 continue;
Ryan Mitchell5d275512018-07-19 14:29:00 -0700340 }
341
342 // Flatten the xml document to get a binary representation of the proto xml file
343 BigBuffer buffer(4096);
344 XmlFlattenerOptions options = {};
345 options.keep_raw_values = true;
346 XmlFlattener flattener(&buffer, options);
347 if (!flattener.Consume(&context, xml.get())) {
Ryan Mitchell214846d2018-09-19 16:57:01 -0700348 error = true;
349 continue;
Ryan Mitchell5d275512018-07-19 14:29:00 -0700350 }
351
352 // Load the run-time xml tree using the flattened data
353 std::string data = buffer.to_string();
354 tree.setTo(data.data(), data.size(), /** copyData */ true);
355
Ryan Mitchell214846d2018-09-19 16:57:01 -0700356 } else if (apk->GetApkFormat() == ApkFormat::kBinary) {
357 io::IFile* file = apk->GetFileCollection()->FindFile(xml_file);
Ryan Mitchell5d275512018-07-19 14:29:00 -0700358 if (!file) {
Ryan Mitchell214846d2018-09-19 16:57:01 -0700359 GetDiagnostics()->Error(DiagMessage(xml_file)
360 << "File '" << xml_file << "' not found in APK");
361 error = true;
362 continue;
Ryan Mitchell5d275512018-07-19 14:29:00 -0700363 }
364
365 std::unique_ptr<io::IData> data = file->OpenAsData();
366 if (!data) {
Ryan Mitchell214846d2018-09-19 16:57:01 -0700367 GetDiagnostics()->Error(DiagMessage() << "Failed to open " << xml_file);
368 error = true;
369 continue;
Ryan Mitchell5d275512018-07-19 14:29:00 -0700370 }
371
372 // Load the run-time xml tree from the file data
373 tree.setTo(data->data(), data->size(), /** copyData */ true);
Ryan Mitchell214846d2018-09-19 16:57:01 -0700374 } else {
375 GetDiagnostics()->Error(DiagMessage(apk->GetSource()) << "Unknown APK format");
376 error = true;
377 continue;
Ryan Mitchell5d275512018-07-19 14:29:00 -0700378 }
379
Ryan Mitchell214846d2018-09-19 16:57:01 -0700380 Debug::DumpResStringPool(&tree.getStrings(), GetPrinter());
Ryan Mitchell5d275512018-07-19 14:29:00 -0700381 }
Ryan Mitchell214846d2018-09-19 16:57:01 -0700382 return (error) ? 1 : 0;
383}
Ryan Mitchell5d275512018-07-19 14:29:00 -0700384
Ryan Mitchell214846d2018-09-19 16:57:01 -0700385int DumpXmlTreeCommand::Dump(LoadedApk* apk) {
386 for (auto file : files_) {
387 auto xml = apk->LoadXml(file, GetDiagnostics());
388 if (!xml) {
389 return 1;
390 }
391 Debug::DumpXml(*xml, GetPrinter());
392 }
Ryan Mitchell5d275512018-07-19 14:29:00 -0700393 return 0;
394}
395
MÃ¥rten Kongstad1d3b64852019-09-17 13:02:32 +0200396int DumpOverlayableCommand::Dump(LoadedApk* apk) {
397 ResourceTable* table = apk->GetResourceTable();
398 if (!table) {
399 GetDiagnostics()->Error(DiagMessage() << "Failed to retrieve resource table");
400 return 1;
401 }
402
403 Debug::DumpOverlayable(*table, GetPrinter());
404 return 0;
405}
406
Ryan Mitchell214846d2018-09-19 16:57:01 -0700407const char DumpBadgerCommand::kBadgerData[2925] = {
408 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
409 32, 32, 32, 32, 32, 32, 95, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
410 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
411 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
412 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 61, 63, 86, 35, 40, 46, 46,
413 95, 95, 95, 95, 97, 97, 44, 32, 46, 124, 42, 33, 83, 62, 32, 32, 32, 32, 32,
414 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32,
415 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
416 32, 32, 58, 46, 58, 59, 61, 59, 61, 81, 81, 81, 81, 66, 96, 61, 61, 58, 46,
417 46, 46, 58, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
418 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
419 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 61, 59, 59, 59, 58, 106, 81, 81,
420 81, 81, 102, 59, 61, 59, 59, 61, 61, 61, 58, 46, 32, 32, 32, 32, 32, 32, 32,
421 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32,
422 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
423 61, 59, 59, 59, 58, 109, 81, 81, 81, 81, 61, 59, 59, 59, 59, 59, 58, 59, 59,
424 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
425 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
426 32, 32, 32, 32, 32, 32, 32, 46, 61, 59, 59, 59, 60, 81, 81, 81, 81, 87, 58,
427 59, 59, 59, 59, 59, 59, 61, 119, 44, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
428 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32,
429 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 47, 61, 59, 59,
430 58, 100, 81, 81, 81, 81, 35, 58, 59, 59, 59, 59, 59, 58, 121, 81, 91, 32, 32,
431 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32,
432 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
433 32, 32, 32, 46, 109, 58, 59, 59, 61, 81, 81, 81, 81, 81, 109, 58, 59, 59, 59,
434 59, 61, 109, 81, 81, 76, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
435 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
436 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 41, 87, 59, 61, 59, 41, 81, 81,
437 81, 81, 81, 81, 59, 61, 59, 59, 58, 109, 81, 81, 87, 39, 46, 32, 32, 32, 32,
438 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32,
439 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
440 60, 81, 91, 59, 59, 61, 81, 81, 81, 81, 81, 87, 43, 59, 58, 59, 60, 81, 81,
441 81, 76, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
442 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
443 32, 32, 32, 32, 32, 32, 32, 32, 32, 52, 91, 58, 45, 59, 87, 81, 81, 81, 81,
444 70, 58, 58, 58, 59, 106, 81, 81, 81, 91, 32, 32, 32, 32, 32, 32, 32, 32, 32,
445 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32,
446 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 93, 40,
447 32, 46, 59, 100, 81, 81, 81, 81, 40, 58, 46, 46, 58, 100, 81, 81, 68, 32, 32,
448 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
449 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 46, 46, 32, 46,
450 46, 46, 32, 46, 32, 46, 45, 91, 59, 61, 58, 109, 81, 81, 81, 87, 46, 58, 61,
451 59, 60, 81, 81, 80, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
452 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 46, 46,
453 61, 59, 61, 61, 61, 59, 61, 61, 59, 59, 59, 58, 58, 46, 46, 41, 58, 59, 58,
454 81, 81, 81, 81, 69, 58, 59, 59, 60, 81, 81, 68, 32, 32, 32, 32, 32, 32, 32,
455 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32,
456 32, 32, 32, 32, 58, 59, 61, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
457 59, 59, 61, 61, 46, 61, 59, 93, 81, 81, 81, 81, 107, 58, 59, 58, 109, 87, 68,
458 96, 32, 32, 32, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
459 32, 32, 32, 32, 32, 10, 32, 32, 32, 46, 60, 61, 61, 59, 59, 59, 59, 59, 59,
460 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 58, 58, 58, 115, 109, 68, 41, 36,
461 81, 109, 46, 61, 61, 81, 69, 96, 46, 58, 58, 46, 58, 46, 46, 32, 32, 32, 32,
462 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 46, 32, 95, 81, 67,
463 61, 61, 58, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
464 59, 59, 58, 68, 39, 61, 105, 61, 63, 81, 119, 58, 106, 80, 32, 58, 61, 59, 59,
465 61, 59, 61, 59, 61, 46, 95, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
466 32, 32, 10, 32, 32, 36, 81, 109, 105, 59, 61, 59, 59, 59, 59, 59, 59, 59, 59,
467 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 46, 58, 37, 73, 108, 108, 62, 52, 81,
468 109, 34, 32, 61, 59, 59, 59, 59, 59, 59, 59, 59, 59, 61, 59, 61, 61, 46, 46,
469 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 46, 45, 57, 101, 43, 43, 61,
470 61, 59, 59, 59, 59, 59, 59, 61, 59, 59, 59, 59, 59, 59, 59, 59, 59, 58, 97,
471 46, 61, 108, 62, 126, 58, 106, 80, 96, 46, 61, 61, 59, 59, 59, 59, 59, 59, 59,
472 59, 59, 59, 59, 59, 59, 61, 61, 97, 103, 97, 32, 32, 32, 32, 32, 32, 32, 10,
473 32, 32, 32, 32, 45, 46, 32, 46, 32, 32, 32, 32, 32, 32, 32, 32, 45, 45, 45,
474 58, 59, 59, 59, 59, 61, 119, 81, 97, 124, 105, 124, 124, 39, 126, 95, 119, 58, 61,
475 58, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 61, 119, 81, 81,
476 99, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
477 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 59, 59, 58, 106, 81, 81, 81, 109, 119,
478 119, 119, 109, 109, 81, 81, 122, 58, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59,
479 59, 59, 59, 58, 115, 81, 87, 81, 102, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32,
480 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 61, 58,
481 59, 61, 81, 81, 81, 81, 81, 81, 87, 87, 81, 81, 81, 81, 81, 58, 59, 59, 59,
482 59, 59, 59, 59, 59, 58, 45, 45, 45, 59, 59, 59, 41, 87, 66, 33, 32, 32, 32,
483 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
484 32, 32, 32, 32, 32, 32, 58, 59, 59, 93, 81, 81, 81, 81, 81, 81, 81, 81, 81,
485 81, 81, 81, 81, 40, 58, 59, 59, 59, 58, 45, 32, 46, 32, 32, 32, 32, 32, 46,
486 32, 126, 96, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32,
487 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 61, 59, 58, 81,
488 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 40, 58, 59, 59, 59, 58, 32,
489 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
490 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
491 32, 32, 32, 58, 59, 59, 58, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81,
492 81, 40, 58, 59, 59, 59, 46, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
493 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32,
494 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 61, 59, 60, 81, 81, 81, 81,
495 81, 81, 81, 81, 81, 81, 81, 81, 81, 59, 61, 59, 59, 61, 32, 32, 32, 32, 32,
496 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32,
497 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
498 58, 59, 59, 93, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 40, 59,
499 59, 59, 59, 32, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
500 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
501 32, 32, 32, 32, 32, 32, 32, 32, 58, 61, 58, 106, 81, 81, 81, 81, 81, 81, 81,
502 81, 81, 81, 81, 81, 81, 76, 58, 59, 59, 59, 32, 46, 32, 32, 32, 32, 32, 32,
503 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32,
504 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 61, 58, 58,
505 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 87, 58, 59, 59, 59, 59,
506 32, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
507 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
508 32, 32, 32, 32, 32, 58, 59, 61, 41, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81,
509 81, 81, 87, 59, 61, 58, 59, 59, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
510 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32,
511 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 61, 58, 61, 81, 81,
512 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 107, 58, 59, 59, 59, 59, 58, 32, 32,
513 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
514 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
515 32, 32, 58, 59, 59, 58, 51, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 102, 94,
516 59, 59, 59, 59, 59, 61, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
517 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
518 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 61, 59, 59, 59, 43, 63, 36, 81,
519 81, 81, 87, 64, 86, 102, 58, 59, 59, 59, 59, 59, 59, 59, 46, 32, 32, 32, 32,
520 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32,
521 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 61,
522 59, 59, 59, 59, 59, 59, 59, 43, 33, 58, 126, 126, 58, 59, 59, 59, 59, 59, 59,
523 59, 59, 59, 59, 32, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
524 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
525 32, 32, 32, 32, 32, 46, 61, 59, 59, 59, 58, 45, 58, 61, 59, 58, 58, 58, 61,
526 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 58, 32, 46, 32, 32, 32, 32,
527 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32,
528 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 61, 59, 59, 59, 59, 59,
529 58, 95, 32, 45, 61, 59, 61, 59, 59, 59, 59, 59, 59, 59, 45, 58, 59, 59, 59,
530 59, 61, 58, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
531 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
532 32, 58, 61, 59, 59, 59, 59, 59, 61, 59, 61, 46, 46, 32, 45, 45, 45, 59, 58,
533 45, 45, 46, 58, 59, 59, 59, 59, 59, 59, 61, 46, 32, 32, 32, 32, 32, 32, 32,
534 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32,
535 32, 32, 32, 32, 32, 32, 32, 32, 46, 58, 59, 59, 59, 59, 59, 59, 59, 59, 59,
536 61, 59, 46, 32, 32, 46, 32, 46, 32, 58, 61, 59, 59, 59, 59, 59, 59, 59, 59,
537 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10,
538 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 45,
539 59, 59, 59, 59, 59, 59, 59, 59, 58, 32, 32, 32, 32, 32, 32, 32, 32, 32, 61,
540 59, 59, 59, 59, 59, 59, 59, 58, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
541 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
542 32, 32, 32, 32, 32, 32, 32, 46, 61, 59, 59, 59, 59, 59, 59, 59, 32, 46, 32,
543 32, 32, 32, 32, 32, 61, 46, 61, 59, 59, 59, 59, 59, 59, 58, 32, 32, 32, 32,
544 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32,
545 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 61, 59, 59, 59,
546 59, 59, 59, 59, 59, 32, 46, 32, 32, 32, 32, 32, 32, 32, 46, 61, 58, 59, 59,
547 59, 59, 59, 58, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
548 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
549 32, 32, 32, 32, 58, 59, 59, 59, 59, 59, 59, 59, 59, 46, 46, 32, 32, 32, 32,
550 32, 32, 32, 61, 59, 59, 59, 59, 59, 59, 59, 45, 32, 32, 32, 32, 32, 32, 32,
551 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32,
552 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 32, 45, 61, 59, 59, 59, 59,
553 59, 58, 32, 46, 32, 32, 32, 32, 32, 32, 32, 58, 59, 59, 59, 59, 59, 58, 45,
554 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
555 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
556 32, 32, 32, 32, 45, 45, 45, 45, 32, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32,
557 32, 45, 61, 59, 58, 45, 45, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
558 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32,
559 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
560 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 32, 32, 46, 32, 32, 32, 32, 32, 32,
561 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10};
Ryan Mitchell5d275512018-07-19 14:29:00 -0700562
Adam Lesinskicacb28f2016-10-19 12:18:14 -0700563} // namespace aapt