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