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