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 size_t kScratchBufferSize = 64 * 1024; 39 40 static const uint16 kAttributeTypes[B_HPKG_ATTRIBUTE_ID_ENUM_COUNT] = { 41 #define B_DEFINE_HPKG_ATTRIBUTE(id, type, name, constant) \ 42 B_HPKG_ATTRIBUTE_TYPE_##type, 43 #include <package/hpkg/PackageAttributes.h> 44 #undef B_DEFINE_HPKG_ATTRIBUTE 45 }; 46 47 // #pragma mark - AttributeHandlerContext 48 49 50 ReaderImplBase::AttributeHandlerContext::AttributeHandlerContext( 51 BErrorOutput* errorOutput, BPackageContentHandler* packageContentHandler, 52 BHPKGPackageSectionID section, bool ignoreUnknownAttributes) 53 : 54 errorOutput(errorOutput), 55 packageContentHandler(packageContentHandler), 56 hasLowLevelHandler(false), 57 ignoreUnknownAttributes(ignoreUnknownAttributes), 58 section(section) 59 { 60 } 61 62 63 ReaderImplBase::AttributeHandlerContext::AttributeHandlerContext( 64 BErrorOutput* errorOutput, BLowLevelPackageContentHandler* lowLevelHandler, 65 BHPKGPackageSectionID section, bool ignoreUnknownAttributes) 66 : 67 errorOutput(errorOutput), 68 lowLevelHandler(lowLevelHandler), 69 hasLowLevelHandler(true), 70 ignoreUnknownAttributes(ignoreUnknownAttributes), 71 section(section) 72 { 73 } 74 75 76 void 77 ReaderImplBase::AttributeHandlerContext::ErrorOccurred() 78 { 79 if (hasLowLevelHandler) 80 lowLevelHandler->HandleErrorOccurred(); 81 else 82 packageContentHandler->HandleErrorOccurred(); 83 } 84 85 86 // #pragma mark - AttributeHandler 87 88 89 ReaderImplBase::AttributeHandler::~AttributeHandler() 90 { 91 } 92 93 94 void 95 ReaderImplBase::AttributeHandler::SetLevel(int level) 96 { 97 fLevel = level; 98 } 99 100 101 status_t 102 ReaderImplBase::AttributeHandler::HandleAttribute( 103 AttributeHandlerContext* context, uint8 id, const AttributeValue& value, 104 AttributeHandler** _handler) 105 { 106 return B_OK; 107 } 108 109 110 status_t 111 ReaderImplBase::AttributeHandler::NotifyDone( 112 AttributeHandlerContext* context) 113 { 114 return B_OK; 115 } 116 117 118 status_t 119 ReaderImplBase::AttributeHandler::Delete(AttributeHandlerContext* context) 120 { 121 delete this; 122 return B_OK; 123 } 124 125 126 // #pragma mark - PackageInfoAttributeHandlerBase 127 128 129 ReaderImplBase::PackageInfoAttributeHandlerBase 130 ::PackageInfoAttributeHandlerBase( 131 BPackageInfoAttributeValue& packageInfoValue) 132 : 133 fPackageInfoValue(packageInfoValue) 134 { 135 } 136 137 138 status_t 139 ReaderImplBase::PackageInfoAttributeHandlerBase::NotifyDone( 140 AttributeHandlerContext* context) 141 { 142 status_t error = context->packageContentHandler->HandlePackageAttribute( 143 fPackageInfoValue); 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 fPackageInfoValue.Clear(); 687 if (error != B_OK) 688 return error; 689 } 690 691 return B_OK; 692 } 693 694 695 // #pragma mark - LowLevelAttributeHandler 696 697 698 ReaderImplBase::LowLevelAttributeHandler::LowLevelAttributeHandler() 699 : 700 fParentToken(NULL), 701 fToken(NULL), 702 fID(B_HPKG_ATTRIBUTE_ID_ENUM_COUNT) 703 { 704 } 705 706 707 ReaderImplBase::LowLevelAttributeHandler::LowLevelAttributeHandler(uint8 id, 708 const BPackageAttributeValue& value, void* parentToken, void* token) 709 : 710 fParentToken(NULL), 711 fToken(token), 712 fID(id), 713 fValue(value) 714 { 715 } 716 717 718 status_t 719 ReaderImplBase::LowLevelAttributeHandler::HandleAttribute( 720 AttributeHandlerContext* context, uint8 id, const AttributeValue& value, 721 AttributeHandler** _handler) 722 { 723 // notify the content handler 724 void* token; 725 status_t error = context->lowLevelHandler->HandleAttribute( 726 (BHPKGAttributeID)id, value, fToken, token); 727 if (error != B_OK) 728 return error; 729 730 // create a subhandler for the attribute, if it has children 731 if (_handler != NULL) { 732 *_handler = new(std::nothrow) LowLevelAttributeHandler(id, value, 733 fToken, token); 734 if (*_handler == NULL) { 735 context->lowLevelHandler->HandleAttributeDone((BHPKGAttributeID)id, 736 value, fToken, token); 737 return B_NO_MEMORY; 738 } 739 return B_OK; 740 } 741 742 // no children -- just call the done hook 743 return context->lowLevelHandler->HandleAttributeDone((BHPKGAttributeID)id, 744 value, fToken, token); 745 } 746 747 748 status_t 749 ReaderImplBase::LowLevelAttributeHandler::NotifyDone( 750 AttributeHandlerContext* context) 751 { 752 if (fID != B_HPKG_ATTRIBUTE_ID_ENUM_COUNT) { 753 status_t error = context->lowLevelHandler->HandleAttributeDone( 754 (BHPKGAttributeID)fID, fValue, fParentToken, fToken); 755 if (error != B_OK) 756 return error; 757 } 758 return super::NotifyDone(context); 759 } 760 761 762 // #pragma mark - ReaderImplBase 763 764 765 ReaderImplBase::ReaderImplBase(const char* fileType, BErrorOutput* errorOutput) 766 : 767 fPackageAttributesSection("package attributes"), 768 fFileType(fileType), 769 fErrorOutput(errorOutput), 770 fFile(NULL), 771 fOwnsFile(false), 772 fRawHeapReader(NULL), 773 fHeapReader(NULL), 774 fCurrentSection(NULL) 775 { 776 } 777 778 779 ReaderImplBase::~ReaderImplBase() 780 { 781 delete fHeapReader; 782 if (fRawHeapReader != fHeapReader) 783 delete fRawHeapReader; 784 785 if (fOwnsFile) 786 delete fFile; 787 } 788 789 790 uint64 791 ReaderImplBase::UncompressedHeapSize() const 792 { 793 return fRawHeapReader->UncompressedHeapSize(); 794 } 795 796 797 BAbstractBufferedDataReader* 798 ReaderImplBase::DetachHeapReader(PackageFileHeapReader*& _rawHeapReader) 799 { 800 BAbstractBufferedDataReader* heapReader = fHeapReader; 801 _rawHeapReader = fRawHeapReader; 802 fHeapReader = NULL; 803 fRawHeapReader = NULL; 804 805 return heapReader; 806 } 807 808 809 status_t 810 ReaderImplBase::InitHeapReader(uint32 compression, uint32 chunkSize, 811 off_t offset, uint64 compressedSize, uint64 uncompressedSize) 812 { 813 DecompressionAlgorithmOwner* decompressionAlgorithm = NULL; 814 BReference<DecompressionAlgorithmOwner> decompressionAlgorithmReference; 815 816 switch (compression) { 817 case B_HPKG_COMPRESSION_NONE: 818 break; 819 case B_HPKG_COMPRESSION_ZLIB: 820 decompressionAlgorithm = DecompressionAlgorithmOwner::Create( 821 new(std::nothrow) BZlibCompressionAlgorithm, 822 new(std::nothrow) BZlibDecompressionParameters); 823 decompressionAlgorithmReference.SetTo(decompressionAlgorithm, true); 824 if (decompressionAlgorithm == NULL 825 || decompressionAlgorithm->algorithm == NULL 826 || decompressionAlgorithm->parameters == NULL) { 827 return B_NO_MEMORY; 828 } 829 break; 830 #ifdef ZSTD_ENABLED 831 case B_HPKG_COMPRESSION_ZSTD: 832 decompressionAlgorithm = DecompressionAlgorithmOwner::Create( 833 new(std::nothrow) BZstdCompressionAlgorithm, 834 new(std::nothrow) BZstdDecompressionParameters); 835 decompressionAlgorithmReference.SetTo(decompressionAlgorithm, true); 836 if (decompressionAlgorithm == NULL 837 || decompressionAlgorithm->algorithm == NULL 838 || decompressionAlgorithm->parameters == NULL) { 839 return B_NO_MEMORY; 840 } 841 break; 842 #endif 843 default: 844 fErrorOutput->PrintError("Error: Invalid heap compression\n"); 845 return B_BAD_DATA; 846 } 847 848 fRawHeapReader = new(std::nothrow) PackageFileHeapReader(fErrorOutput, 849 fFile, offset, compressedSize, uncompressedSize, 850 decompressionAlgorithm); 851 if (fRawHeapReader == NULL) 852 return B_NO_MEMORY; 853 854 status_t error = fRawHeapReader->Init(); 855 if (error != B_OK) 856 return error; 857 858 error = CreateCachedHeapReader(fRawHeapReader, fHeapReader); 859 if (error != B_OK) { 860 if (error != B_NOT_SUPPORTED) 861 return error; 862 863 fHeapReader = fRawHeapReader; 864 } 865 866 return B_OK; 867 } 868 869 870 status_t 871 ReaderImplBase::CreateCachedHeapReader(PackageFileHeapReader* heapReader, 872 BAbstractBufferedDataReader*& _cachedReader) 873 { 874 return B_NOT_SUPPORTED; 875 } 876 877 878 status_t 879 ReaderImplBase::InitSection(PackageFileSection& section, uint64 endOffset, 880 uint64 length, uint64 maxSaneLength, uint64 stringsLength, 881 uint64 stringsCount) 882 { 883 // check length vs. endOffset 884 if (length > endOffset) { 885 ErrorOutput()->PrintError("Error: %s file %s section size is %" 886 B_PRIu64 " bytes. This is greater than the available space\n", 887 fFileType, section.name, length); 888 return B_BAD_DATA; 889 } 890 891 // check sanity length 892 if (maxSaneLength > 0 && length > maxSaneLength) { 893 ErrorOutput()->PrintError("Error: %s file %s section size is %" 894 B_PRIu64 " bytes. This is beyond the reader's sanity limit\n", 895 fFileType, section.name, length); 896 return B_NOT_SUPPORTED; 897 } 898 899 // check strings subsection size/count 900 if ((stringsLength <= 1) != (stringsCount == 0) || stringsLength > length) { 901 ErrorOutput()->PrintError("Error: strings subsection description of %s " 902 "file %s section is invalid (%" B_PRIu64 " strings, length: %" 903 B_PRIu64 ", section length: %" B_PRIu64 ")\n", 904 fFileType, section.name, stringsCount, stringsLength, length); 905 return B_BAD_DATA; 906 } 907 908 section.uncompressedLength = length; 909 section.offset = endOffset - length; 910 section.currentOffset = 0; 911 section.stringsLength = stringsLength; 912 section.stringsCount = stringsCount; 913 914 return B_OK; 915 } 916 917 918 status_t 919 ReaderImplBase::PrepareSection(PackageFileSection& section) 920 { 921 // allocate memory for the section data and read it in 922 section.data = new(std::nothrow) uint8[section.uncompressedLength]; 923 if (section.data == NULL) { 924 ErrorOutput()->PrintError("Error: Out of memory!\n"); 925 return B_NO_MEMORY; 926 } 927 928 status_t error = ReadSection(section); 929 if (error != B_OK) 930 return error; 931 932 // parse the section strings 933 section.currentOffset = 0; 934 SetCurrentSection(§ion); 935 936 error = ParseStrings(); 937 if (error != B_OK) 938 return error; 939 940 return B_OK; 941 } 942 943 944 status_t 945 ReaderImplBase::ParseStrings() 946 { 947 // allocate table, if there are any strings 948 if (fCurrentSection->stringsCount == 0) { 949 fCurrentSection->currentOffset += fCurrentSection->stringsLength; 950 return B_OK; 951 } 952 953 fCurrentSection->strings 954 = new(std::nothrow) char*[fCurrentSection->stringsCount]; 955 if (fCurrentSection->strings == NULL) { 956 fErrorOutput->PrintError("Error: Out of memory!\n"); 957 return B_NO_MEMORY; 958 } 959 960 // parse the section and fill the table 961 char* position 962 = (char*)fCurrentSection->data + fCurrentSection->currentOffset; 963 char* sectionEnd = position + fCurrentSection->stringsLength; 964 uint32 index = 0; 965 while (true) { 966 if (position >= sectionEnd) { 967 fErrorOutput->PrintError("Error: Malformed %s strings section\n", 968 fCurrentSection->name); 969 return B_BAD_DATA; 970 } 971 972 size_t stringLength = strnlen(position, (char*)sectionEnd - position); 973 974 if (stringLength == 0) { 975 if (position + 1 != sectionEnd) { 976 fErrorOutput->PrintError( 977 "Error: %ld excess bytes in %s strings section\n", 978 sectionEnd - (position + 1), fCurrentSection->name); 979 return B_BAD_DATA; 980 } 981 982 if (index != fCurrentSection->stringsCount) { 983 fErrorOutput->PrintError("Error: Invalid %s strings section: " 984 "Less strings (%lld) than specified in the header (%lld)\n", 985 fCurrentSection->name, index, 986 fCurrentSection->stringsCount); 987 return B_BAD_DATA; 988 } 989 990 fCurrentSection->currentOffset += fCurrentSection->stringsLength; 991 992 return B_OK; 993 } 994 995 if (index >= fCurrentSection->stringsCount) { 996 fErrorOutput->PrintError("Error: Invalid %s strings section: " 997 "More strings (%lld) than specified in the header (%lld)\n", 998 fCurrentSection->name, index, fCurrentSection->stringsCount); 999 return B_BAD_DATA; 1000 } 1001 1002 fCurrentSection->strings[index++] = position; 1003 position += stringLength + 1; 1004 } 1005 } 1006 1007 1008 status_t 1009 ReaderImplBase::ParsePackageAttributesSection( 1010 AttributeHandlerContext* context, AttributeHandler* rootAttributeHandler) 1011 { 1012 // parse package attributes 1013 SetCurrentSection(&fPackageAttributesSection); 1014 1015 // init the attribute handler stack 1016 rootAttributeHandler->SetLevel(0); 1017 ClearAttributeHandlerStack(); 1018 PushAttributeHandler(rootAttributeHandler); 1019 1020 bool sectionHandled; 1021 status_t error = ParseAttributeTree(context, sectionHandled); 1022 if (error == B_OK && sectionHandled) { 1023 if (fPackageAttributesSection.currentOffset 1024 < fPackageAttributesSection.uncompressedLength) { 1025 fErrorOutput->PrintError("Error: %llu excess byte(s) in package " 1026 "attributes section\n", 1027 fPackageAttributesSection.uncompressedLength 1028 - fPackageAttributesSection.currentOffset); 1029 error = B_BAD_DATA; 1030 } 1031 } 1032 1033 SetCurrentSection(NULL); 1034 1035 // clean up on error 1036 if (error != B_OK) { 1037 context->ErrorOccurred(); 1038 while (AttributeHandler* handler = PopAttributeHandler()) { 1039 if (handler != rootAttributeHandler) 1040 handler->Delete(context); 1041 } 1042 return error; 1043 } 1044 1045 return B_OK; 1046 } 1047 1048 1049 status_t 1050 ReaderImplBase::ParseAttributeTree(AttributeHandlerContext* context, 1051 bool& _sectionHandled) 1052 { 1053 if (context->hasLowLevelHandler) { 1054 bool handleSection = false; 1055 status_t error = context->lowLevelHandler->HandleSectionStart( 1056 context->section, handleSection); 1057 if (error != B_OK) 1058 return error; 1059 1060 if (!handleSection) { 1061 _sectionHandled = false; 1062 return B_OK; 1063 } 1064 } 1065 1066 status_t error = _ParseAttributeTree(context); 1067 1068 if (context->hasLowLevelHandler) { 1069 status_t endError = context->lowLevelHandler->HandleSectionEnd( 1070 context->section); 1071 if (error == B_OK) 1072 error = endError; 1073 } 1074 1075 _sectionHandled = true; 1076 return error; 1077 } 1078 1079 1080 status_t 1081 ReaderImplBase::_Init(BPositionIO* file, bool keepFile) 1082 { 1083 fFile = file; 1084 fOwnsFile = keepFile; 1085 return fFile != NULL ? B_OK : B_BAD_VALUE; 1086 } 1087 1088 1089 status_t 1090 ReaderImplBase::_ParseAttributeTree(AttributeHandlerContext* context) 1091 { 1092 int level = 0; 1093 1094 while (true) { 1095 uint8 id; 1096 AttributeValue value; 1097 bool hasChildren; 1098 uint64 tag; 1099 1100 status_t error = _ReadAttribute(id, value, &hasChildren, &tag); 1101 if (error != B_OK) 1102 return error; 1103 1104 if (tag == 0) { 1105 AttributeHandler* handler = PopAttributeHandler(); 1106 error = handler->NotifyDone(context); 1107 if (error != B_OK) 1108 return error; 1109 if (level-- == 0) 1110 return B_OK; 1111 1112 error = handler->Delete(context); 1113 if (error != B_OK) 1114 return error; 1115 1116 continue; 1117 } 1118 1119 AttributeHandler* childHandler = NULL; 1120 error = CurrentAttributeHandler()->HandleAttribute(context, id, value, 1121 hasChildren ? &childHandler : NULL); 1122 if (error != B_OK) 1123 return error; 1124 1125 // parse children 1126 if (hasChildren) { 1127 // create an ignore handler, if necessary 1128 if (childHandler == NULL) { 1129 childHandler = new(std::nothrow) IgnoreAttributeHandler; 1130 if (childHandler == NULL) { 1131 fErrorOutput->PrintError("Error: Out of memory!\n"); 1132 return B_NO_MEMORY; 1133 } 1134 } 1135 1136 childHandler->SetLevel(++level); 1137 PushAttributeHandler(childHandler); 1138 } 1139 } 1140 } 1141 1142 1143 status_t 1144 ReaderImplBase::_ReadAttribute(uint8& _id, AttributeValue& _value, 1145 bool* _hasChildren, uint64* _tag) 1146 { 1147 uint64 tag; 1148 status_t error = ReadUnsignedLEB128(tag); 1149 if (error != B_OK) 1150 return error; 1151 1152 if (tag != 0) { 1153 // get the type 1154 uint16 type = attribute_tag_type(tag); 1155 if (type >= B_HPKG_ATTRIBUTE_TYPE_ENUM_COUNT) { 1156 fErrorOutput->PrintError("Error: Invalid %s section: attribute " 1157 "type %d not supported!\n", fCurrentSection->name, type); 1158 return B_BAD_DATA; 1159 } 1160 1161 // get the ID 1162 _id = attribute_tag_id(tag); 1163 if (_id < B_HPKG_ATTRIBUTE_ID_ENUM_COUNT) { 1164 if (type != kAttributeTypes[_id]) { 1165 fErrorOutput->PrintError("Error: Invalid %s section: " 1166 "unexpected type %d for attribute id %d (expected %d)!\n", 1167 fCurrentSection->name, type, _id, kAttributeTypes[_id]); 1168 return B_BAD_DATA; 1169 } 1170 } else if (fMinorFormatVersion <= fCurrentMinorFormatVersion) { 1171 fErrorOutput->PrintError("Error: Invalid %s section: " 1172 "attribute id %d not supported!\n", fCurrentSection->name, _id); 1173 return B_BAD_DATA; 1174 } 1175 1176 // get the value 1177 error = ReadAttributeValue(type, attribute_tag_encoding(tag), 1178 _value); 1179 if (error != B_OK) 1180 return error; 1181 } 1182 1183 if (_hasChildren != NULL) 1184 *_hasChildren = attribute_tag_has_children(tag); 1185 if (_tag != NULL) 1186 *_tag = tag; 1187 1188 return B_OK; 1189 } 1190 1191 1192 status_t 1193 ReaderImplBase::ReadAttributeValue(uint8 type, uint8 encoding, 1194 AttributeValue& _value) 1195 { 1196 switch (type) { 1197 case B_HPKG_ATTRIBUTE_TYPE_INT: 1198 case B_HPKG_ATTRIBUTE_TYPE_UINT: 1199 { 1200 uint64 intValue; 1201 status_t error; 1202 1203 switch (encoding) { 1204 case B_HPKG_ATTRIBUTE_ENCODING_INT_8_BIT: 1205 { 1206 uint8 value; 1207 error = _Read(value); 1208 intValue = value; 1209 break; 1210 } 1211 case B_HPKG_ATTRIBUTE_ENCODING_INT_16_BIT: 1212 { 1213 uint16 value; 1214 error = _Read(value); 1215 intValue = B_BENDIAN_TO_HOST_INT16(value); 1216 break; 1217 } 1218 case B_HPKG_ATTRIBUTE_ENCODING_INT_32_BIT: 1219 { 1220 uint32 value; 1221 error = _Read(value); 1222 intValue = B_BENDIAN_TO_HOST_INT32(value); 1223 break; 1224 } 1225 case B_HPKG_ATTRIBUTE_ENCODING_INT_64_BIT: 1226 { 1227 uint64 value; 1228 error = _Read(value); 1229 intValue = B_BENDIAN_TO_HOST_INT64(value); 1230 break; 1231 } 1232 default: 1233 { 1234 fErrorOutput->PrintError("Error: Invalid %s section: " 1235 "invalid encoding %d for int value type %d\n", 1236 fCurrentSection->name, encoding, type); 1237 return B_BAD_VALUE; 1238 } 1239 } 1240 1241 if (error != B_OK) 1242 return error; 1243 1244 if (type == B_HPKG_ATTRIBUTE_TYPE_INT) 1245 _value.SetTo((int64)intValue); 1246 else 1247 _value.SetTo(intValue); 1248 1249 return B_OK; 1250 } 1251 1252 case B_HPKG_ATTRIBUTE_TYPE_STRING: 1253 { 1254 if (encoding == B_HPKG_ATTRIBUTE_ENCODING_STRING_TABLE) { 1255 uint64 index; 1256 status_t error = ReadUnsignedLEB128(index); 1257 if (error != B_OK) 1258 return error; 1259 1260 if (index > fCurrentSection->stringsCount) { 1261 fErrorOutput->PrintError("Error: Invalid %s section: " 1262 "string reference (%lld) out of bounds (%lld)\n", 1263 fCurrentSection->name, index, 1264 fCurrentSection->stringsCount); 1265 return B_BAD_DATA; 1266 } 1267 1268 _value.SetTo(fCurrentSection->strings[index]); 1269 } else if (encoding == B_HPKG_ATTRIBUTE_ENCODING_STRING_INLINE) { 1270 const char* string; 1271 status_t error = _ReadString(string); 1272 if (error != B_OK) 1273 return error; 1274 1275 _value.SetTo(string); 1276 } else { 1277 fErrorOutput->PrintError("Error: Invalid %s section: invalid " 1278 "string encoding (%u)\n", fCurrentSection->name, encoding); 1279 return B_BAD_DATA; 1280 } 1281 1282 return B_OK; 1283 } 1284 1285 default: 1286 fErrorOutput->PrintError("Error: Invalid %s section: invalid " 1287 "value type: %d\n", fCurrentSection->name, type); 1288 return B_BAD_DATA; 1289 } 1290 } 1291 1292 1293 status_t 1294 ReaderImplBase::ReadUnsignedLEB128(uint64& _value) 1295 { 1296 uint64 result = 0; 1297 int shift = 0; 1298 while (true) { 1299 uint8 byte; 1300 status_t error = _Read(byte); 1301 if (error != B_OK) 1302 return error; 1303 1304 result |= uint64(byte & 0x7f) << shift; 1305 if ((byte & 0x80) == 0) 1306 break; 1307 shift += 7; 1308 } 1309 1310 _value = result; 1311 return B_OK; 1312 } 1313 1314 1315 status_t 1316 ReaderImplBase::_ReadString(const char*& _string, size_t* _stringLength) 1317 { 1318 const char* string 1319 = (const char*)fCurrentSection->data + fCurrentSection->currentOffset; 1320 size_t stringLength = strnlen(string, 1321 fCurrentSection->uncompressedLength - fCurrentSection->currentOffset); 1322 1323 if (stringLength 1324 == fCurrentSection->uncompressedLength 1325 - fCurrentSection->currentOffset) { 1326 fErrorOutput->PrintError( 1327 "_ReadString(): string extends beyond %s end\n", 1328 fCurrentSection->name); 1329 return B_BAD_DATA; 1330 } 1331 1332 _string = string; 1333 if (_stringLength != NULL) 1334 *_stringLength = stringLength; 1335 1336 fCurrentSection->currentOffset += stringLength + 1; 1337 return B_OK; 1338 } 1339 1340 1341 status_t 1342 ReaderImplBase::_ReadSectionBuffer(void* buffer, size_t size) 1343 { 1344 if (size > fCurrentSection->uncompressedLength 1345 - fCurrentSection->currentOffset) { 1346 fErrorOutput->PrintError( 1347 "_ReadSectionBuffer(%lu): read beyond %s end\n", size, 1348 fCurrentSection->name); 1349 return B_BAD_DATA; 1350 } 1351 1352 memcpy(buffer, fCurrentSection->data + fCurrentSection->currentOffset, 1353 size); 1354 fCurrentSection->currentOffset += size; 1355 return B_OK; 1356 } 1357 1358 1359 status_t 1360 ReaderImplBase::ReadBuffer(off_t offset, void* buffer, size_t size) 1361 { 1362 status_t error = fFile->ReadAtExactly(offset, buffer, size); 1363 if (error != B_OK) { 1364 fErrorOutput->PrintError("_ReadBuffer(%p, %lu) failed to read data: " 1365 "%s\n", buffer, size, strerror(error)); 1366 return error; 1367 } 1368 1369 return B_OK; 1370 } 1371 1372 1373 status_t 1374 ReaderImplBase::ReadSection(const PackageFileSection& section) 1375 { 1376 return fHeapReader->ReadData(section.offset, 1377 section.data, section.uncompressedLength); 1378 } 1379 1380 1381 } // namespace BPrivate 1382 1383 } // namespace BHPKG 1384 1385 } // namespace BPackageKit 1386