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