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 default: 445 context->errorOutput->PrintError( 446 "Error: Invalid package attribute section: unexpected " 447 "package attribute id %d encountered\n", id); 448 return B_BAD_DATA; 449 } 450 451 // notify unless the current attribute has children, in which case 452 // the child-handler will notify when it's done 453 if (_handler == NULL) { 454 status_t error = context->packageContentHandler 455 ->HandlePackageAttribute(fPackageInfoValue); 456 fPackageInfoValue.Clear(); 457 if (error != B_OK) 458 return error; 459 } 460 461 return B_OK; 462 } 463 464 465 // #pragma mark - LowLevelAttributeHandler 466 467 468 ReaderImplBase::LowLevelAttributeHandler::LowLevelAttributeHandler() 469 : 470 fParentToken(NULL), 471 fToken(NULL), 472 fID(B_HPKG_ATTRIBUTE_ID_ENUM_COUNT) 473 { 474 } 475 476 477 ReaderImplBase::LowLevelAttributeHandler::LowLevelAttributeHandler(uint8 id, 478 const BPackageAttributeValue& value, void* parentToken, void* token) 479 : 480 fParentToken(NULL), 481 fToken(token), 482 fID(id), 483 fValue(value) 484 { 485 } 486 487 488 status_t 489 ReaderImplBase::LowLevelAttributeHandler::HandleAttribute( 490 AttributeHandlerContext* context, uint8 id, const AttributeValue& value, 491 AttributeHandler** _handler) 492 { 493 // notify the content handler 494 void* token; 495 status_t error = context->lowLevelHandler->HandleAttribute( 496 (BHPKGAttributeID)id, value, fToken, token); 497 if (error != B_OK) 498 return error; 499 500 // create a subhandler for the attribute, if it has children 501 if (_handler != NULL) { 502 *_handler = new(std::nothrow) LowLevelAttributeHandler(id, value, 503 fToken, token); 504 if (*_handler == NULL) { 505 context->lowLevelHandler->HandleAttributeDone((BHPKGAttributeID)id, 506 value, fToken, token); 507 return B_NO_MEMORY; 508 } 509 return B_OK; 510 } 511 512 // no children -- just call the done hook 513 return context->lowLevelHandler->HandleAttributeDone((BHPKGAttributeID)id, 514 value, fToken, token); 515 } 516 517 518 status_t 519 ReaderImplBase::LowLevelAttributeHandler::Delete( 520 AttributeHandlerContext* context) 521 { 522 status_t error = B_OK; 523 if (fID != B_HPKG_ATTRIBUTE_ID_ENUM_COUNT) { 524 error = context->lowLevelHandler->HandleAttributeDone( 525 (BHPKGAttributeID)fID, fValue, fParentToken, fToken); 526 } 527 528 delete this; 529 return error; 530 } 531 532 533 // #pragma mark - ReaderImplBase 534 535 536 ReaderImplBase::ReaderImplBase(BErrorOutput* errorOutput) 537 : 538 fPackageAttributesSection("package attributes"), 539 fErrorOutput(errorOutput), 540 fFD(-1), 541 fOwnsFD(false), 542 fCurrentSection(NULL), 543 fScratchBuffer(NULL), 544 fScratchBufferSize(0) 545 { 546 } 547 548 549 ReaderImplBase::~ReaderImplBase() 550 { 551 if (fOwnsFD && fFD >= 0) 552 close(fFD); 553 554 delete[] fScratchBuffer; 555 } 556 557 558 status_t 559 ReaderImplBase::Init(int fd, bool keepFD) 560 { 561 fFD = fd; 562 fOwnsFD = keepFD; 563 564 // allocate a scratch buffer 565 fScratchBuffer = new(std::nothrow) uint8[kScratchBufferSize]; 566 if (fScratchBuffer == NULL) { 567 fErrorOutput->PrintError("Error: Out of memory!\n"); 568 return B_NO_MEMORY; 569 } 570 fScratchBufferSize = kScratchBufferSize; 571 572 return B_OK; 573 } 574 575 576 const char* 577 ReaderImplBase::CheckCompression(const SectionInfo& section) const 578 { 579 switch (section.compression) { 580 case B_HPKG_COMPRESSION_NONE: 581 if (section.compressedLength != section.uncompressedLength) { 582 return "Uncompressed, but compressed and uncompressed length " 583 "don't match"; 584 } 585 return NULL; 586 587 case B_HPKG_COMPRESSION_ZLIB: 588 if (section.compressedLength >= section.uncompressedLength) { 589 return "Compressed, but compressed length is not less than " 590 "uncompressed length"; 591 } 592 return NULL; 593 594 default: 595 return "Invalid compression algorithm ID"; 596 } 597 } 598 599 600 status_t 601 ReaderImplBase::ParseStrings() 602 { 603 // allocate table, if there are any strings 604 if (fCurrentSection->stringsCount == 0) { 605 fCurrentSection->currentOffset += fCurrentSection->stringsLength; 606 return B_OK; 607 } 608 609 fCurrentSection->strings 610 = new(std::nothrow) char*[fCurrentSection->stringsCount]; 611 if (fCurrentSection->strings == NULL) { 612 fErrorOutput->PrintError("Error: Out of memory!\n"); 613 return B_NO_MEMORY; 614 } 615 616 // parse the section and fill the table 617 char* position 618 = (char*)fCurrentSection->data + fCurrentSection->currentOffset; 619 char* sectionEnd = position + fCurrentSection->stringsLength; 620 uint32 index = 0; 621 while (true) { 622 if (position >= sectionEnd) { 623 fErrorOutput->PrintError("Error: Malformed %s strings section\n", 624 fCurrentSection->name); 625 return B_BAD_DATA; 626 } 627 628 size_t stringLength = strnlen(position, (char*)sectionEnd - position); 629 630 if (stringLength == 0) { 631 if (position + 1 != sectionEnd) { 632 fErrorOutput->PrintError( 633 "Error: %ld excess bytes in %s strings section\n", 634 sectionEnd - (position + 1), fCurrentSection->name); 635 return B_BAD_DATA; 636 } 637 638 if (index != fCurrentSection->stringsCount) { 639 fErrorOutput->PrintError("Error: Invalid %s strings section: " 640 "Less strings (%lld) than specified in the header (%lld)\n", 641 fCurrentSection->name, index, 642 fCurrentSection->stringsCount); 643 return B_BAD_DATA; 644 } 645 646 fCurrentSection->currentOffset += fCurrentSection->stringsLength; 647 648 return B_OK; 649 } 650 651 if (index >= fCurrentSection->stringsCount) { 652 fErrorOutput->PrintError("Error: Invalid %s strings section: " 653 "More strings (%lld) than specified in the header (%lld)\n", 654 fCurrentSection->name, index, fCurrentSection->stringsCount); 655 return B_BAD_DATA; 656 } 657 658 fCurrentSection->strings[index++] = position; 659 position += stringLength + 1; 660 } 661 } 662 663 664 status_t 665 ReaderImplBase::ParsePackageAttributesSection( 666 AttributeHandlerContext* context, AttributeHandler* rootAttributeHandler) 667 { 668 // parse package attributes 669 SetCurrentSection(&fPackageAttributesSection); 670 671 // init the attribute handler stack 672 rootAttributeHandler->SetLevel(0); 673 ClearAttributeHandlerStack(); 674 PushAttributeHandler(rootAttributeHandler); 675 676 bool sectionHandled; 677 status_t error = ParseAttributeTree(context, sectionHandled); 678 if (error == B_OK && sectionHandled) { 679 if (fPackageAttributesSection.currentOffset 680 < fPackageAttributesSection.uncompressedLength) { 681 fErrorOutput->PrintError("Error: %llu excess byte(s) in package " 682 "attributes section\n", 683 fPackageAttributesSection.uncompressedLength 684 - fPackageAttributesSection.currentOffset); 685 error = B_BAD_DATA; 686 } 687 } 688 689 SetCurrentSection(NULL); 690 691 // clean up on error 692 if (error != B_OK) { 693 context->ErrorOccurred(); 694 while (AttributeHandler* handler = PopAttributeHandler()) { 695 if (handler != rootAttributeHandler) 696 handler->Delete(context); 697 } 698 return error; 699 } 700 701 return B_OK; 702 } 703 704 705 status_t 706 ReaderImplBase::ParseAttributeTree(AttributeHandlerContext* context, 707 bool& _sectionHandled) 708 { 709 if (context->hasLowLevelHandler) { 710 bool handleSection = false; 711 status_t error = context->lowLevelHandler->HandleSectionStart( 712 context->section, handleSection); 713 if (error != B_OK) 714 return error; 715 716 if (!handleSection) { 717 _sectionHandled = false; 718 return B_OK; 719 } 720 } 721 722 status_t error = _ParseAttributeTree(context); 723 724 if (context->hasLowLevelHandler) { 725 status_t endError = context->lowLevelHandler->HandleSectionEnd( 726 context->section); 727 if (error == B_OK) 728 error = endError; 729 } 730 731 _sectionHandled = true; 732 return error; 733 } 734 735 736 status_t 737 ReaderImplBase::_ParseAttributeTree(AttributeHandlerContext* context) 738 { 739 int level = 0; 740 741 while (true) { 742 uint8 id; 743 AttributeValue value; 744 bool hasChildren; 745 uint64 tag; 746 747 status_t error = _ReadAttribute(id, value, &hasChildren, &tag); 748 if (error != B_OK) 749 return error; 750 751 if (tag == 0) { 752 AttributeHandler* handler = PopAttributeHandler(); 753 if (level-- == 0) 754 return B_OK; 755 756 error = handler->Delete(context); 757 if (error != B_OK) 758 return error; 759 760 continue; 761 } 762 763 AttributeHandler* childHandler = NULL; 764 error = CurrentAttributeHandler()->HandleAttribute(context, id, value, 765 hasChildren ? &childHandler : NULL); 766 if (error != B_OK) 767 return error; 768 769 // parse children 770 if (hasChildren) { 771 // create an ignore handler, if necessary 772 if (childHandler == NULL) { 773 childHandler = new(std::nothrow) IgnoreAttributeHandler; 774 if (childHandler == NULL) { 775 fErrorOutput->PrintError("Error: Out of memory!\n"); 776 return B_NO_MEMORY; 777 } 778 } 779 780 childHandler->SetLevel(++level); 781 PushAttributeHandler(childHandler); 782 } 783 } 784 } 785 786 787 status_t 788 ReaderImplBase::_ReadAttribute(uint8& _id, AttributeValue& _value, 789 bool* _hasChildren, uint64* _tag) 790 { 791 uint64 tag; 792 status_t error = ReadUnsignedLEB128(tag); 793 if (error != B_OK) 794 return error; 795 796 if (tag != 0) { 797 // get the type 798 uint16 type = HPKG_ATTRIBUTE_TAG_TYPE(tag); 799 if (type >= B_HPKG_ATTRIBUTE_TYPE_ENUM_COUNT) { 800 fErrorOutput->PrintError("Error: Invalid %s section: attribute " 801 "type %d not supported!\n", fCurrentSection->name, type); 802 return B_BAD_DATA; 803 } 804 805 // get the value 806 error = ReadAttributeValue(type, HPKG_ATTRIBUTE_TAG_ENCODING(tag), 807 _value); 808 if (error != B_OK) 809 return error; 810 811 _id = HPKG_ATTRIBUTE_TAG_ID(tag); 812 if (_id >= B_HPKG_ATTRIBUTE_ID_ENUM_COUNT) { 813 fErrorOutput->PrintError("Error: Invalid %s section: " 814 "attribute id %d not supported!\n", fCurrentSection->name, _id); 815 return B_BAD_DATA; 816 } 817 } 818 819 if (_hasChildren != NULL) 820 *_hasChildren = HPKG_ATTRIBUTE_TAG_HAS_CHILDREN(tag); 821 if (_tag != NULL) 822 *_tag = tag; 823 824 return B_OK; 825 } 826 827 828 status_t 829 ReaderImplBase::ReadAttributeValue(uint8 type, uint8 encoding, 830 AttributeValue& _value) 831 { 832 switch (type) { 833 case B_HPKG_ATTRIBUTE_TYPE_INT: 834 case B_HPKG_ATTRIBUTE_TYPE_UINT: 835 { 836 uint64 intValue; 837 status_t error; 838 839 switch (encoding) { 840 case B_HPKG_ATTRIBUTE_ENCODING_INT_8_BIT: 841 { 842 uint8 value; 843 error = _Read(value); 844 intValue = value; 845 break; 846 } 847 case B_HPKG_ATTRIBUTE_ENCODING_INT_16_BIT: 848 { 849 uint16 value; 850 error = _Read(value); 851 intValue = B_BENDIAN_TO_HOST_INT16(value); 852 break; 853 } 854 case B_HPKG_ATTRIBUTE_ENCODING_INT_32_BIT: 855 { 856 uint32 value; 857 error = _Read(value); 858 intValue = B_BENDIAN_TO_HOST_INT32(value); 859 break; 860 } 861 case B_HPKG_ATTRIBUTE_ENCODING_INT_64_BIT: 862 { 863 uint64 value; 864 error = _Read(value); 865 intValue = B_BENDIAN_TO_HOST_INT64(value); 866 break; 867 } 868 default: 869 { 870 fErrorOutput->PrintError("Error: Invalid %s section: " 871 "invalid encoding %d for int value type %d\n", 872 fCurrentSection->name, encoding, type); 873 return B_BAD_VALUE; 874 } 875 } 876 877 if (error != B_OK) 878 return error; 879 880 if (type == B_HPKG_ATTRIBUTE_TYPE_INT) 881 _value.SetTo((int64)intValue); 882 else 883 _value.SetTo(intValue); 884 885 return B_OK; 886 } 887 888 case B_HPKG_ATTRIBUTE_TYPE_STRING: 889 { 890 if (encoding == B_HPKG_ATTRIBUTE_ENCODING_STRING_TABLE) { 891 uint64 index; 892 status_t error = ReadUnsignedLEB128(index); 893 if (error != B_OK) 894 return error; 895 896 if (index > fCurrentSection->stringsCount) { 897 fErrorOutput->PrintError("Error: Invalid %s section: " 898 "string reference (%lld) out of bounds (%lld)\n", 899 fCurrentSection->name, index, 900 fCurrentSection->stringsCount); 901 return B_BAD_DATA; 902 } 903 904 _value.SetTo(fCurrentSection->strings[index]); 905 } else if (encoding == B_HPKG_ATTRIBUTE_ENCODING_STRING_INLINE) { 906 const char* string; 907 status_t error = _ReadString(string); 908 if (error != B_OK) 909 return error; 910 911 _value.SetTo(string); 912 } else { 913 fErrorOutput->PrintError("Error: Invalid %s section: invalid " 914 "string encoding (%u)\n", fCurrentSection->name, encoding); 915 return B_BAD_DATA; 916 } 917 918 return B_OK; 919 } 920 921 default: 922 fErrorOutput->PrintError("Error: Invalid %s section: invalid " 923 "value type: %d\n", fCurrentSection->name, type); 924 return B_BAD_DATA; 925 } 926 } 927 928 929 status_t 930 ReaderImplBase::ReadUnsignedLEB128(uint64& _value) 931 { 932 uint64 result = 0; 933 int shift = 0; 934 while (true) { 935 uint8 byte; 936 status_t error = _Read(byte); 937 if (error != B_OK) 938 return error; 939 940 result |= uint64(byte & 0x7f) << shift; 941 if ((byte & 0x80) == 0) 942 break; 943 shift += 7; 944 } 945 946 _value = result; 947 return B_OK; 948 } 949 950 951 status_t 952 ReaderImplBase::_ReadString(const char*& _string, size_t* _stringLength) 953 { 954 const char* string 955 = (const char*)fCurrentSection->data + fCurrentSection->currentOffset; 956 size_t stringLength = strnlen(string, 957 fCurrentSection->uncompressedLength - fCurrentSection->currentOffset); 958 959 if (stringLength 960 == fCurrentSection->uncompressedLength 961 - fCurrentSection->currentOffset) { 962 fErrorOutput->PrintError( 963 "_ReadString(): string extends beyond %s end\n", 964 fCurrentSection->name); 965 return B_BAD_DATA; 966 } 967 968 _string = string; 969 if (_stringLength != NULL) 970 *_stringLength = stringLength; 971 972 fCurrentSection->currentOffset += stringLength + 1; 973 return B_OK; 974 } 975 976 977 status_t 978 ReaderImplBase::_ReadSectionBuffer(void* buffer, size_t size) 979 { 980 if (size > fCurrentSection->uncompressedLength 981 - fCurrentSection->currentOffset) { 982 fErrorOutput->PrintError("_ReadBuffer(%lu): read beyond %s end\n", 983 size, fCurrentSection->name); 984 return B_BAD_DATA; 985 } 986 987 memcpy(buffer, fCurrentSection->data + fCurrentSection->currentOffset, 988 size); 989 fCurrentSection->currentOffset += size; 990 return B_OK; 991 } 992 993 994 status_t 995 ReaderImplBase::ReadBuffer(off_t offset, void* buffer, size_t size) 996 { 997 ssize_t bytesRead = pread(fFD, buffer, size, offset); 998 if (bytesRead < 0) { 999 fErrorOutput->PrintError("_ReadBuffer(%p, %lu) failed to read data: " 1000 "%s\n", buffer, size, strerror(errno)); 1001 return errno; 1002 } 1003 if ((size_t)bytesRead != size) { 1004 fErrorOutput->PrintError("_ReadBuffer(%p, %lu) failed to read all " 1005 "data\n", buffer, size); 1006 return B_ERROR; 1007 } 1008 1009 return B_OK; 1010 } 1011 1012 1013 status_t 1014 ReaderImplBase::ReadCompressedBuffer(const SectionInfo& section) 1015 { 1016 uint32 compressedSize = section.compressedLength; 1017 uint64 offset = section.offset; 1018 1019 switch (section.compression) { 1020 case B_HPKG_COMPRESSION_NONE: 1021 return ReadBuffer(offset, section.data, compressedSize); 1022 1023 case B_HPKG_COMPRESSION_ZLIB: 1024 { 1025 // init the decompressor 1026 BBufferDataOutput bufferOutput(section.data, 1027 section.uncompressedLength); 1028 ZlibDecompressor decompressor(&bufferOutput); 1029 status_t error = decompressor.Init(); 1030 if (error != B_OK) 1031 return error; 1032 1033 while (compressedSize > 0) { 1034 // read compressed buffer 1035 size_t toRead = std::min((size_t)compressedSize, 1036 fScratchBufferSize); 1037 error = ReadBuffer(offset, fScratchBuffer, toRead); 1038 if (error != B_OK) 1039 return error; 1040 1041 // uncompress 1042 error = decompressor.DecompressNext(fScratchBuffer, toRead); 1043 if (error != B_OK) 1044 return error; 1045 1046 compressedSize -= toRead; 1047 offset += toRead; 1048 } 1049 1050 error = decompressor.Finish(); 1051 if (error != B_OK) 1052 return error; 1053 1054 // verify that all data have been read 1055 if (bufferOutput.BytesWritten() != section.uncompressedLength) { 1056 fErrorOutput->PrintError("Error: Missing bytes in uncompressed " 1057 "buffer!\n"); 1058 return B_BAD_DATA; 1059 } 1060 1061 return B_OK; 1062 } 1063 1064 default: 1065 return B_BAD_DATA; 1066 } 1067 } 1068 1069 1070 } // namespace BPrivate 1071 1072 } // namespace BHPKG 1073 1074 } // namespace BPackageKit 1075