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