1 /* 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 17 #include "Dump.h" 18 19 #include <cinttypes> 20 #include <vector> 21 22 #include "android-base/stringprintf.h" 23 #include "androidfw/ConfigDescription.h" 24 #include "androidfw/StringPiece.h" 25 26 #include "Debug.h" 27 #include "Diagnostics.h" 28 #include "LoadedApk.h" 29 #include "Util.h" 30 #include "format/Container.h" 31 #include "format/binary/BinaryResourceParser.h" 32 #include "format/binary/XmlFlattener.h" 33 #include "format/proto/ProtoDeserialize.h" 34 #include "io/FileStream.h" 35 #include "io/ZipArchive.h" 36 #include "process/IResourceTableConsumer.h" 37 #include "text/Printer.h" 38 #include "util/Files.h" 39 40 using ::aapt::text::Printer; 41 using ::android::StringPiece; 42 using ::android::base::StringPrintf; 43 44 namespace aapt { 45 46 static 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; 56 } 57 return "UNKNOWN"; 58 } 59 60 static void DumpCompiledFile(const ResourceFile& file, const Source& source, off64_t offset, 61 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)); 75 } 76 77 namespace { 78 79 class DumpContext : public IAaptContext { 80 public: 81 PackageType GetPackageType() override { 82 // Doesn't matter. 83 return PackageType::kApp; 84 } 85 86 IDiagnostics* GetDiagnostics() override { 87 return &diagnostics_; 88 } 89 90 NameMangler* GetNameMangler() override { 91 UNIMPLEMENTED(FATAL); 92 return nullptr; 93 } 94 95 const std::string& GetCompilationPackage() override { 96 static std::string empty; 97 return empty; 98 } 99 100 uint8_t GetPackageId() override { 101 return 0; 102 } 103 104 SymbolTable* GetExternalSymbols() override { 105 UNIMPLEMENTED(FATAL); 106 return nullptr; 107 } 108 109 bool IsVerbose() override { 110 return verbose_; 111 } 112 113 void SetVerbose(bool val) { 114 verbose_ = val; 115 } 116 117 int GetMinSdkVersion() override { 118 return 0; 119 } 120 121 private: 122 StdErrDiagnostics diagnostics_; 123 bool verbose_ = false; 124 }; 125 126 } // namespace 127 128 int DumpAPCCommand::Action(const std::vector<std::string>& args) { 129 DumpContext context; 130 DebugPrintTableOptions print_options; 131 print_options.show_sources = true; 132 print_options.show_values = !no_values_; 133 134 if (args.size() < 1) { 135 diag_->Error(DiagMessage() << "No dump container specified"); 136 return 1; 137 } 138 139 bool error = false; 140 for (auto container : args) { 141 io::FileInputStream input(container); 142 if (input.HadError()) { 143 context.GetDiagnostics()->Error(DiagMessage(container) 144 << "failed to open file: " << input.GetError()); 145 error = true; 146 continue; 147 } 148 149 // Try as a compiled file. 150 ContainerReader reader(&input); 151 if (reader.HadError()) { 152 context.GetDiagnostics()->Error(DiagMessage(container) 153 << "failed to read container: " << reader.GetError()); 154 error = true; 155 continue; 156 } 157 158 printer_->Println("AAPT2 Container (APC)"); 159 ContainerReaderEntry* entry; 160 std::string error; 161 while ((entry = reader.Next()) != nullptr) { 162 if (entry->Type() == ContainerEntryType::kResTable) { 163 printer_->Println("kResTable"); 164 165 pb::ResourceTable pb_table; 166 if (!entry->GetResTable(&pb_table)) { 167 context.GetDiagnostics()->Error(DiagMessage(container) 168 << "failed to parse proto table: " << entry->GetError()); 169 error = true; 170 continue; 171 } 172 173 ResourceTable table; 174 error.clear(); 175 if (!DeserializeTableFromPb(pb_table, nullptr /*files*/, &table, &error)) { 176 context.GetDiagnostics()->Error(DiagMessage(container) 177 << "failed to parse table: " << error); 178 error = true; 179 continue; 180 } 181 182 printer_->Indent(); 183 Debug::PrintTable(table, print_options, printer_); 184 printer_->Undent(); 185 } else if (entry->Type() == ContainerEntryType::kResFile) { 186 printer_->Println("kResFile"); 187 pb::internal::CompiledFile pb_compiled_file; 188 off64_t offset; 189 size_t length; 190 if (!entry->GetResFileOffsets(&pb_compiled_file, &offset, &length)) { 191 context.GetDiagnostics()->Error(DiagMessage(container) 192 << "failed to parse compiled proto file: " 193 << entry->GetError()); 194 error = true; 195 continue; 196 } 197 198 ResourceFile file; 199 if (!DeserializeCompiledFileFromPb(pb_compiled_file, &file, &error)) { 200 context.GetDiagnostics()->Warn(DiagMessage(container) 201 << "failed to parse compiled file: " << error); 202 error = true; 203 continue; 204 } 205 206 printer_->Indent(); 207 DumpCompiledFile(file, Source(container), offset, length, printer_); 208 printer_->Undent(); 209 } 210 } 211 } 212 213 return (error) ? 1 : 0; 214 } 215 216 int DumpBadgerCommand::Action(const std::vector<std::string>& args) { 217 printer_->Print(StringPrintf("%s", kBadgerData)); 218 printer_->Print("Did you mean \"aapt2 dump badging\"?\n"); 219 return 1; 220 } 221 222 int DumpConfigsCommand::Dump(LoadedApk* apk) { 223 ResourceTable* table = apk->GetResourceTable(); 224 if (!table) { 225 GetDiagnostics()->Error(DiagMessage() << "Failed to retrieve resource table"); 226 return 1; 227 } 228 229 // Comparison function used to order configurations 230 auto compare = [](android::ConfigDescription c1, android::ConfigDescription c2) -> bool { 231 return c1.compare(c2) < 0; 232 }; 233 234 // Insert the configurations into a set in order to keep every configuarion seen 235 std::set<android::ConfigDescription, decltype(compare)> configs(compare); 236 for (auto& package : table->packages) { 237 for (auto& type : package->types) { 238 for (auto& entry : type->entries) { 239 for (auto& value : entry->values) { 240 configs.insert(value->config); 241 } 242 } 243 } 244 } 245 246 // Print the configurations in order 247 for (auto& config : configs) { 248 GetPrinter()->Print(StringPrintf("%s\n", config.to_string().data())); 249 } 250 return 0; 251 } 252 253 int DumpPackageNameCommand::Dump(LoadedApk* apk) { 254 Maybe<std::string> package_name = GetPackageName(apk); 255 if (!package_name) { 256 return 1; 257 } 258 259 GetPrinter()->Println(package_name.value()); 260 return 0; 261 } 262 263 int DumpStringsCommand::Dump(LoadedApk* apk) { 264 ResourceTable* table = apk->GetResourceTable(); 265 if (!table) { 266 GetDiagnostics()->Error(DiagMessage() << "Failed to retrieve resource table"); 267 return 1; 268 } 269 270 // Load the run-time xml string pool using the flattened data 271 BigBuffer buffer(4096); 272 StringPool::FlattenUtf8(&buffer, table->string_pool, GetDiagnostics()); 273 auto data = buffer.to_string(); 274 android::ResStringPool pool(data.data(), data.size(), false); 275 Debug::DumpResStringPool(&pool, GetPrinter()); 276 return 0; 277 } 278 279 int DumpStyleParentCommand::Dump(LoadedApk* apk) { 280 Maybe<std::string> package_name = GetPackageName(apk); 281 if (!package_name) { 282 return 1; 283 } 284 285 const auto target_style = ResourceName(package_name.value(), ResourceType::kStyle, style_); 286 const auto table = apk->GetResourceTable(); 287 288 if (!table) { 289 GetDiagnostics()->Error(DiagMessage() << "Failed to retrieve resource table"); 290 return 1; 291 } 292 293 Maybe<ResourceTable::SearchResult> target = table->FindResource(target_style); 294 if (!target) { 295 GetDiagnostics()->Error( 296 DiagMessage() << "Target style \"" << target_style.entry << "\" does not exist"); 297 return 1; 298 } 299 300 Debug::PrintStyleGraph(table, target_style); 301 return 0; 302 } 303 304 int DumpTableCommand::Dump(LoadedApk* apk) { 305 if (apk->GetApkFormat() == ApkFormat::kProto) { 306 GetPrinter()->Println("Proto APK"); 307 } else { 308 GetPrinter()->Println("Binary APK"); 309 } 310 311 ResourceTable* table = apk->GetResourceTable(); 312 if (!table) { 313 GetDiagnostics()->Error(DiagMessage() << "Failed to retrieve resource table"); 314 return 1; 315 } 316 317 DebugPrintTableOptions print_options; 318 print_options.show_sources = true; 319 print_options.show_values = !no_values_; 320 Debug::PrintTable(*table, print_options, GetPrinter()); 321 return 0; 322 } 323 324 int DumpXmlStringsCommand::Dump(LoadedApk* apk) { 325 DumpContext context; 326 bool error = false; 327 for (auto xml_file : files_) { 328 android::ResXMLTree tree; 329 330 if (apk->GetApkFormat() == ApkFormat::kProto) { 331 auto xml = apk->LoadXml(xml_file, GetDiagnostics()); 332 if (!xml) { 333 error = true; 334 continue; 335 } 336 337 // Flatten the xml document to get a binary representation of the proto xml file 338 BigBuffer buffer(4096); 339 XmlFlattenerOptions options = {}; 340 options.keep_raw_values = true; 341 XmlFlattener flattener(&buffer, options); 342 if (!flattener.Consume(&context, xml.get())) { 343 error = true; 344 continue; 345 } 346 347 // Load the run-time xml tree using the flattened data 348 std::string data = buffer.to_string(); 349 tree.setTo(data.data(), data.size(), /** copyData */ true); 350 351 } else if (apk->GetApkFormat() == ApkFormat::kBinary) { 352 io::IFile* file = apk->GetFileCollection()->FindFile(xml_file); 353 if (!file) { 354 GetDiagnostics()->Error(DiagMessage(xml_file) 355 << "File '" << xml_file << "' not found in APK"); 356 error = true; 357 continue; 358 } 359 360 std::unique_ptr<io::IData> data = file->OpenAsData(); 361 if (!data) { 362 GetDiagnostics()->Error(DiagMessage() << "Failed to open " << xml_file); 363 error = true; 364 continue; 365 } 366 367 // Load the run-time xml tree from the file data 368 tree.setTo(data->data(), data->size(), /** copyData */ true); 369 } else { 370 GetDiagnostics()->Error(DiagMessage(apk->GetSource()) << "Unknown APK format"); 371 error = true; 372 continue; 373 } 374 375 Debug::DumpResStringPool(&tree.getStrings(), GetPrinter()); 376 } 377 return (error) ? 1 : 0; 378 } 379 380 int DumpXmlTreeCommand::Dump(LoadedApk* apk) { 381 for (auto file : files_) { 382 auto xml = apk->LoadXml(file, GetDiagnostics()); 383 if (!xml) { 384 return 1; 385 } 386 Debug::DumpXml(*xml, GetPrinter()); 387 } 388 return 0; 389 } 390 391 const char DumpBadgerCommand::kBadgerData[2925] = { 392 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 393 32, 32, 32, 32, 32, 32, 95, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 394 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 395 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 396 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 61, 63, 86, 35, 40, 46, 46, 397 95, 95, 95, 95, 97, 97, 44, 32, 46, 124, 42, 33, 83, 62, 32, 32, 32, 32, 32, 398 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 399 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 400 32, 32, 58, 46, 58, 59, 61, 59, 61, 81, 81, 81, 81, 66, 96, 61, 61, 58, 46, 401 46, 46, 58, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 402 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 403 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 61, 59, 59, 59, 58, 106, 81, 81, 404 81, 81, 102, 59, 61, 59, 59, 61, 61, 61, 58, 46, 32, 32, 32, 32, 32, 32, 32, 405 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 406 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 407 61, 59, 59, 59, 58, 109, 81, 81, 81, 81, 61, 59, 59, 59, 59, 59, 58, 59, 59, 408 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 409 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 410 32, 32, 32, 32, 32, 32, 32, 46, 61, 59, 59, 59, 60, 81, 81, 81, 81, 87, 58, 411 59, 59, 59, 59, 59, 59, 61, 119, 44, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 412 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 413 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 47, 61, 59, 59, 414 58, 100, 81, 81, 81, 81, 35, 58, 59, 59, 59, 59, 59, 58, 121, 81, 91, 32, 32, 415 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 416 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 417 32, 32, 32, 46, 109, 58, 59, 59, 61, 81, 81, 81, 81, 81, 109, 58, 59, 59, 59, 418 59, 61, 109, 81, 81, 76, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 419 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 420 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 41, 87, 59, 61, 59, 41, 81, 81, 421 81, 81, 81, 81, 59, 61, 59, 59, 58, 109, 81, 81, 87, 39, 46, 32, 32, 32, 32, 422 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 423 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 424 60, 81, 91, 59, 59, 61, 81, 81, 81, 81, 81, 87, 43, 59, 58, 59, 60, 81, 81, 425 81, 76, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 426 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 427 32, 32, 32, 32, 32, 32, 32, 32, 32, 52, 91, 58, 45, 59, 87, 81, 81, 81, 81, 428 70, 58, 58, 58, 59, 106, 81, 81, 81, 91, 32, 32, 32, 32, 32, 32, 32, 32, 32, 429 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 430 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 93, 40, 431 32, 46, 59, 100, 81, 81, 81, 81, 40, 58, 46, 46, 58, 100, 81, 81, 68, 32, 32, 432 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 433 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 46, 46, 32, 46, 434 46, 46, 32, 46, 32, 46, 45, 91, 59, 61, 58, 109, 81, 81, 81, 87, 46, 58, 61, 435 59, 60, 81, 81, 80, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 436 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 46, 46, 437 61, 59, 61, 61, 61, 59, 61, 61, 59, 59, 59, 58, 58, 46, 46, 41, 58, 59, 58, 438 81, 81, 81, 81, 69, 58, 59, 59, 60, 81, 81, 68, 32, 32, 32, 32, 32, 32, 32, 439 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 440 32, 32, 32, 32, 58, 59, 61, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 441 59, 59, 61, 61, 46, 61, 59, 93, 81, 81, 81, 81, 107, 58, 59, 58, 109, 87, 68, 442 96, 32, 32, 32, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 443 32, 32, 32, 32, 32, 10, 32, 32, 32, 46, 60, 61, 61, 59, 59, 59, 59, 59, 59, 444 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 58, 58, 58, 115, 109, 68, 41, 36, 445 81, 109, 46, 61, 61, 81, 69, 96, 46, 58, 58, 46, 58, 46, 46, 32, 32, 32, 32, 446 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 46, 32, 95, 81, 67, 447 61, 61, 58, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 448 59, 59, 58, 68, 39, 61, 105, 61, 63, 81, 119, 58, 106, 80, 32, 58, 61, 59, 59, 449 61, 59, 61, 59, 61, 46, 95, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 450 32, 32, 10, 32, 32, 36, 81, 109, 105, 59, 61, 59, 59, 59, 59, 59, 59, 59, 59, 451 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 46, 58, 37, 73, 108, 108, 62, 52, 81, 452 109, 34, 32, 61, 59, 59, 59, 59, 59, 59, 59, 59, 59, 61, 59, 61, 61, 46, 46, 453 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 46, 45, 57, 101, 43, 43, 61, 454 61, 59, 59, 59, 59, 59, 59, 61, 59, 59, 59, 59, 59, 59, 59, 59, 59, 58, 97, 455 46, 61, 108, 62, 126, 58, 106, 80, 96, 46, 61, 61, 59, 59, 59, 59, 59, 59, 59, 456 59, 59, 59, 59, 59, 59, 61, 61, 97, 103, 97, 32, 32, 32, 32, 32, 32, 32, 10, 457 32, 32, 32, 32, 45, 46, 32, 46, 32, 32, 32, 32, 32, 32, 32, 32, 45, 45, 45, 458 58, 59, 59, 59, 59, 61, 119, 81, 97, 124, 105, 124, 124, 39, 126, 95, 119, 58, 61, 459 58, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 61, 119, 81, 81, 460 99, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 461 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 59, 59, 58, 106, 81, 81, 81, 109, 119, 462 119, 119, 109, 109, 81, 81, 122, 58, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 463 59, 59, 59, 58, 115, 81, 87, 81, 102, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 464 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 61, 58, 465 59, 61, 81, 81, 81, 81, 81, 81, 87, 87, 81, 81, 81, 81, 81, 58, 59, 59, 59, 466 59, 59, 59, 59, 59, 58, 45, 45, 45, 59, 59, 59, 41, 87, 66, 33, 32, 32, 32, 467 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 468 32, 32, 32, 32, 32, 32, 58, 59, 59, 93, 81, 81, 81, 81, 81, 81, 81, 81, 81, 469 81, 81, 81, 81, 40, 58, 59, 59, 59, 58, 45, 32, 46, 32, 32, 32, 32, 32, 46, 470 32, 126, 96, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 471 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 61, 59, 58, 81, 472 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 40, 58, 59, 59, 59, 58, 32, 473 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 474 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 475 32, 32, 32, 58, 59, 59, 58, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 476 81, 40, 58, 59, 59, 59, 46, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 477 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 478 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 61, 59, 60, 81, 81, 81, 81, 479 81, 81, 81, 81, 81, 81, 81, 81, 81, 59, 61, 59, 59, 61, 32, 32, 32, 32, 32, 480 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 481 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 482 58, 59, 59, 93, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 40, 59, 483 59, 59, 59, 32, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 484 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 485 32, 32, 32, 32, 32, 32, 32, 32, 58, 61, 58, 106, 81, 81, 81, 81, 81, 81, 81, 486 81, 81, 81, 81, 81, 81, 76, 58, 59, 59, 59, 32, 46, 32, 32, 32, 32, 32, 32, 487 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 488 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 61, 58, 58, 489 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 87, 58, 59, 59, 59, 59, 490 32, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 491 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 492 32, 32, 32, 32, 32, 58, 59, 61, 41, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 493 81, 81, 87, 59, 61, 58, 59, 59, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 494 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 495 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 61, 58, 61, 81, 81, 496 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 107, 58, 59, 59, 59, 59, 58, 32, 32, 497 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 498 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 499 32, 32, 58, 59, 59, 58, 51, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 102, 94, 500 59, 59, 59, 59, 59, 61, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 501 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 502 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 58, 61, 59, 59, 59, 43, 63, 36, 81, 503 81, 81, 87, 64, 86, 102, 58, 59, 59, 59, 59, 59, 59, 59, 46, 32, 32, 32, 32, 504 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 505 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 61, 506 59, 59, 59, 59, 59, 59, 59, 43, 33, 58, 126, 126, 58, 59, 59, 59, 59, 59, 59, 507 59, 59, 59, 59, 32, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 508 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 509 32, 32, 32, 32, 32, 46, 61, 59, 59, 59, 58, 45, 58, 61, 59, 58, 58, 58, 61, 510 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 58, 32, 46, 32, 32, 32, 32, 511 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 512 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 61, 59, 59, 59, 59, 59, 513 58, 95, 32, 45, 61, 59, 61, 59, 59, 59, 59, 59, 59, 59, 45, 58, 59, 59, 59, 514 59, 61, 58, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 515 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 516 32, 58, 61, 59, 59, 59, 59, 59, 61, 59, 61, 46, 46, 32, 45, 45, 45, 59, 58, 517 45, 45, 46, 58, 59, 59, 59, 59, 59, 59, 61, 46, 32, 32, 32, 32, 32, 32, 32, 518 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 519 32, 32, 32, 32, 32, 32, 32, 32, 46, 58, 59, 59, 59, 59, 59, 59, 59, 59, 59, 520 61, 59, 46, 32, 32, 46, 32, 46, 32, 58, 61, 59, 59, 59, 59, 59, 59, 59, 59, 521 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 522 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 45, 523 59, 59, 59, 59, 59, 59, 59, 59, 58, 32, 32, 32, 32, 32, 32, 32, 32, 32, 61, 524 59, 59, 59, 59, 59, 59, 59, 58, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 525 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 526 32, 32, 32, 32, 32, 32, 32, 46, 61, 59, 59, 59, 59, 59, 59, 59, 32, 46, 32, 527 32, 32, 32, 32, 32, 61, 46, 61, 59, 59, 59, 59, 59, 59, 58, 32, 32, 32, 32, 528 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 529 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 61, 59, 59, 59, 530 59, 59, 59, 59, 59, 32, 46, 32, 32, 32, 32, 32, 32, 32, 46, 61, 58, 59, 59, 531 59, 59, 59, 58, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 532 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 533 32, 32, 32, 32, 58, 59, 59, 59, 59, 59, 59, 59, 59, 46, 46, 32, 32, 32, 32, 534 32, 32, 32, 61, 59, 59, 59, 59, 59, 59, 59, 45, 32, 32, 32, 32, 32, 32, 32, 535 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 536 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 32, 45, 61, 59, 59, 59, 59, 537 59, 58, 32, 46, 32, 32, 32, 32, 32, 32, 32, 58, 59, 59, 59, 59, 59, 58, 45, 538 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 539 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 540 32, 32, 32, 32, 45, 45, 45, 45, 32, 46, 32, 32, 32, 32, 32, 32, 32, 32, 32, 541 32, 45, 61, 59, 58, 45, 45, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 542 32, 32, 32, 32, 32, 32, 32, 32, 32, 10, 32, 32, 32, 32, 32, 32, 32, 32, 32, 543 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 544 32, 32, 32, 32, 32, 32, 32, 32, 32, 46, 32, 32, 46, 32, 32, 32, 32, 32, 32, 545 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 10}; 546 547 } // namespace aapt 548