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