1 /* 2 * Copyright 2009-2014, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Copyright 2011, Oliver Tappe <zooey@hirschkaefer.de> 4 * Distributed under the terms of the MIT License. 5 */ 6 7 8 #include <package/hpkg/ReaderImplBase.h> 9 10 #include <errno.h> 11 #include <stdio.h> 12 #include <stdlib.h> 13 #include <string.h> 14 #include <unistd.h> 15 16 #include <algorithm> 17 #include <new> 18 19 #include <ByteOrder.h> 20 #include <DataIO.h> 21 22 #include <ZlibCompressionAlgorithm.h> 23 #ifdef ZSTD_ENABLED 24 #include <ZstdCompressionAlgorithm.h> 25 #endif 26 27 #include <package/hpkg/HPKGDefsPrivate.h> 28 #include <package/hpkg/PackageFileHeapReader.h> 29 30 31 namespace BPackageKit { 32 33 namespace BHPKG { 34 35 namespace BPrivate { 36 37 38 static const uint16 kAttributeTypes[B_HPKG_ATTRIBUTE_ID_ENUM_COUNT] = { 39 #define B_DEFINE_HPKG_ATTRIBUTE(id, type, name, constant) \ 40 B_HPKG_ATTRIBUTE_TYPE_##type, 41 #include <package/hpkg/PackageAttributes.h> 42 #undef B_DEFINE_HPKG_ATTRIBUTE 43 }; 44 45 // #pragma mark - AttributeHandlerContext 46 47 48 ReaderImplBase::AttributeHandlerContext::AttributeHandlerContext( 49 BErrorOutput* errorOutput, BPackageContentHandler* packageContentHandler, 50 BHPKGPackageSectionID section, bool ignoreUnknownAttributes) 51 : 52 errorOutput(errorOutput), 53 packageContentHandler(packageContentHandler), 54 hasLowLevelHandler(false), 55 ignoreUnknownAttributes(ignoreUnknownAttributes), 56 section(section) 57 { 58 } 59 60 61 ReaderImplBase::AttributeHandlerContext::AttributeHandlerContext( 62 BErrorOutput* errorOutput, BLowLevelPackageContentHandler* lowLevelHandler, 63 BHPKGPackageSectionID section, bool ignoreUnknownAttributes) 64 : 65 errorOutput(errorOutput), 66 lowLevelHandler(lowLevelHandler), 67 hasLowLevelHandler(true), 68 ignoreUnknownAttributes(ignoreUnknownAttributes), 69 section(section) 70 { 71 } 72 73 74 void 75 ReaderImplBase::AttributeHandlerContext::ErrorOccurred() 76 { 77 if (hasLowLevelHandler) 78 lowLevelHandler->HandleErrorOccurred(); 79 else 80 packageContentHandler->HandleErrorOccurred(); 81 } 82 83 84 // #pragma mark - AttributeHandler 85 86 87 ReaderImplBase::AttributeHandler::~AttributeHandler() 88 { 89 } 90 91 92 void 93 ReaderImplBase::AttributeHandler::SetLevel(int level) 94 { 95 fLevel = level; 96 } 97 98 99 status_t 100 ReaderImplBase::AttributeHandler::HandleAttribute( 101 AttributeHandlerContext* context, uint8 id, const AttributeValue& value, 102 AttributeHandler** _handler) 103 { 104 return B_OK; 105 } 106 107 108 status_t 109 ReaderImplBase::AttributeHandler::NotifyDone( 110 AttributeHandlerContext* context) 111 { 112 return B_OK; 113 } 114 115 116 status_t 117 ReaderImplBase::AttributeHandler::Delete(AttributeHandlerContext* context) 118 { 119 delete this; 120 return B_OK; 121 } 122 123 124 // #pragma mark - PackageInfoAttributeHandlerBase 125 126 127 ReaderImplBase::PackageInfoAttributeHandlerBase 128 ::PackageInfoAttributeHandlerBase( 129 BPackageInfoAttributeValue& packageInfoValue) 130 : 131 fPackageInfoValue(packageInfoValue) 132 { 133 } 134 135 136 status_t 137 ReaderImplBase::PackageInfoAttributeHandlerBase::NotifyDone( 138 AttributeHandlerContext* context) 139 { 140 status_t error = context->packageContentHandler->HandlePackageAttribute( 141 fPackageInfoValue); 142 if (context->ignoreUnknownAttributes && error == B_NOT_SUPPORTED) 143 error = B_OK; // Safe to skip a future/unknown attribute. 144 fPackageInfoValue.Clear(); 145 return error; 146 } 147 148 149 // #pragma mark - PackageVersionAttributeHandler 150 151 152 ReaderImplBase::PackageVersionAttributeHandler::PackageVersionAttributeHandler( 153 BPackageInfoAttributeValue& packageInfoValue, 154 BPackageVersionData& versionData, bool notify) 155 : 156 super(packageInfoValue), 157 fPackageVersionData(versionData), 158 fNotify(notify) 159 { 160 } 161 162 163 status_t 164 ReaderImplBase::PackageVersionAttributeHandler::HandleAttribute( 165 AttributeHandlerContext* context, uint8 id, const AttributeValue& value, 166 AttributeHandler** _handler) 167 { 168 switch (id) { 169 case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_MINOR: 170 fPackageVersionData.minor = value.string; 171 break; 172 173 case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_MICRO: 174 fPackageVersionData.micro = value.string; 175 break; 176 177 case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_PRE_RELEASE: 178 fPackageVersionData.preRelease = value.string; 179 break; 180 181 case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_REVISION: 182 fPackageVersionData.revision = value.unsignedInt; 183 break; 184 185 default: 186 if (context->ignoreUnknownAttributes) 187 break; 188 189 context->errorOutput->PrintError("Error: Invalid package " 190 "attribute section: unexpected package attribute id %d " 191 "encountered when parsing package version\n", id); 192 return B_BAD_DATA; 193 } 194 195 return B_OK; 196 } 197 198 199 status_t 200 ReaderImplBase::PackageVersionAttributeHandler::NotifyDone( 201 AttributeHandlerContext* context) 202 { 203 if (!fNotify) 204 return B_OK; 205 206 fPackageInfoValue.attributeID = B_PACKAGE_INFO_VERSION; 207 return super::NotifyDone(context); 208 } 209 210 211 // #pragma mark - PackageResolvableAttributeHandler 212 213 214 ReaderImplBase::PackageResolvableAttributeHandler 215 ::PackageResolvableAttributeHandler( 216 BPackageInfoAttributeValue& packageInfoValue) 217 : 218 super(packageInfoValue) 219 { 220 } 221 222 223 status_t 224 ReaderImplBase::PackageResolvableAttributeHandler::HandleAttribute( 225 AttributeHandlerContext* context, uint8 id, const AttributeValue& value, 226 AttributeHandler** _handler) 227 { 228 switch (id) { 229 case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_MAJOR: 230 fPackageInfoValue.resolvable.haveVersion = true; 231 fPackageInfoValue.resolvable.version.major = value.string; 232 if (_handler != NULL) { 233 *_handler 234 = new(std::nothrow) PackageVersionAttributeHandler( 235 fPackageInfoValue, 236 fPackageInfoValue.resolvable.version, false); 237 if (*_handler == NULL) 238 return B_NO_MEMORY; 239 } 240 break; 241 242 case B_HPKG_ATTRIBUTE_ID_PACKAGE_PROVIDES_COMPATIBLE: 243 fPackageInfoValue.resolvable.haveCompatibleVersion = true; 244 fPackageInfoValue.resolvable.compatibleVersion.major = value.string; 245 if (_handler != NULL) { 246 *_handler 247 = new(std::nothrow) PackageVersionAttributeHandler( 248 fPackageInfoValue, 249 fPackageInfoValue.resolvable.compatibleVersion, false); 250 if (*_handler == NULL) 251 return B_NO_MEMORY; 252 } 253 break; 254 255 default: 256 if (context->ignoreUnknownAttributes) 257 break; 258 259 context->errorOutput->PrintError("Error: Invalid package " 260 "attribute section: unexpected package attribute id %d " 261 "encountered when parsing package resolvable\n", id); 262 return B_BAD_DATA; 263 } 264 265 return B_OK; 266 } 267 268 269 // #pragma mark - PackageResolvableExpressionAttributeHandler 270 271 272 ReaderImplBase::PackageResolvableExpressionAttributeHandler 273 ::PackageResolvableExpressionAttributeHandler( 274 BPackageInfoAttributeValue& packageInfoValue) 275 : 276 super(packageInfoValue) 277 { 278 } 279 280 281 status_t 282 ReaderImplBase::PackageResolvableExpressionAttributeHandler::HandleAttribute( 283 AttributeHandlerContext* context, uint8 id, const AttributeValue& value, 284 AttributeHandler** _handler) 285 { 286 switch (id) { 287 case B_HPKG_ATTRIBUTE_ID_PACKAGE_RESOLVABLE_OPERATOR: 288 if (value.unsignedInt >= B_PACKAGE_RESOLVABLE_OP_ENUM_COUNT) { 289 context->errorOutput->PrintError( 290 "Error: Invalid package attribute section: invalid " 291 "package resolvable operator %lld encountered\n", 292 value.unsignedInt); 293 return B_BAD_DATA; 294 } 295 fPackageInfoValue.resolvableExpression.op 296 = (BPackageResolvableOperator)value.unsignedInt; 297 break; 298 299 case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_MAJOR: 300 fPackageInfoValue.resolvableExpression.haveOpAndVersion = true; 301 fPackageInfoValue.resolvableExpression.version.major 302 = value.string; 303 if (_handler != NULL) { 304 *_handler 305 = new(std::nothrow) PackageVersionAttributeHandler( 306 fPackageInfoValue, 307 fPackageInfoValue.resolvableExpression.version, 308 false); 309 if (*_handler == NULL) 310 return B_NO_MEMORY; 311 } 312 return B_OK; 313 314 default: 315 if (context->ignoreUnknownAttributes) 316 break; 317 318 context->errorOutput->PrintError("Error: Invalid package " 319 "attribute section: unexpected package attribute id %d " 320 "encountered when parsing package resolvable-expression\n", 321 id); 322 return B_BAD_DATA; 323 } 324 325 return B_OK; 326 } 327 328 329 // #pragma mark - GlobalWritableFileInfoAttributeHandler 330 331 332 ReaderImplBase::GlobalWritableFileInfoAttributeHandler 333 ::GlobalWritableFileInfoAttributeHandler( 334 BPackageInfoAttributeValue& packageInfoValue) 335 : 336 super(packageInfoValue) 337 { 338 } 339 340 341 status_t 342 ReaderImplBase::GlobalWritableFileInfoAttributeHandler::HandleAttribute( 343 AttributeHandlerContext* context, uint8 id, const AttributeValue& value, 344 AttributeHandler** _handler) 345 { 346 switch (id) { 347 case B_HPKG_ATTRIBUTE_ID_PACKAGE_WRITABLE_FILE_UPDATE_TYPE: 348 if (value.unsignedInt >= B_WRITABLE_FILE_UPDATE_TYPE_ENUM_COUNT) { 349 context->errorOutput->PrintError( 350 "Error: Invalid package attribute section: invalid " 351 "global settings file update type %" B_PRIu64 352 " encountered\n", value.unsignedInt); 353 return B_BAD_DATA; 354 } 355 fPackageInfoValue.globalWritableFileInfo.updateType 356 = (BWritableFileUpdateType)value.unsignedInt; 357 break; 358 359 case B_HPKG_ATTRIBUTE_ID_PACKAGE_IS_WRITABLE_DIRECTORY: 360 fPackageInfoValue.globalWritableFileInfo.isDirectory 361 = value.unsignedInt != 0; 362 break; 363 364 default: 365 if (context->ignoreUnknownAttributes) 366 break; 367 368 context->errorOutput->PrintError("Error: Invalid package " 369 "attribute section: unexpected package attribute id %d " 370 "encountered when parsing global settings file info\n", 371 id); 372 return B_BAD_DATA; 373 } 374 375 return B_OK; 376 } 377 378 379 // #pragma mark - UserSettingsFileInfoAttributeHandler 380 381 382 ReaderImplBase::UserSettingsFileInfoAttributeHandler 383 ::UserSettingsFileInfoAttributeHandler( 384 BPackageInfoAttributeValue& packageInfoValue) 385 : 386 super(packageInfoValue) 387 { 388 } 389 390 391 status_t 392 ReaderImplBase::UserSettingsFileInfoAttributeHandler::HandleAttribute( 393 AttributeHandlerContext* context, uint8 id, const AttributeValue& value, 394 AttributeHandler** _handler) 395 { 396 switch (id) { 397 case B_HPKG_ATTRIBUTE_ID_PACKAGE_SETTINGS_FILE_TEMPLATE: 398 fPackageInfoValue.userSettingsFileInfo.templatePath = value.string; 399 break; 400 401 case B_HPKG_ATTRIBUTE_ID_PACKAGE_IS_WRITABLE_DIRECTORY: 402 fPackageInfoValue.userSettingsFileInfo.isDirectory 403 = value.unsignedInt != 0; 404 break; 405 406 default: 407 if (context->ignoreUnknownAttributes) 408 break; 409 410 context->errorOutput->PrintError("Error: Invalid package " 411 "attribute section: unexpected package attribute id %d " 412 "encountered when parsing user settings file info\n", 413 id); 414 return B_BAD_DATA; 415 } 416 417 return B_OK; 418 } 419 420 421 // #pragma mark - UserAttributeHandler 422 423 424 ReaderImplBase::UserAttributeHandler::UserAttributeHandler( 425 BPackageInfoAttributeValue& packageInfoValue) 426 : 427 super(packageInfoValue), 428 fGroups() 429 { 430 } 431 432 433 status_t 434 ReaderImplBase::UserAttributeHandler::HandleAttribute( 435 AttributeHandlerContext* context, uint8 id, const AttributeValue& value, 436 AttributeHandler** _handler) 437 { 438 switch (id) { 439 case B_HPKG_ATTRIBUTE_ID_PACKAGE_USER_REAL_NAME: 440 fPackageInfoValue.user.realName = value.string; 441 break; 442 443 case B_HPKG_ATTRIBUTE_ID_PACKAGE_USER_HOME: 444 fPackageInfoValue.user.home = value.string; 445 break; 446 447 case B_HPKG_ATTRIBUTE_ID_PACKAGE_USER_SHELL: 448 fPackageInfoValue.user.shell = value.string; 449 break; 450 451 case B_HPKG_ATTRIBUTE_ID_PACKAGE_USER_GROUP: 452 if (!fGroups.Add(value.string)) 453 return B_NO_MEMORY; 454 break; 455 456 default: 457 if (context->ignoreUnknownAttributes) 458 break; 459 460 context->errorOutput->PrintError("Error: Invalid package " 461 "attribute section: unexpected package attribute id %d " 462 "encountered when parsing user settings file info\n", 463 id); 464 return B_BAD_DATA; 465 } 466 467 return B_OK; 468 } 469 470 471 status_t 472 ReaderImplBase::UserAttributeHandler::NotifyDone( 473 AttributeHandlerContext* context) 474 { 475 if (!fGroups.IsEmpty()) { 476 fPackageInfoValue.user.groups = fGroups.Elements(); 477 fPackageInfoValue.user.groupCount = fGroups.Count(); 478 } 479 480 return super::NotifyDone(context); 481 } 482 483 484 // #pragma mark - PackageAttributeHandler 485 486 487 status_t 488 ReaderImplBase::PackageAttributeHandler::HandleAttribute( 489 AttributeHandlerContext* context, uint8 id, const AttributeValue& value, 490 AttributeHandler** _handler) 491 { 492 switch (id) { 493 case B_HPKG_ATTRIBUTE_ID_PACKAGE_NAME: 494 fPackageInfoValue.SetTo(B_PACKAGE_INFO_NAME, value.string); 495 break; 496 497 case B_HPKG_ATTRIBUTE_ID_PACKAGE_SUMMARY: 498 fPackageInfoValue.SetTo(B_PACKAGE_INFO_SUMMARY, value.string); 499 break; 500 501 case B_HPKG_ATTRIBUTE_ID_PACKAGE_DESCRIPTION: 502 fPackageInfoValue.SetTo(B_PACKAGE_INFO_DESCRIPTION, 503 value.string); 504 break; 505 506 case B_HPKG_ATTRIBUTE_ID_PACKAGE_VENDOR: 507 fPackageInfoValue.SetTo(B_PACKAGE_INFO_VENDOR, value.string); 508 break; 509 510 case B_HPKG_ATTRIBUTE_ID_PACKAGE_PACKAGER: 511 fPackageInfoValue.SetTo(B_PACKAGE_INFO_PACKAGER, value.string); 512 break; 513 514 case B_HPKG_ATTRIBUTE_ID_PACKAGE_BASE_PACKAGE: 515 fPackageInfoValue.SetTo(B_PACKAGE_INFO_BASE_PACKAGE, value.string); 516 break; 517 518 case B_HPKG_ATTRIBUTE_ID_PACKAGE_FLAGS: 519 fPackageInfoValue.SetTo(B_PACKAGE_INFO_FLAGS, 520 (uint32)value.unsignedInt); 521 break; 522 523 case B_HPKG_ATTRIBUTE_ID_PACKAGE_ARCHITECTURE: 524 if (value.unsignedInt 525 >= B_PACKAGE_ARCHITECTURE_ENUM_COUNT) { 526 context->errorOutput->PrintError( 527 "Error: Invalid package attribute section: " 528 "Invalid package architecture %lld encountered\n", 529 value.unsignedInt); 530 return B_BAD_DATA; 531 } 532 fPackageInfoValue.SetTo(B_PACKAGE_INFO_ARCHITECTURE, 533 (uint8)value.unsignedInt); 534 break; 535 536 case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_MAJOR: 537 fPackageInfoValue.attributeID = B_PACKAGE_INFO_VERSION; 538 fPackageInfoValue.version.major = value.string; 539 if (_handler != NULL) { 540 *_handler 541 = new(std::nothrow) PackageVersionAttributeHandler( 542 fPackageInfoValue, fPackageInfoValue.version, true); 543 if (*_handler == NULL) 544 return B_NO_MEMORY; 545 } 546 break; 547 548 case B_HPKG_ATTRIBUTE_ID_PACKAGE_COPYRIGHT: 549 fPackageInfoValue.SetTo(B_PACKAGE_INFO_COPYRIGHTS, 550 value.string); 551 break; 552 553 case B_HPKG_ATTRIBUTE_ID_PACKAGE_LICENSE: 554 fPackageInfoValue.SetTo(B_PACKAGE_INFO_LICENSES, 555 value.string); 556 break; 557 558 case B_HPKG_ATTRIBUTE_ID_PACKAGE_URL: 559 fPackageInfoValue.SetTo(B_PACKAGE_INFO_URLS, value.string); 560 break; 561 562 case B_HPKG_ATTRIBUTE_ID_PACKAGE_SOURCE_URL: 563 fPackageInfoValue.SetTo(B_PACKAGE_INFO_SOURCE_URLS, value.string); 564 break; 565 566 case B_HPKG_ATTRIBUTE_ID_PACKAGE_PROVIDES: 567 fPackageInfoValue.resolvable.name = value.string; 568 fPackageInfoValue.attributeID = B_PACKAGE_INFO_PROVIDES; 569 if (_handler != NULL) { 570 *_handler 571 = new(std::nothrow) PackageResolvableAttributeHandler( 572 fPackageInfoValue); 573 if (*_handler == NULL) 574 return B_NO_MEMORY; 575 } 576 break; 577 578 case B_HPKG_ATTRIBUTE_ID_PACKAGE_REQUIRES: 579 case B_HPKG_ATTRIBUTE_ID_PACKAGE_SUPPLEMENTS: 580 case B_HPKG_ATTRIBUTE_ID_PACKAGE_CONFLICTS: 581 case B_HPKG_ATTRIBUTE_ID_PACKAGE_FRESHENS: 582 fPackageInfoValue.resolvableExpression.name = value.string; 583 switch (id) { 584 case B_HPKG_ATTRIBUTE_ID_PACKAGE_REQUIRES: 585 fPackageInfoValue.attributeID = B_PACKAGE_INFO_REQUIRES; 586 break; 587 588 case B_HPKG_ATTRIBUTE_ID_PACKAGE_SUPPLEMENTS: 589 fPackageInfoValue.attributeID 590 = B_PACKAGE_INFO_SUPPLEMENTS; 591 break; 592 593 case B_HPKG_ATTRIBUTE_ID_PACKAGE_CONFLICTS: 594 fPackageInfoValue.attributeID 595 = B_PACKAGE_INFO_CONFLICTS; 596 break; 597 598 case B_HPKG_ATTRIBUTE_ID_PACKAGE_FRESHENS: 599 fPackageInfoValue.attributeID = B_PACKAGE_INFO_FRESHENS; 600 break; 601 } 602 if (_handler != NULL) { 603 *_handler = new(std::nothrow) 604 PackageResolvableExpressionAttributeHandler( 605 fPackageInfoValue); 606 if (*_handler == NULL) 607 return B_NO_MEMORY; 608 } 609 break; 610 611 case B_HPKG_ATTRIBUTE_ID_PACKAGE_REPLACES: 612 fPackageInfoValue.SetTo(B_PACKAGE_INFO_REPLACES, value.string); 613 break; 614 615 case B_HPKG_ATTRIBUTE_ID_PACKAGE_CHECKSUM: 616 fPackageInfoValue.SetTo(B_PACKAGE_INFO_CHECKSUM, value.string); 617 break; 618 619 case B_HPKG_ATTRIBUTE_ID_PACKAGE_INSTALL_PATH: 620 fPackageInfoValue.SetTo(B_PACKAGE_INFO_INSTALL_PATH, value.string); 621 break; 622 623 case B_HPKG_ATTRIBUTE_ID_PACKAGE_GLOBAL_WRITABLE_FILE: 624 fPackageInfoValue.globalWritableFileInfo.path = value.string; 625 fPackageInfoValue.globalWritableFileInfo.updateType 626 = B_WRITABLE_FILE_UPDATE_TYPE_ENUM_COUNT; 627 fPackageInfoValue.attributeID 628 = B_PACKAGE_INFO_GLOBAL_WRITABLE_FILES; 629 if (_handler != NULL) { 630 *_handler 631 = new(std::nothrow) GlobalWritableFileInfoAttributeHandler( 632 fPackageInfoValue); 633 if (*_handler == NULL) 634 return B_NO_MEMORY; 635 } 636 break; 637 638 case B_HPKG_ATTRIBUTE_ID_PACKAGE_USER_SETTINGS_FILE: 639 fPackageInfoValue.userSettingsFileInfo.path = value.string; 640 fPackageInfoValue.attributeID 641 = B_PACKAGE_INFO_USER_SETTINGS_FILES; 642 if (_handler != NULL) { 643 *_handler 644 = new(std::nothrow) UserSettingsFileInfoAttributeHandler( 645 fPackageInfoValue); 646 if (*_handler == NULL) 647 return B_NO_MEMORY; 648 } 649 break; 650 651 case B_HPKG_ATTRIBUTE_ID_PACKAGE_USER: 652 fPackageInfoValue.user.name = value.string; 653 fPackageInfoValue.attributeID = B_PACKAGE_INFO_USERS; 654 if (_handler != NULL) { 655 *_handler = new(std::nothrow) UserAttributeHandler( 656 fPackageInfoValue); 657 if (*_handler == NULL) 658 return B_NO_MEMORY; 659 } 660 break; 661 662 case B_HPKG_ATTRIBUTE_ID_PACKAGE_GROUP: 663 fPackageInfoValue.SetTo(B_PACKAGE_INFO_GROUPS, value.string); 664 break; 665 666 case B_HPKG_ATTRIBUTE_ID_PACKAGE_POST_INSTALL_SCRIPT: 667 fPackageInfoValue.SetTo(B_PACKAGE_INFO_POST_INSTALL_SCRIPTS, 668 value.string); 669 break; 670 671 default: 672 if (context->ignoreUnknownAttributes) 673 break; 674 675 context->errorOutput->PrintError( 676 "Error: Invalid package attribute section: unexpected " 677 "package attribute id %d encountered\n", id); 678 return B_BAD_DATA; 679 } 680 681 // notify unless the current attribute has children, in which case 682 // the child-handler will notify when it's done 683 if (_handler == NULL) { 684 status_t error = context->packageContentHandler 685 ->HandlePackageAttribute(fPackageInfoValue); 686 if (context->ignoreUnknownAttributes && error == B_NOT_SUPPORTED) 687 error = B_OK; // Safe to skip a future/unknown attribute. 688 fPackageInfoValue.Clear(); 689 if (error != B_OK) 690 return error; 691 } 692 693 return B_OK; 694 } 695 696 697 // #pragma mark - LowLevelAttributeHandler 698 699 700 ReaderImplBase::LowLevelAttributeHandler::LowLevelAttributeHandler() 701 : 702 fParentToken(NULL), 703 fToken(NULL), 704 fID(B_HPKG_ATTRIBUTE_ID_ENUM_COUNT) 705 { 706 } 707 708 709 ReaderImplBase::LowLevelAttributeHandler::LowLevelAttributeHandler(uint8 id, 710 const BPackageAttributeValue& value, void* parentToken, void* token) 711 : 712 fParentToken(NULL), 713 fToken(token), 714 fID(id), 715 fValue(value) 716 { 717 } 718 719 720 status_t 721 ReaderImplBase::LowLevelAttributeHandler::HandleAttribute( 722 AttributeHandlerContext* context, uint8 id, const AttributeValue& value, 723 AttributeHandler** _handler) 724 { 725 // notify the content handler 726 void* token; 727 status_t error = context->lowLevelHandler->HandleAttribute( 728 (BHPKGAttributeID)id, value, fToken, token); 729 if (error != B_OK) 730 return error; 731 732 // create a subhandler for the attribute, if it has children 733 if (_handler != NULL) { 734 *_handler = new(std::nothrow) LowLevelAttributeHandler(id, value, 735 fToken, token); 736 if (*_handler == NULL) { 737 context->lowLevelHandler->HandleAttributeDone((BHPKGAttributeID)id, 738 value, fToken, token); 739 return B_NO_MEMORY; 740 } 741 return B_OK; 742 } 743 744 // no children -- just call the done hook 745 return context->lowLevelHandler->HandleAttributeDone((BHPKGAttributeID)id, 746 value, fToken, token); 747 } 748 749 750 status_t 751 ReaderImplBase::LowLevelAttributeHandler::NotifyDone( 752 AttributeHandlerContext* context) 753 { 754 if (fID != B_HPKG_ATTRIBUTE_ID_ENUM_COUNT) { 755 status_t error = context->lowLevelHandler->HandleAttributeDone( 756 (BHPKGAttributeID)fID, fValue, fParentToken, fToken); 757 if (error != B_OK) 758 return error; 759 } 760 return super::NotifyDone(context); 761 } 762 763 764 // #pragma mark - ReaderImplBase 765 766 767 ReaderImplBase::ReaderImplBase(const char* fileType, BErrorOutput* errorOutput) 768 : 769 fPackageAttributesSection("package attributes"), 770 fFileType(fileType), 771 fErrorOutput(errorOutput), 772 fFile(NULL), 773 fOwnsFile(false), 774 fRawHeapReader(NULL), 775 fHeapReader(NULL), 776 fCurrentSection(NULL) 777 { 778 } 779 780 781 ReaderImplBase::~ReaderImplBase() 782 { 783 delete fHeapReader; 784 if (fRawHeapReader != fHeapReader) 785 delete fRawHeapReader; 786 787 if (fOwnsFile) 788 delete fFile; 789 } 790 791 792 uint64 793 ReaderImplBase::UncompressedHeapSize() const 794 { 795 return fRawHeapReader->UncompressedHeapSize(); 796 } 797 798 799 BAbstractBufferedDataReader* 800 ReaderImplBase::DetachHeapReader(PackageFileHeapReader*& _rawHeapReader) 801 { 802 BAbstractBufferedDataReader* heapReader = fHeapReader; 803 _rawHeapReader = fRawHeapReader; 804 fHeapReader = NULL; 805 fRawHeapReader = NULL; 806 807 return heapReader; 808 } 809 810 811 status_t 812 ReaderImplBase::InitHeapReader(uint32 compression, uint32 chunkSize, 813 off_t offset, uint64 compressedSize, uint64 uncompressedSize) 814 { 815 DecompressionAlgorithmOwner* decompressionAlgorithm = NULL; 816 BReference<DecompressionAlgorithmOwner> decompressionAlgorithmReference; 817 818 switch (compression) { 819 case B_HPKG_COMPRESSION_NONE: 820 break; 821 case B_HPKG_COMPRESSION_ZLIB: 822 decompressionAlgorithm = DecompressionAlgorithmOwner::Create( 823 new(std::nothrow) BZlibCompressionAlgorithm, 824 new(std::nothrow) BZlibDecompressionParameters); 825 decompressionAlgorithmReference.SetTo(decompressionAlgorithm, true); 826 if (decompressionAlgorithm == NULL 827 || decompressionAlgorithm->algorithm == NULL 828 || decompressionAlgorithm->parameters == NULL) { 829 return B_NO_MEMORY; 830 } 831 break; 832 #ifdef ZSTD_ENABLED 833 case B_HPKG_COMPRESSION_ZSTD: 834 decompressionAlgorithm = DecompressionAlgorithmOwner::Create( 835 new(std::nothrow) BZstdCompressionAlgorithm, 836 new(std::nothrow) BZstdDecompressionParameters); 837 decompressionAlgorithmReference.SetTo(decompressionAlgorithm, true); 838 if (decompressionAlgorithm == NULL 839 || decompressionAlgorithm->algorithm == NULL 840 || decompressionAlgorithm->parameters == NULL) { 841 return B_NO_MEMORY; 842 } 843 break; 844 #endif 845 default: 846 fErrorOutput->PrintError("Error: Invalid heap compression\n"); 847 return B_BAD_DATA; 848 } 849 850 fRawHeapReader = new(std::nothrow) PackageFileHeapReader(fErrorOutput, 851 fFile, offset, compressedSize, uncompressedSize, 852 decompressionAlgorithm); 853 if (fRawHeapReader == NULL) 854 return B_NO_MEMORY; 855 856 status_t error = fRawHeapReader->Init(); 857 if (error != B_OK) 858 return error; 859 860 error = CreateCachedHeapReader(fRawHeapReader, fHeapReader); 861 if (error != B_OK) { 862 if (error != B_NOT_SUPPORTED) 863 return error; 864 865 fHeapReader = fRawHeapReader; 866 } 867 868 return B_OK; 869 } 870 871 872 status_t 873 ReaderImplBase::CreateCachedHeapReader(PackageFileHeapReader* heapReader, 874 BAbstractBufferedDataReader*& _cachedReader) 875 { 876 return B_NOT_SUPPORTED; 877 } 878 879 880 status_t 881 ReaderImplBase::InitSection(PackageFileSection& section, uint64 endOffset, 882 uint64 length, uint64 maxSaneLength, uint64 stringsLength, 883 uint64 stringsCount) 884 { 885 // check length vs. endOffset 886 if (length > endOffset) { 887 ErrorOutput()->PrintError("Error: %s file %s section size is %" 888 B_PRIu64 " bytes. This is greater than the available space\n", 889 fFileType, section.name, length); 890 return B_BAD_DATA; 891 } 892 893 // check sanity length 894 if (maxSaneLength > 0 && length > maxSaneLength) { 895 ErrorOutput()->PrintError("Error: %s file %s section size is %" 896 B_PRIu64 " bytes. This is beyond the reader's sanity limit\n", 897 fFileType, section.name, length); 898 return B_NOT_SUPPORTED; 899 } 900 901 // check strings subsection size/count 902 if ((stringsLength <= 1) != (stringsCount == 0) || stringsLength > length) { 903 ErrorOutput()->PrintError("Error: strings subsection description of %s " 904 "file %s section is invalid (%" B_PRIu64 " strings, length: %" 905 B_PRIu64 ", section length: %" B_PRIu64 ")\n", 906 fFileType, section.name, stringsCount, stringsLength, length); 907 return B_BAD_DATA; 908 } 909 910 section.uncompressedLength = length; 911 section.offset = endOffset - length; 912 section.currentOffset = 0; 913 section.stringsLength = stringsLength; 914 section.stringsCount = stringsCount; 915 916 return B_OK; 917 } 918 919 920 status_t 921 ReaderImplBase::PrepareSection(PackageFileSection& section) 922 { 923 // allocate memory for the section data and read it in 924 section.data = new(std::nothrow) uint8[section.uncompressedLength]; 925 if (section.data == NULL) { 926 ErrorOutput()->PrintError("Error: Out of memory!\n"); 927 return B_NO_MEMORY; 928 } 929 930 status_t error = ReadSection(section); 931 if (error != B_OK) 932 return error; 933 934 // parse the section strings 935 section.currentOffset = 0; 936 SetCurrentSection(§ion); 937 938 error = ParseStrings(); 939 if (error != B_OK) 940 return error; 941 942 return B_OK; 943 } 944 945 946 status_t 947 ReaderImplBase::ParseStrings() 948 { 949 // allocate table, if there are any strings 950 if (fCurrentSection->stringsCount == 0) { 951 fCurrentSection->currentOffset += fCurrentSection->stringsLength; 952 return B_OK; 953 } 954 955 fCurrentSection->strings 956 = new(std::nothrow) char*[fCurrentSection->stringsCount]; 957 if (fCurrentSection->strings == NULL) { 958 fErrorOutput->PrintError("Error: Out of memory!\n"); 959 return B_NO_MEMORY; 960 } 961 962 // parse the section and fill the table 963 char* position 964 = (char*)fCurrentSection->data + fCurrentSection->currentOffset; 965 char* sectionEnd = position + fCurrentSection->stringsLength; 966 uint32 index = 0; 967 while (true) { 968 if (position >= sectionEnd) { 969 fErrorOutput->PrintError("Error: Malformed %s strings section\n", 970 fCurrentSection->name); 971 return B_BAD_DATA; 972 } 973 974 size_t stringLength = strnlen(position, (char*)sectionEnd - position); 975 976 if (stringLength == 0) { 977 if (position + 1 != sectionEnd) { 978 fErrorOutput->PrintError( 979 "Error: %ld excess bytes in %s strings section\n", 980 sectionEnd - (position + 1), fCurrentSection->name); 981 return B_BAD_DATA; 982 } 983 984 if (index != fCurrentSection->stringsCount) { 985 fErrorOutput->PrintError("Error: Invalid %s strings section: " 986 "Less strings (%lld) than specified in the header (%lld)\n", 987 fCurrentSection->name, index, 988 fCurrentSection->stringsCount); 989 return B_BAD_DATA; 990 } 991 992 fCurrentSection->currentOffset += fCurrentSection->stringsLength; 993 994 return B_OK; 995 } 996 997 if (index >= fCurrentSection->stringsCount) { 998 fErrorOutput->PrintError("Error: Invalid %s strings section: " 999 "More strings (%lld) than specified in the header (%lld)\n", 1000 fCurrentSection->name, index, fCurrentSection->stringsCount); 1001 return B_BAD_DATA; 1002 } 1003 1004 fCurrentSection->strings[index++] = position; 1005 position += stringLength + 1; 1006 } 1007 } 1008 1009 1010 status_t 1011 ReaderImplBase::ParsePackageAttributesSection( 1012 AttributeHandlerContext* context, AttributeHandler* rootAttributeHandler) 1013 { 1014 // parse package attributes 1015 SetCurrentSection(&fPackageAttributesSection); 1016 1017 // init the attribute handler stack 1018 rootAttributeHandler->SetLevel(0); 1019 ClearAttributeHandlerStack(); 1020 PushAttributeHandler(rootAttributeHandler); 1021 1022 bool sectionHandled; 1023 status_t error = ParseAttributeTree(context, sectionHandled); 1024 if (error == B_OK && sectionHandled) { 1025 if (fPackageAttributesSection.currentOffset 1026 < fPackageAttributesSection.uncompressedLength) { 1027 fErrorOutput->PrintError("Error: %llu excess byte(s) in package " 1028 "attributes section\n", 1029 fPackageAttributesSection.uncompressedLength 1030 - fPackageAttributesSection.currentOffset); 1031 error = B_BAD_DATA; 1032 } 1033 } 1034 1035 SetCurrentSection(NULL); 1036 1037 // clean up on error 1038 if (error != B_OK) { 1039 context->ErrorOccurred(); 1040 while (AttributeHandler* handler = PopAttributeHandler()) { 1041 if (handler != rootAttributeHandler) 1042 handler->Delete(context); 1043 } 1044 return error; 1045 } 1046 1047 return B_OK; 1048 } 1049 1050 1051 status_t 1052 ReaderImplBase::ParseAttributeTree(AttributeHandlerContext* context, 1053 bool& _sectionHandled) 1054 { 1055 if (context->hasLowLevelHandler) { 1056 bool handleSection = false; 1057 status_t error = context->lowLevelHandler->HandleSectionStart( 1058 context->section, handleSection); 1059 if (error != B_OK) 1060 return error; 1061 1062 if (!handleSection) { 1063 _sectionHandled = false; 1064 return B_OK; 1065 } 1066 } 1067 1068 status_t error = _ParseAttributeTree(context); 1069 1070 if (context->hasLowLevelHandler) { 1071 status_t endError = context->lowLevelHandler->HandleSectionEnd( 1072 context->section); 1073 if (error == B_OK) 1074 error = endError; 1075 } 1076 1077 _sectionHandled = true; 1078 return error; 1079 } 1080 1081 1082 status_t 1083 ReaderImplBase::_Init(BPositionIO* file, bool keepFile) 1084 { 1085 fFile = file; 1086 fOwnsFile = keepFile; 1087 return fFile != NULL ? B_OK : B_BAD_VALUE; 1088 } 1089 1090 1091 status_t 1092 ReaderImplBase::_ParseAttributeTree(AttributeHandlerContext* context) 1093 { 1094 int level = 0; 1095 1096 while (true) { 1097 uint8 id; 1098 AttributeValue value; 1099 bool hasChildren; 1100 uint64 tag; 1101 1102 status_t error = _ReadAttribute(id, value, &hasChildren, &tag); 1103 if (error != B_OK) 1104 return error; 1105 1106 if (tag == 0) { 1107 AttributeHandler* handler = PopAttributeHandler(); 1108 error = handler->NotifyDone(context); 1109 if (error != B_OK) 1110 return error; 1111 if (level-- == 0) 1112 return B_OK; 1113 1114 error = handler->Delete(context); 1115 if (error != B_OK) 1116 return error; 1117 1118 continue; 1119 } 1120 1121 AttributeHandler* childHandler = NULL; 1122 error = CurrentAttributeHandler()->HandleAttribute(context, id, value, 1123 hasChildren ? &childHandler : NULL); 1124 if (error != B_OK) 1125 return error; 1126 1127 // parse children 1128 if (hasChildren) { 1129 // create an ignore handler, if necessary 1130 if (childHandler == NULL) { 1131 childHandler = new(std::nothrow) IgnoreAttributeHandler; 1132 if (childHandler == NULL) { 1133 fErrorOutput->PrintError("Error: Out of memory!\n"); 1134 return B_NO_MEMORY; 1135 } 1136 } 1137 1138 childHandler->SetLevel(++level); 1139 PushAttributeHandler(childHandler); 1140 } 1141 } 1142 } 1143 1144 1145 status_t 1146 ReaderImplBase::_ReadAttribute(uint8& _id, AttributeValue& _value, 1147 bool* _hasChildren, uint64* _tag) 1148 { 1149 uint64 tag; 1150 status_t error = ReadUnsignedLEB128(tag); 1151 if (error != B_OK) 1152 return error; 1153 1154 if (tag != 0) { 1155 // get the type 1156 uint16 type = attribute_tag_type(tag); 1157 if (type >= B_HPKG_ATTRIBUTE_TYPE_ENUM_COUNT) { 1158 fErrorOutput->PrintError("Error: Invalid %s section: attribute " 1159 "type %d not supported!\n", fCurrentSection->name, type); 1160 return B_BAD_DATA; 1161 } 1162 1163 // get the ID 1164 _id = attribute_tag_id(tag); 1165 if (_id < B_HPKG_ATTRIBUTE_ID_ENUM_COUNT) { 1166 if (type != kAttributeTypes[_id]) { 1167 fErrorOutput->PrintError("Error: Invalid %s section: " 1168 "unexpected type %d for attribute id %d (expected %d)!\n", 1169 fCurrentSection->name, type, _id, kAttributeTypes[_id]); 1170 return B_BAD_DATA; 1171 } 1172 } else if (fMinorFormatVersion <= fCurrentMinorFormatVersion) { 1173 fErrorOutput->PrintError("Error: Invalid %s section: " 1174 "attribute id %d not supported!\n", fCurrentSection->name, _id); 1175 return B_BAD_DATA; 1176 } 1177 1178 // get the value 1179 error = ReadAttributeValue(type, attribute_tag_encoding(tag), 1180 _value); 1181 if (error != B_OK) 1182 return error; 1183 } 1184 1185 if (_hasChildren != NULL) 1186 *_hasChildren = attribute_tag_has_children(tag); 1187 if (_tag != NULL) 1188 *_tag = tag; 1189 1190 return B_OK; 1191 } 1192 1193 1194 status_t 1195 ReaderImplBase::ReadAttributeValue(uint8 type, uint8 encoding, 1196 AttributeValue& _value) 1197 { 1198 switch (type) { 1199 case B_HPKG_ATTRIBUTE_TYPE_INT: 1200 case B_HPKG_ATTRIBUTE_TYPE_UINT: 1201 { 1202 uint64 intValue; 1203 status_t error; 1204 1205 switch (encoding) { 1206 case B_HPKG_ATTRIBUTE_ENCODING_INT_8_BIT: 1207 { 1208 uint8 value; 1209 error = _Read(value); 1210 intValue = value; 1211 break; 1212 } 1213 case B_HPKG_ATTRIBUTE_ENCODING_INT_16_BIT: 1214 { 1215 uint16 value; 1216 error = _Read(value); 1217 intValue = B_BENDIAN_TO_HOST_INT16(value); 1218 break; 1219 } 1220 case B_HPKG_ATTRIBUTE_ENCODING_INT_32_BIT: 1221 { 1222 uint32 value; 1223 error = _Read(value); 1224 intValue = B_BENDIAN_TO_HOST_INT32(value); 1225 break; 1226 } 1227 case B_HPKG_ATTRIBUTE_ENCODING_INT_64_BIT: 1228 { 1229 uint64 value; 1230 error = _Read(value); 1231 intValue = B_BENDIAN_TO_HOST_INT64(value); 1232 break; 1233 } 1234 default: 1235 { 1236 fErrorOutput->PrintError("Error: Invalid %s section: " 1237 "invalid encoding %d for int value type %d\n", 1238 fCurrentSection->name, encoding, type); 1239 return B_BAD_VALUE; 1240 } 1241 } 1242 1243 if (error != B_OK) 1244 return error; 1245 1246 if (type == B_HPKG_ATTRIBUTE_TYPE_INT) 1247 _value.SetTo((int64)intValue); 1248 else 1249 _value.SetTo(intValue); 1250 1251 return B_OK; 1252 } 1253 1254 case B_HPKG_ATTRIBUTE_TYPE_STRING: 1255 { 1256 if (encoding == B_HPKG_ATTRIBUTE_ENCODING_STRING_TABLE) { 1257 uint64 index; 1258 status_t error = ReadUnsignedLEB128(index); 1259 if (error != B_OK) 1260 return error; 1261 1262 if (index > fCurrentSection->stringsCount) { 1263 fErrorOutput->PrintError("Error: Invalid %s section: " 1264 "string reference (%lld) out of bounds (%lld)\n", 1265 fCurrentSection->name, index, 1266 fCurrentSection->stringsCount); 1267 return B_BAD_DATA; 1268 } 1269 1270 _value.SetTo(fCurrentSection->strings[index]); 1271 } else if (encoding == B_HPKG_ATTRIBUTE_ENCODING_STRING_INLINE) { 1272 const char* string; 1273 status_t error = _ReadString(string); 1274 if (error != B_OK) 1275 return error; 1276 1277 _value.SetTo(string); 1278 } else { 1279 fErrorOutput->PrintError("Error: Invalid %s section: invalid " 1280 "string encoding (%u)\n", fCurrentSection->name, encoding); 1281 return B_BAD_DATA; 1282 } 1283 1284 return B_OK; 1285 } 1286 1287 default: 1288 fErrorOutput->PrintError("Error: Invalid %s section: invalid " 1289 "value type: %d\n", fCurrentSection->name, type); 1290 return B_BAD_DATA; 1291 } 1292 } 1293 1294 1295 status_t 1296 ReaderImplBase::ReadUnsignedLEB128(uint64& _value) 1297 { 1298 uint64 result = 0; 1299 int shift = 0; 1300 while (true) { 1301 uint8 byte; 1302 status_t error = _Read(byte); 1303 if (error != B_OK) 1304 return error; 1305 1306 result |= uint64(byte & 0x7f) << shift; 1307 if ((byte & 0x80) == 0) 1308 break; 1309 shift += 7; 1310 } 1311 1312 _value = result; 1313 return B_OK; 1314 } 1315 1316 1317 status_t 1318 ReaderImplBase::_ReadString(const char*& _string, size_t* _stringLength) 1319 { 1320 const char* string 1321 = (const char*)fCurrentSection->data + fCurrentSection->currentOffset; 1322 size_t stringLength = strnlen(string, 1323 fCurrentSection->uncompressedLength - fCurrentSection->currentOffset); 1324 1325 if (stringLength 1326 == fCurrentSection->uncompressedLength 1327 - fCurrentSection->currentOffset) { 1328 fErrorOutput->PrintError( 1329 "_ReadString(): string extends beyond %s end\n", 1330 fCurrentSection->name); 1331 return B_BAD_DATA; 1332 } 1333 1334 _string = string; 1335 if (_stringLength != NULL) 1336 *_stringLength = stringLength; 1337 1338 fCurrentSection->currentOffset += stringLength + 1; 1339 return B_OK; 1340 } 1341 1342 1343 status_t 1344 ReaderImplBase::_ReadSectionBuffer(void* buffer, size_t size) 1345 { 1346 if (size > fCurrentSection->uncompressedLength 1347 - fCurrentSection->currentOffset) { 1348 fErrorOutput->PrintError( 1349 "_ReadSectionBuffer(%lu): read beyond %s end\n", size, 1350 fCurrentSection->name); 1351 return B_BAD_DATA; 1352 } 1353 1354 memcpy(buffer, fCurrentSection->data + fCurrentSection->currentOffset, 1355 size); 1356 fCurrentSection->currentOffset += size; 1357 return B_OK; 1358 } 1359 1360 1361 status_t 1362 ReaderImplBase::ReadBuffer(off_t offset, void* buffer, size_t size) 1363 { 1364 status_t error = fFile->ReadAtExactly(offset, buffer, size); 1365 if (error != B_OK) { 1366 fErrorOutput->PrintError("_ReadBuffer(%p, %lu) failed to read data: " 1367 "%s\n", buffer, size, strerror(error)); 1368 return error; 1369 } 1370 1371 return B_OK; 1372 } 1373 1374 1375 status_t 1376 ReaderImplBase::ReadSection(const PackageFileSection& section) 1377 { 1378 return fHeapReader->ReadData(section.offset, 1379 section.data, section.uncompressedLength); 1380 } 1381 1382 1383 } // namespace BPrivate 1384 1385 } // namespace BHPKG 1386 1387 } // namespace BPackageKit 1388