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