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