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