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/ErrorOutput.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 37 // #pragma mark - AttributeHandlerContext 38 39 40 ReaderImplBase::AttributeHandlerContext::AttributeHandlerContext( 41 BErrorOutput* errorOutput, BPackageContentHandler* packageContentHandler, 42 BHPKGPackageSectionID section) 43 : 44 errorOutput(errorOutput), 45 packageContentHandler(packageContentHandler), 46 hasLowLevelHandler(false), 47 section(section) 48 { 49 } 50 51 52 ReaderImplBase::AttributeHandlerContext::AttributeHandlerContext( 53 BErrorOutput* errorOutput, BLowLevelPackageContentHandler* lowLevelHandler, 54 BHPKGPackageSectionID section) 55 : 56 errorOutput(errorOutput), 57 lowLevelHandler(lowLevelHandler), 58 hasLowLevelHandler(true), 59 section(section) 60 { 61 } 62 63 64 void 65 ReaderImplBase::AttributeHandlerContext::ErrorOccurred() 66 { 67 if (hasLowLevelHandler) 68 lowLevelHandler->HandleErrorOccurred(); 69 else 70 packageContentHandler->HandleErrorOccurred(); 71 } 72 73 74 // #pragma mark - AttributeHandler 75 76 77 ReaderImplBase::AttributeHandler::~AttributeHandler() 78 { 79 } 80 81 82 void 83 ReaderImplBase::AttributeHandler::SetLevel(int level) 84 { 85 fLevel = level; 86 } 87 88 89 status_t 90 ReaderImplBase::AttributeHandler::HandleAttribute( 91 AttributeHandlerContext* context, uint8 id, const AttributeValue& value, 92 AttributeHandler** _handler) 93 { 94 return B_OK; 95 } 96 97 98 status_t 99 ReaderImplBase::AttributeHandler::Delete(AttributeHandlerContext* context) 100 { 101 delete this; 102 return B_OK; 103 } 104 105 106 // #pragma mark - PackageVersionAttributeHandler 107 108 109 ReaderImplBase::PackageVersionAttributeHandler::PackageVersionAttributeHandler( 110 BPackageInfoAttributeValue& packageInfoValue, 111 BPackageVersionData& versionData, bool notify) 112 : 113 fPackageInfoValue(packageInfoValue), 114 fPackageVersionData(versionData), 115 fNotify(notify) 116 { 117 } 118 119 120 status_t 121 ReaderImplBase::PackageVersionAttributeHandler::HandleAttribute( 122 AttributeHandlerContext* context, uint8 id, const AttributeValue& value, 123 AttributeHandler** _handler) 124 { 125 switch (id) { 126 case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_MINOR: 127 fPackageVersionData.minor = value.string; 128 break; 129 130 case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_MICRO: 131 fPackageVersionData.micro = value.string; 132 break; 133 134 case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_PRE_RELEASE: 135 fPackageVersionData.preRelease = value.string; 136 break; 137 138 case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_RELEASE: 139 fPackageVersionData.release = value.unsignedInt; 140 break; 141 142 default: 143 context->errorOutput->PrintError("Error: Invalid package " 144 "attribute section: unexpected package attribute id %d " 145 "encountered when parsing package version\n", id); 146 return B_BAD_DATA; 147 } 148 149 return B_OK; 150 } 151 152 153 status_t 154 ReaderImplBase::PackageVersionAttributeHandler::Delete( 155 AttributeHandlerContext* context) 156 { 157 status_t error = B_OK; 158 if (fNotify) { 159 fPackageInfoValue.attributeID = B_PACKAGE_INFO_VERSION; 160 error = context->packageContentHandler->HandlePackageAttribute( 161 fPackageInfoValue); 162 fPackageInfoValue.Clear(); 163 } 164 165 delete this; 166 return error; 167 } 168 169 170 // #pragma mark - PackageResolvableAttributeHandler 171 172 173 ReaderImplBase::PackageResolvableAttributeHandler 174 ::PackageResolvableAttributeHandler( 175 BPackageInfoAttributeValue& packageInfoValue) 176 : 177 fPackageInfoValue(packageInfoValue) 178 { 179 } 180 181 182 status_t 183 ReaderImplBase::PackageResolvableAttributeHandler::HandleAttribute( 184 AttributeHandlerContext* context, uint8 id, const AttributeValue& value, 185 AttributeHandler** _handler) 186 { 187 switch (id) { 188 case B_HPKG_ATTRIBUTE_ID_PACKAGE_PROVIDES_TYPE: 189 fPackageInfoValue.resolvable.type 190 = (BPackageResolvableType)value.unsignedInt; 191 break; 192 193 case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_MAJOR: 194 fPackageInfoValue.resolvable.haveVersion = true; 195 fPackageInfoValue.resolvable.version.major = value.string; 196 if (_handler != NULL) { 197 *_handler 198 = new(std::nothrow) PackageVersionAttributeHandler( 199 fPackageInfoValue, 200 fPackageInfoValue.resolvable.version, false); 201 if (*_handler == NULL) 202 return B_NO_MEMORY; 203 } 204 break; 205 206 case B_HPKG_ATTRIBUTE_ID_PACKAGE_PROVIDES_COMPATIBLE: 207 fPackageInfoValue.resolvable.haveCompatibleVersion = true; 208 fPackageInfoValue.resolvable.compatibleVersion.major = value.string; 209 if (_handler != NULL) { 210 *_handler 211 = new(std::nothrow) PackageVersionAttributeHandler( 212 fPackageInfoValue, 213 fPackageInfoValue.resolvable.compatibleVersion, false); 214 if (*_handler == NULL) 215 return B_NO_MEMORY; 216 } 217 break; 218 219 default: 220 context->errorOutput->PrintError("Error: Invalid package " 221 "attribute section: unexpected package attribute id %d " 222 "encountered when parsing package resolvable\n", id); 223 return B_BAD_DATA; 224 } 225 226 return B_OK; 227 } 228 229 230 status_t 231 ReaderImplBase::PackageResolvableAttributeHandler::Delete( 232 AttributeHandlerContext* context) 233 { 234 status_t error = context->packageContentHandler->HandlePackageAttribute( 235 fPackageInfoValue); 236 fPackageInfoValue.Clear(); 237 238 delete this; 239 return error; 240 } 241 242 243 // #pragma mark - PackageResolvableExpressionAttributeHandler 244 245 246 ReaderImplBase::PackageResolvableExpressionAttributeHandler 247 ::PackageResolvableExpressionAttributeHandler( 248 BPackageInfoAttributeValue& packageInfoValue) 249 : 250 fPackageInfoValue(packageInfoValue) 251 { 252 } 253 254 255 status_t 256 ReaderImplBase::PackageResolvableExpressionAttributeHandler::HandleAttribute( 257 AttributeHandlerContext* context, uint8 id, const AttributeValue& value, 258 AttributeHandler** _handler) 259 { 260 switch (id) { 261 case B_HPKG_ATTRIBUTE_ID_PACKAGE_RESOLVABLE_OPERATOR: 262 if (value.unsignedInt >= B_PACKAGE_RESOLVABLE_OP_ENUM_COUNT) { 263 context->errorOutput->PrintError( 264 "Error: Invalid package attribute section: invalid " 265 "package resolvable operator %lld encountered\n", 266 value.unsignedInt); 267 return B_BAD_DATA; 268 } 269 fPackageInfoValue.resolvableExpression.op 270 = (BPackageResolvableOperator)value.unsignedInt; 271 break; 272 273 case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_MAJOR: 274 fPackageInfoValue.resolvableExpression.haveOpAndVersion = true; 275 fPackageInfoValue.resolvableExpression.version.major 276 = value.string; 277 if (_handler != NULL) { 278 *_handler 279 = new(std::nothrow) PackageVersionAttributeHandler( 280 fPackageInfoValue, 281 fPackageInfoValue.resolvableExpression.version, 282 false); 283 if (*_handler == NULL) 284 return B_NO_MEMORY; 285 } 286 return B_OK; 287 288 default: 289 context->errorOutput->PrintError("Error: Invalid package " 290 "attribute section: unexpected package attribute id %d " 291 "encountered when parsing package resolvable-expression\n", 292 id); 293 return B_BAD_DATA; 294 } 295 296 return B_OK; 297 } 298 299 300 status_t 301 ReaderImplBase::PackageResolvableExpressionAttributeHandler::Delete( 302 AttributeHandlerContext* context) 303 { 304 status_t error = context->packageContentHandler->HandlePackageAttribute( 305 fPackageInfoValue); 306 fPackageInfoValue.Clear(); 307 308 delete this; 309 return error; 310 } 311 312 313 // #pragma mark - PackageAttributeHandler 314 315 316 status_t 317 ReaderImplBase::PackageAttributeHandler::HandleAttribute( 318 AttributeHandlerContext* context, uint8 id, const AttributeValue& value, 319 AttributeHandler** _handler) 320 { 321 switch (id) { 322 case B_HPKG_ATTRIBUTE_ID_PACKAGE_NAME: 323 fPackageInfoValue.SetTo(B_PACKAGE_INFO_NAME, value.string); 324 break; 325 326 case B_HPKG_ATTRIBUTE_ID_PACKAGE_SUMMARY: 327 fPackageInfoValue.SetTo(B_PACKAGE_INFO_SUMMARY, value.string); 328 break; 329 330 case B_HPKG_ATTRIBUTE_ID_PACKAGE_DESCRIPTION: 331 fPackageInfoValue.SetTo(B_PACKAGE_INFO_DESCRIPTION, 332 value.string); 333 break; 334 335 case B_HPKG_ATTRIBUTE_ID_PACKAGE_VENDOR: 336 fPackageInfoValue.SetTo(B_PACKAGE_INFO_VENDOR, value.string); 337 break; 338 339 case B_HPKG_ATTRIBUTE_ID_PACKAGE_PACKAGER: 340 fPackageInfoValue.SetTo(B_PACKAGE_INFO_PACKAGER, value.string); 341 break; 342 343 case B_HPKG_ATTRIBUTE_ID_PACKAGE_FLAGS: 344 fPackageInfoValue.SetTo(B_PACKAGE_INFO_FLAGS, 345 (uint32)value.unsignedInt); 346 break; 347 348 case B_HPKG_ATTRIBUTE_ID_PACKAGE_ARCHITECTURE: 349 if (value.unsignedInt 350 >= B_PACKAGE_ARCHITECTURE_ENUM_COUNT) { 351 context->errorOutput->PrintError( 352 "Error: Invalid package attribute section: " 353 "Invalid package architecture %lld encountered\n", 354 value.unsignedInt); 355 return B_BAD_DATA; 356 } 357 fPackageInfoValue.SetTo(B_PACKAGE_INFO_ARCHITECTURE, 358 (uint8)value.unsignedInt); 359 break; 360 361 case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_MAJOR: 362 fPackageInfoValue.attributeID = B_PACKAGE_INFO_VERSION; 363 fPackageInfoValue.version.major = value.string; 364 if (_handler != NULL) { 365 *_handler 366 = new(std::nothrow) PackageVersionAttributeHandler( 367 fPackageInfoValue, fPackageInfoValue.version, true); 368 if (*_handler == NULL) 369 return B_NO_MEMORY; 370 } 371 break; 372 373 case B_HPKG_ATTRIBUTE_ID_PACKAGE_COPYRIGHT: 374 fPackageInfoValue.SetTo(B_PACKAGE_INFO_COPYRIGHTS, 375 value.string); 376 break; 377 378 case B_HPKG_ATTRIBUTE_ID_PACKAGE_LICENSE: 379 fPackageInfoValue.SetTo(B_PACKAGE_INFO_LICENSES, 380 value.string); 381 break; 382 383 case B_HPKG_ATTRIBUTE_ID_PACKAGE_URL: 384 fPackageInfoValue.SetTo(B_PACKAGE_INFO_URLS, value.string); 385 break; 386 387 case B_HPKG_ATTRIBUTE_ID_PACKAGE_SOURCE_URL: 388 fPackageInfoValue.SetTo(B_PACKAGE_INFO_SOURCE_URLS, value.string); 389 break; 390 391 case B_HPKG_ATTRIBUTE_ID_PACKAGE_PROVIDES: 392 fPackageInfoValue.resolvable.name = value.string; 393 fPackageInfoValue.attributeID = B_PACKAGE_INFO_PROVIDES; 394 if (_handler != NULL) { 395 *_handler 396 = new(std::nothrow) PackageResolvableAttributeHandler( 397 fPackageInfoValue); 398 if (*_handler == NULL) 399 return B_NO_MEMORY; 400 } 401 break; 402 403 case B_HPKG_ATTRIBUTE_ID_PACKAGE_REQUIRES: 404 case B_HPKG_ATTRIBUTE_ID_PACKAGE_SUPPLEMENTS: 405 case B_HPKG_ATTRIBUTE_ID_PACKAGE_CONFLICTS: 406 case B_HPKG_ATTRIBUTE_ID_PACKAGE_FRESHENS: 407 fPackageInfoValue.resolvableExpression.name = value.string; 408 switch (id) { 409 case B_HPKG_ATTRIBUTE_ID_PACKAGE_REQUIRES: 410 fPackageInfoValue.attributeID = B_PACKAGE_INFO_REQUIRES; 411 break; 412 413 case B_HPKG_ATTRIBUTE_ID_PACKAGE_SUPPLEMENTS: 414 fPackageInfoValue.attributeID 415 = B_PACKAGE_INFO_SUPPLEMENTS; 416 break; 417 418 case B_HPKG_ATTRIBUTE_ID_PACKAGE_CONFLICTS: 419 fPackageInfoValue.attributeID 420 = B_PACKAGE_INFO_CONFLICTS; 421 break; 422 423 case B_HPKG_ATTRIBUTE_ID_PACKAGE_FRESHENS: 424 fPackageInfoValue.attributeID = B_PACKAGE_INFO_FRESHENS; 425 break; 426 } 427 if (_handler != NULL) { 428 *_handler = new(std::nothrow) 429 PackageResolvableExpressionAttributeHandler( 430 fPackageInfoValue); 431 if (*_handler == NULL) 432 return B_NO_MEMORY; 433 } 434 break; 435 436 case B_HPKG_ATTRIBUTE_ID_PACKAGE_REPLACES: 437 fPackageInfoValue.SetTo(B_PACKAGE_INFO_REPLACES, value.string); 438 break; 439 440 case B_HPKG_ATTRIBUTE_ID_PACKAGE_CHECKSUM: 441 fPackageInfoValue.SetTo(B_PACKAGE_INFO_CHECKSUM, value.string); 442 break; 443 444 case B_HPKG_ATTRIBUTE_ID_PACKAGE_INSTALL_PATH: 445 fPackageInfoValue.SetTo(B_PACKAGE_INFO_INSTALL_PATH, value.string); 446 break; 447 448 default: 449 context->errorOutput->PrintError( 450 "Error: Invalid package attribute section: unexpected " 451 "package attribute id %d encountered\n", id); 452 return B_BAD_DATA; 453 } 454 455 // notify unless the current attribute has children, in which case 456 // the child-handler will notify when it's done 457 if (_handler == NULL) { 458 status_t error = context->packageContentHandler 459 ->HandlePackageAttribute(fPackageInfoValue); 460 fPackageInfoValue.Clear(); 461 if (error != B_OK) 462 return error; 463 } 464 465 return B_OK; 466 } 467 468 469 // #pragma mark - LowLevelAttributeHandler 470 471 472 ReaderImplBase::LowLevelAttributeHandler::LowLevelAttributeHandler() 473 : 474 fParentToken(NULL), 475 fToken(NULL), 476 fID(B_HPKG_ATTRIBUTE_ID_ENUM_COUNT) 477 { 478 } 479 480 481 ReaderImplBase::LowLevelAttributeHandler::LowLevelAttributeHandler(uint8 id, 482 const BPackageAttributeValue& value, void* parentToken, void* token) 483 : 484 fParentToken(NULL), 485 fToken(token), 486 fID(id), 487 fValue(value) 488 { 489 } 490 491 492 status_t 493 ReaderImplBase::LowLevelAttributeHandler::HandleAttribute( 494 AttributeHandlerContext* context, uint8 id, const AttributeValue& value, 495 AttributeHandler** _handler) 496 { 497 // notify the content handler 498 void* token; 499 status_t error = context->lowLevelHandler->HandleAttribute( 500 (BHPKGAttributeID)id, value, fToken, token); 501 if (error != B_OK) 502 return error; 503 504 // create a subhandler for the attribute, if it has children 505 if (_handler != NULL) { 506 *_handler = new(std::nothrow) LowLevelAttributeHandler(id, value, 507 fToken, token); 508 if (*_handler == NULL) { 509 context->lowLevelHandler->HandleAttributeDone((BHPKGAttributeID)id, 510 value, fToken, token); 511 return B_NO_MEMORY; 512 } 513 return B_OK; 514 } 515 516 // no children -- just call the done hook 517 return context->lowLevelHandler->HandleAttributeDone((BHPKGAttributeID)id, 518 value, fToken, token); 519 } 520 521 522 status_t 523 ReaderImplBase::LowLevelAttributeHandler::Delete( 524 AttributeHandlerContext* context) 525 { 526 status_t error = B_OK; 527 if (fID != B_HPKG_ATTRIBUTE_ID_ENUM_COUNT) { 528 error = context->lowLevelHandler->HandleAttributeDone( 529 (BHPKGAttributeID)fID, fValue, fParentToken, fToken); 530 } 531 532 delete this; 533 return error; 534 } 535 536 537 // #pragma mark - ReaderImplBase 538 539 540 ReaderImplBase::ReaderImplBase(BErrorOutput* errorOutput) 541 : 542 fPackageAttributesSection("package attributes"), 543 fErrorOutput(errorOutput), 544 fFD(-1), 545 fOwnsFD(false), 546 fCurrentSection(NULL), 547 fScratchBuffer(NULL), 548 fScratchBufferSize(0) 549 { 550 } 551 552 553 ReaderImplBase::~ReaderImplBase() 554 { 555 if (fOwnsFD && fFD >= 0) 556 close(fFD); 557 558 delete[] fScratchBuffer; 559 } 560 561 562 status_t 563 ReaderImplBase::Init(int fd, bool keepFD) 564 { 565 fFD = fd; 566 fOwnsFD = keepFD; 567 568 // allocate a scratch buffer 569 fScratchBuffer = new(std::nothrow) uint8[kScratchBufferSize]; 570 if (fScratchBuffer == NULL) { 571 fErrorOutput->PrintError("Error: Out of memory!\n"); 572 return B_NO_MEMORY; 573 } 574 fScratchBufferSize = kScratchBufferSize; 575 576 return B_OK; 577 } 578 579 580 const char* 581 ReaderImplBase::CheckCompression(const SectionInfo& section) const 582 { 583 switch (section.compression) { 584 case B_HPKG_COMPRESSION_NONE: 585 if (section.compressedLength != section.uncompressedLength) { 586 return "Uncompressed, but compressed and uncompressed length " 587 "don't match"; 588 } 589 return NULL; 590 591 case B_HPKG_COMPRESSION_ZLIB: 592 if (section.compressedLength >= section.uncompressedLength) { 593 return "Compressed, but compressed length is not less than " 594 "uncompressed length"; 595 } 596 return NULL; 597 598 default: 599 return "Invalid compression algorithm ID"; 600 } 601 } 602 603 604 status_t 605 ReaderImplBase::ParseStrings() 606 { 607 // allocate table, if there are any strings 608 if (fCurrentSection->stringsCount == 0) { 609 fCurrentSection->currentOffset += fCurrentSection->stringsLength; 610 return B_OK; 611 } 612 613 fCurrentSection->strings 614 = new(std::nothrow) char*[fCurrentSection->stringsCount]; 615 if (fCurrentSection->strings == NULL) { 616 fErrorOutput->PrintError("Error: Out of memory!\n"); 617 return B_NO_MEMORY; 618 } 619 620 // parse the section and fill the table 621 char* position 622 = (char*)fCurrentSection->data + fCurrentSection->currentOffset; 623 char* sectionEnd = position + fCurrentSection->stringsLength; 624 uint32 index = 0; 625 while (true) { 626 if (position >= sectionEnd) { 627 fErrorOutput->PrintError("Error: Malformed %s strings section\n", 628 fCurrentSection->name); 629 return B_BAD_DATA; 630 } 631 632 size_t stringLength = strnlen(position, (char*)sectionEnd - position); 633 634 if (stringLength == 0) { 635 if (position + 1 != sectionEnd) { 636 fErrorOutput->PrintError( 637 "Error: %ld excess bytes in %s strings section\n", 638 sectionEnd - (position + 1), fCurrentSection->name); 639 return B_BAD_DATA; 640 } 641 642 if (index != fCurrentSection->stringsCount) { 643 fErrorOutput->PrintError("Error: Invalid %s strings section: " 644 "Less strings (%lld) than specified in the header (%lld)\n", 645 fCurrentSection->name, index, 646 fCurrentSection->stringsCount); 647 return B_BAD_DATA; 648 } 649 650 fCurrentSection->currentOffset += fCurrentSection->stringsLength; 651 652 return B_OK; 653 } 654 655 if (index >= fCurrentSection->stringsCount) { 656 fErrorOutput->PrintError("Error: Invalid %s strings section: " 657 "More strings (%lld) than specified in the header (%lld)\n", 658 fCurrentSection->name, index, fCurrentSection->stringsCount); 659 return B_BAD_DATA; 660 } 661 662 fCurrentSection->strings[index++] = position; 663 position += stringLength + 1; 664 } 665 } 666 667 668 status_t 669 ReaderImplBase::ParsePackageAttributesSection( 670 AttributeHandlerContext* context, AttributeHandler* rootAttributeHandler) 671 { 672 // parse package attributes 673 SetCurrentSection(&fPackageAttributesSection); 674 675 // init the attribute handler stack 676 rootAttributeHandler->SetLevel(0); 677 ClearAttributeHandlerStack(); 678 PushAttributeHandler(rootAttributeHandler); 679 680 bool sectionHandled; 681 status_t error = ParseAttributeTree(context, sectionHandled); 682 if (error == B_OK && sectionHandled) { 683 if (fPackageAttributesSection.currentOffset 684 < fPackageAttributesSection.uncompressedLength) { 685 fErrorOutput->PrintError("Error: %llu excess byte(s) in package " 686 "attributes section\n", 687 fPackageAttributesSection.uncompressedLength 688 - fPackageAttributesSection.currentOffset); 689 error = B_BAD_DATA; 690 } 691 } 692 693 SetCurrentSection(NULL); 694 695 // clean up on error 696 if (error != B_OK) { 697 context->ErrorOccurred(); 698 while (AttributeHandler* handler = PopAttributeHandler()) { 699 if (handler != rootAttributeHandler) 700 handler->Delete(context); 701 } 702 return error; 703 } 704 705 return B_OK; 706 } 707 708 709 status_t 710 ReaderImplBase::ParseAttributeTree(AttributeHandlerContext* context, 711 bool& _sectionHandled) 712 { 713 if (context->hasLowLevelHandler) { 714 bool handleSection = false; 715 status_t error = context->lowLevelHandler->HandleSectionStart( 716 context->section, handleSection); 717 if (error != B_OK) 718 return error; 719 720 if (!handleSection) { 721 _sectionHandled = false; 722 return B_OK; 723 } 724 } 725 726 status_t error = _ParseAttributeTree(context); 727 728 if (context->hasLowLevelHandler) { 729 status_t endError = context->lowLevelHandler->HandleSectionEnd( 730 context->section); 731 if (error == B_OK) 732 error = endError; 733 } 734 735 _sectionHandled = true; 736 return error; 737 } 738 739 740 status_t 741 ReaderImplBase::_ParseAttributeTree(AttributeHandlerContext* context) 742 { 743 int level = 0; 744 745 while (true) { 746 uint8 id; 747 AttributeValue value; 748 bool hasChildren; 749 uint64 tag; 750 751 status_t error = _ReadAttribute(id, value, &hasChildren, &tag); 752 if (error != B_OK) 753 return error; 754 755 if (tag == 0) { 756 AttributeHandler* handler = PopAttributeHandler(); 757 if (level-- == 0) 758 return B_OK; 759 760 error = handler->Delete(context); 761 if (error != B_OK) 762 return error; 763 764 continue; 765 } 766 767 AttributeHandler* childHandler = NULL; 768 error = CurrentAttributeHandler()->HandleAttribute(context, id, value, 769 hasChildren ? &childHandler : NULL); 770 if (error != B_OK) 771 return error; 772 773 // parse children 774 if (hasChildren) { 775 // create an ignore handler, if necessary 776 if (childHandler == NULL) { 777 childHandler = new(std::nothrow) IgnoreAttributeHandler; 778 if (childHandler == NULL) { 779 fErrorOutput->PrintError("Error: Out of memory!\n"); 780 return B_NO_MEMORY; 781 } 782 } 783 784 childHandler->SetLevel(++level); 785 PushAttributeHandler(childHandler); 786 } 787 } 788 } 789 790 791 status_t 792 ReaderImplBase::_ReadAttribute(uint8& _id, AttributeValue& _value, 793 bool* _hasChildren, uint64* _tag) 794 { 795 uint64 tag; 796 status_t error = ReadUnsignedLEB128(tag); 797 if (error != B_OK) 798 return error; 799 800 if (tag != 0) { 801 // get the type 802 uint16 type = HPKG_ATTRIBUTE_TAG_TYPE(tag); 803 if (type >= B_HPKG_ATTRIBUTE_TYPE_ENUM_COUNT) { 804 fErrorOutput->PrintError("Error: Invalid %s section: attribute " 805 "type %d not supported!\n", fCurrentSection->name, type); 806 return B_BAD_DATA; 807 } 808 809 // get the value 810 error = ReadAttributeValue(type, HPKG_ATTRIBUTE_TAG_ENCODING(tag), 811 _value); 812 if (error != B_OK) 813 return error; 814 815 _id = HPKG_ATTRIBUTE_TAG_ID(tag); 816 if (_id >= B_HPKG_ATTRIBUTE_ID_ENUM_COUNT) { 817 fErrorOutput->PrintError("Error: Invalid %s section: " 818 "attribute id %d not supported!\n", fCurrentSection->name, _id); 819 return B_BAD_DATA; 820 } 821 } 822 823 if (_hasChildren != NULL) 824 *_hasChildren = HPKG_ATTRIBUTE_TAG_HAS_CHILDREN(tag); 825 if (_tag != NULL) 826 *_tag = tag; 827 828 return B_OK; 829 } 830 831 832 status_t 833 ReaderImplBase::ReadAttributeValue(uint8 type, uint8 encoding, 834 AttributeValue& _value) 835 { 836 switch (type) { 837 case B_HPKG_ATTRIBUTE_TYPE_INT: 838 case B_HPKG_ATTRIBUTE_TYPE_UINT: 839 { 840 uint64 intValue; 841 status_t error; 842 843 switch (encoding) { 844 case B_HPKG_ATTRIBUTE_ENCODING_INT_8_BIT: 845 { 846 uint8 value; 847 error = _Read(value); 848 intValue = value; 849 break; 850 } 851 case B_HPKG_ATTRIBUTE_ENCODING_INT_16_BIT: 852 { 853 uint16 value; 854 error = _Read(value); 855 intValue = B_BENDIAN_TO_HOST_INT16(value); 856 break; 857 } 858 case B_HPKG_ATTRIBUTE_ENCODING_INT_32_BIT: 859 { 860 uint32 value; 861 error = _Read(value); 862 intValue = B_BENDIAN_TO_HOST_INT32(value); 863 break; 864 } 865 case B_HPKG_ATTRIBUTE_ENCODING_INT_64_BIT: 866 { 867 uint64 value; 868 error = _Read(value); 869 intValue = B_BENDIAN_TO_HOST_INT64(value); 870 break; 871 } 872 default: 873 { 874 fErrorOutput->PrintError("Error: Invalid %s section: " 875 "invalid encoding %d for int value type %d\n", 876 fCurrentSection->name, encoding, type); 877 return B_BAD_VALUE; 878 } 879 } 880 881 if (error != B_OK) 882 return error; 883 884 if (type == B_HPKG_ATTRIBUTE_TYPE_INT) 885 _value.SetTo((int64)intValue); 886 else 887 _value.SetTo(intValue); 888 889 return B_OK; 890 } 891 892 case B_HPKG_ATTRIBUTE_TYPE_STRING: 893 { 894 if (encoding == B_HPKG_ATTRIBUTE_ENCODING_STRING_TABLE) { 895 uint64 index; 896 status_t error = ReadUnsignedLEB128(index); 897 if (error != B_OK) 898 return error; 899 900 if (index > fCurrentSection->stringsCount) { 901 fErrorOutput->PrintError("Error: Invalid %s section: " 902 "string reference (%lld) out of bounds (%lld)\n", 903 fCurrentSection->name, index, 904 fCurrentSection->stringsCount); 905 return B_BAD_DATA; 906 } 907 908 _value.SetTo(fCurrentSection->strings[index]); 909 } else if (encoding == B_HPKG_ATTRIBUTE_ENCODING_STRING_INLINE) { 910 const char* string; 911 status_t error = _ReadString(string); 912 if (error != B_OK) 913 return error; 914 915 _value.SetTo(string); 916 } else { 917 fErrorOutput->PrintError("Error: Invalid %s section: invalid " 918 "string encoding (%u)\n", fCurrentSection->name, encoding); 919 return B_BAD_DATA; 920 } 921 922 return B_OK; 923 } 924 925 default: 926 fErrorOutput->PrintError("Error: Invalid %s section: invalid " 927 "value type: %d\n", fCurrentSection->name, type); 928 return B_BAD_DATA; 929 } 930 } 931 932 933 status_t 934 ReaderImplBase::ReadUnsignedLEB128(uint64& _value) 935 { 936 uint64 result = 0; 937 int shift = 0; 938 while (true) { 939 uint8 byte; 940 status_t error = _Read(byte); 941 if (error != B_OK) 942 return error; 943 944 result |= uint64(byte & 0x7f) << shift; 945 if ((byte & 0x80) == 0) 946 break; 947 shift += 7; 948 } 949 950 _value = result; 951 return B_OK; 952 } 953 954 955 status_t 956 ReaderImplBase::_ReadString(const char*& _string, size_t* _stringLength) 957 { 958 const char* string 959 = (const char*)fCurrentSection->data + fCurrentSection->currentOffset; 960 size_t stringLength = strnlen(string, 961 fCurrentSection->uncompressedLength - fCurrentSection->currentOffset); 962 963 if (stringLength 964 == fCurrentSection->uncompressedLength 965 - fCurrentSection->currentOffset) { 966 fErrorOutput->PrintError( 967 "_ReadString(): string extends beyond %s end\n", 968 fCurrentSection->name); 969 return B_BAD_DATA; 970 } 971 972 _string = string; 973 if (_stringLength != NULL) 974 *_stringLength = stringLength; 975 976 fCurrentSection->currentOffset += stringLength + 1; 977 return B_OK; 978 } 979 980 981 status_t 982 ReaderImplBase::_ReadSectionBuffer(void* buffer, size_t size) 983 { 984 if (size > fCurrentSection->uncompressedLength 985 - fCurrentSection->currentOffset) { 986 fErrorOutput->PrintError("_ReadBuffer(%lu): read beyond %s end\n", 987 size, fCurrentSection->name); 988 return B_BAD_DATA; 989 } 990 991 memcpy(buffer, fCurrentSection->data + fCurrentSection->currentOffset, 992 size); 993 fCurrentSection->currentOffset += size; 994 return B_OK; 995 } 996 997 998 status_t 999 ReaderImplBase::ReadBuffer(off_t offset, void* buffer, size_t size) 1000 { 1001 ssize_t bytesRead = pread(fFD, buffer, size, offset); 1002 if (bytesRead < 0) { 1003 fErrorOutput->PrintError("_ReadBuffer(%p, %lu) failed to read data: " 1004 "%s\n", buffer, size, strerror(errno)); 1005 return errno; 1006 } 1007 if ((size_t)bytesRead != size) { 1008 fErrorOutput->PrintError("_ReadBuffer(%p, %lu) failed to read all " 1009 "data\n", buffer, size); 1010 return B_ERROR; 1011 } 1012 1013 return B_OK; 1014 } 1015 1016 1017 status_t 1018 ReaderImplBase::ReadCompressedBuffer(const SectionInfo& section) 1019 { 1020 uint32 compressedSize = section.compressedLength; 1021 uint64 offset = section.offset; 1022 1023 switch (section.compression) { 1024 case B_HPKG_COMPRESSION_NONE: 1025 return ReadBuffer(offset, section.data, compressedSize); 1026 1027 case B_HPKG_COMPRESSION_ZLIB: 1028 { 1029 // init the decompressor 1030 BBufferDataOutput bufferOutput(section.data, 1031 section.uncompressedLength); 1032 ZlibDecompressor decompressor(&bufferOutput); 1033 status_t error = decompressor.Init(); 1034 if (error != B_OK) 1035 return error; 1036 1037 while (compressedSize > 0) { 1038 // read compressed buffer 1039 size_t toRead = std::min((size_t)compressedSize, 1040 fScratchBufferSize); 1041 error = ReadBuffer(offset, fScratchBuffer, toRead); 1042 if (error != B_OK) 1043 return error; 1044 1045 // uncompress 1046 error = decompressor.DecompressNext(fScratchBuffer, toRead); 1047 if (error != B_OK) 1048 return error; 1049 1050 compressedSize -= toRead; 1051 offset += toRead; 1052 } 1053 1054 error = decompressor.Finish(); 1055 if (error != B_OK) 1056 return error; 1057 1058 // verify that all data have been read 1059 if (bufferOutput.BytesWritten() != section.uncompressedLength) { 1060 fErrorOutput->PrintError("Error: Missing bytes in uncompressed " 1061 "buffer!\n"); 1062 return B_BAD_DATA; 1063 } 1064 1065 return B_OK; 1066 } 1067 1068 default: 1069 { 1070 fErrorOutput->PrintError("Error: Invalid compression type: %u\n", 1071 section.compression); 1072 return B_BAD_DATA; 1073 } 1074 } 1075 } 1076 1077 1078 } // namespace BPrivate 1079 1080 } // namespace BHPKG 1081 1082 } // namespace BPackageKit 1083