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