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