17575abbcSIngo Weinhold/*
232832cbeSIngo Weinhold * Copyright 2009-2014, Ingo Weinhold, ingo_weinhold@gmx.de.
37575abbcSIngo Weinhold * Copyright 2011, Oliver Tappe <zooey@hirschkaefer.de>
47575abbcSIngo Weinhold * Distributed under the terms of the MIT License.
57575abbcSIngo Weinhold */
67575abbcSIngo Weinhold
77575abbcSIngo Weinhold
87575abbcSIngo Weinhold#include <package/hpkg/v1/ReaderImplBase.h>
97575abbcSIngo Weinhold
107575abbcSIngo Weinhold#include <errno.h>
117575abbcSIngo Weinhold#include <stdio.h>
127575abbcSIngo Weinhold#include <stdlib.h>
137575abbcSIngo Weinhold#include <string.h>
146a89a36aSIngo Weinhold#include <unistd.h>
157575abbcSIngo Weinhold
167575abbcSIngo Weinhold#include <algorithm>
177575abbcSIngo Weinhold#include <new>
187575abbcSIngo Weinhold
197575abbcSIngo Weinhold#include <ByteOrder.h>
2032832cbeSIngo Weinhold#include <DataIO.h>
217575abbcSIngo Weinhold
227575abbcSIngo Weinhold#include <package/hpkg/ErrorOutput.h>
23b3263ad3SIngo Weinhold
24b3263ad3SIngo Weinhold#include <AutoDeleter.h>
25b3263ad3SIngo Weinhold#include <package/hpkg/v1/HPKGDefsPrivate.h>
26b3263ad3SIngo Weinhold#include <ZlibCompressionAlgorithm.h>
277575abbcSIngo Weinhold
287575abbcSIngo Weinhold
297575abbcSIngo Weinholdnamespace BPackageKit {
307575abbcSIngo Weinhold
317575abbcSIngo Weinholdnamespace BHPKG {
327575abbcSIngo Weinhold
337575abbcSIngo Weinholdnamespace V1 {
347575abbcSIngo Weinhold
357575abbcSIngo Weinholdnamespace BPrivate {
367575abbcSIngo Weinhold
377575abbcSIngo Weinhold
387575abbcSIngo Weinholdstatic const size_t kScratchBufferSize = 64 * 1024;
397575abbcSIngo Weinhold
407575abbcSIngo Weinhold
417575abbcSIngo Weinhold// #pragma mark - AttributeHandlerContext
427575abbcSIngo Weinhold
437575abbcSIngo Weinhold
447575abbcSIngo WeinholdReaderImplBase::AttributeHandlerContext::AttributeHandlerContext(
457575abbcSIngo Weinhold	BErrorOutput* errorOutput, BPackageContentHandler* packageContentHandler,
467575abbcSIngo Weinhold	BHPKGPackageSectionID section)
477575abbcSIngo Weinhold	:
487575abbcSIngo Weinhold	errorOutput(errorOutput),
497575abbcSIngo Weinhold	packageContentHandler(packageContentHandler),
507575abbcSIngo Weinhold	hasLowLevelHandler(false),
517575abbcSIngo Weinhold	section(section)
527575abbcSIngo Weinhold{
537575abbcSIngo Weinhold}
547575abbcSIngo Weinhold
557575abbcSIngo Weinhold
567575abbcSIngo WeinholdReaderImplBase::AttributeHandlerContext::AttributeHandlerContext(
577575abbcSIngo Weinhold	BErrorOutput* errorOutput, BLowLevelPackageContentHandler* lowLevelHandler,
587575abbcSIngo Weinhold	BHPKGPackageSectionID section)
597575abbcSIngo Weinhold	:
607575abbcSIngo Weinhold	errorOutput(errorOutput),
617575abbcSIngo Weinhold	lowLevelHandler(lowLevelHandler),
627575abbcSIngo Weinhold	hasLowLevelHandler(true),
637575abbcSIngo Weinhold	section(section)
647575abbcSIngo Weinhold{
657575abbcSIngo Weinhold}
667575abbcSIngo Weinhold
677575abbcSIngo Weinhold
687575abbcSIngo Weinholdvoid
697575abbcSIngo WeinholdReaderImplBase::AttributeHandlerContext::ErrorOccurred()
707575abbcSIngo Weinhold{
717575abbcSIngo Weinhold	if (hasLowLevelHandler)
727575abbcSIngo Weinhold		lowLevelHandler->HandleErrorOccurred();
737575abbcSIngo Weinhold	else
747575abbcSIngo Weinhold		packageContentHandler->HandleErrorOccurred();
757575abbcSIngo Weinhold}
767575abbcSIngo Weinhold
777575abbcSIngo Weinhold
787575abbcSIngo Weinhold// #pragma mark - AttributeHandler
797575abbcSIngo Weinhold
807575abbcSIngo Weinhold
817575abbcSIngo WeinholdReaderImplBase::AttributeHandler::~AttributeHandler()
827575abbcSIngo Weinhold{
837575abbcSIngo Weinhold}
847575abbcSIngo Weinhold
857575abbcSIngo Weinhold
867575abbcSIngo Weinholdvoid
877575abbcSIngo WeinholdReaderImplBase::AttributeHandler::SetLevel(int level)
887575abbcSIngo Weinhold{
897575abbcSIngo Weinhold	fLevel = level;
907575abbcSIngo Weinhold}
917575abbcSIngo Weinhold
927575abbcSIngo Weinhold
937575abbcSIngo Weinholdstatus_t
947575abbcSIngo WeinholdReaderImplBase::AttributeHandler::HandleAttribute(
957575abbcSIngo Weinhold	AttributeHandlerContext* context, uint8 id, const AttributeValue& value,
967575abbcSIngo Weinhold	AttributeHandler** _handler)
977575abbcSIngo Weinhold{
987575abbcSIngo Weinhold	return B_OK;
997575abbcSIngo Weinhold}
1007575abbcSIngo Weinhold
1017575abbcSIngo Weinhold
1027575abbcSIngo Weinholdstatus_t
1037575abbcSIngo WeinholdReaderImplBase::AttributeHandler::Delete(AttributeHandlerContext* context)
1047575abbcSIngo Weinhold{
1057575abbcSIngo Weinhold	delete this;
1067575abbcSIngo Weinhold	return B_OK;
1077575abbcSIngo Weinhold}
1087575abbcSIngo Weinhold
1097575abbcSIngo Weinhold
1107575abbcSIngo Weinhold// #pragma mark - PackageVersionAttributeHandler
1117575abbcSIngo Weinhold
1127575abbcSIngo Weinhold
1137575abbcSIngo WeinholdReaderImplBase::PackageVersionAttributeHandler::PackageVersionAttributeHandler(
1147575abbcSIngo Weinhold	BPackageInfoAttributeValue& packageInfoValue,
1157575abbcSIngo Weinhold	BPackageVersionData& versionData, bool notify)
1167575abbcSIngo Weinhold	:
1177575abbcSIngo Weinhold	fPackageInfoValue(packageInfoValue),
1187575abbcSIngo Weinhold	fPackageVersionData(versionData),
1197575abbcSIngo Weinhold	fNotify(notify)
1207575abbcSIngo Weinhold{
1217575abbcSIngo Weinhold}
1227575abbcSIngo Weinhold
1237575abbcSIngo Weinhold
1247575abbcSIngo Weinholdstatus_t
1257575abbcSIngo WeinholdReaderImplBase::PackageVersionAttributeHandler::HandleAttribute(
1267575abbcSIngo Weinhold	AttributeHandlerContext* context, uint8 id, const AttributeValue& value,
1277575abbcSIngo Weinhold	AttributeHandler** _handler)
1287575abbcSIngo Weinhold{
1297575abbcSIngo Weinhold	switch (id) {
1307575abbcSIngo Weinhold		case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_MINOR:
1317575abbcSIngo Weinhold			fPackageVersionData.minor = value.string;
1327575abbcSIngo Weinhold			break;
1337575abbcSIngo Weinhold
1347575abbcSIngo Weinhold		case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_MICRO:
1357575abbcSIngo Weinhold			fPackageVersionData.micro = value.string;
1367575abbcSIngo Weinhold			break;
1377575abbcSIngo Weinhold
1387575abbcSIngo Weinhold		case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_PRE_RELEASE:
1397575abbcSIngo Weinhold			fPackageVersionData.preRelease = value.string;
1407575abbcSIngo Weinhold			break;
1417575abbcSIngo Weinhold
1427575abbcSIngo Weinhold		case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_REVISION:
1437575abbcSIngo Weinhold			fPackageVersionData.revision = value.unsignedInt;
1447575abbcSIngo Weinhold			break;
1457575abbcSIngo Weinhold
1467575abbcSIngo Weinhold		default:
1477575abbcSIngo Weinhold			context->errorOutput->PrintError("Error: Invalid package "
1487575abbcSIngo Weinhold				"attribute section: unexpected package attribute id %d "
1497575abbcSIngo Weinhold				"encountered when parsing package version\n", id);
1507575abbcSIngo Weinhold			return B_BAD_DATA;
1517575abbcSIngo Weinhold	}
1527575abbcSIngo Weinhold
1537575abbcSIngo Weinhold	return B_OK;
1547575abbcSIngo Weinhold}
1557575abbcSIngo Weinhold
1567575abbcSIngo Weinhold
1577575abbcSIngo Weinholdstatus_t
1587575abbcSIngo WeinholdReaderImplBase::PackageVersionAttributeHandler::Delete(
1597575abbcSIngo Weinhold	AttributeHandlerContext* context)
1607575abbcSIngo Weinhold{
1617575abbcSIngo Weinhold	status_t error = B_OK;
1627575abbcSIngo Weinhold	if (fNotify) {
1637575abbcSIngo Weinhold		fPackageInfoValue.attributeID = B_PACKAGE_INFO_VERSION;
1647575abbcSIngo Weinhold		error = context->packageContentHandler->HandlePackageAttribute(
1657575abbcSIngo Weinhold			fPackageInfoValue);
1667575abbcSIngo Weinhold		fPackageInfoValue.Clear();
1677575abbcSIngo Weinhold	}
1687575abbcSIngo Weinhold
1697575abbcSIngo Weinhold	delete this;
1707575abbcSIngo Weinhold	return error;
1717575abbcSIngo Weinhold}
1727575abbcSIngo Weinhold
1737575abbcSIngo Weinhold
1747575abbcSIngo Weinhold// #pragma mark - PackageResolvableAttributeHandler
1757575abbcSIngo Weinhold
1767575abbcSIngo Weinhold
1777575abbcSIngo WeinholdReaderImplBase::PackageResolvableAttributeHandler
1787575abbcSIngo Weinhold	::PackageResolvableAttributeHandler(
1797575abbcSIngo Weinhold		BPackageInfoAttributeValue& packageInfoValue)
1807575abbcSIngo Weinhold	:
1817575abbcSIngo Weinhold	fPackageInfoValue(packageInfoValue)
1827575abbcSIngo Weinhold{
1837575abbcSIngo Weinhold}
1847575abbcSIngo Weinhold
1857575abbcSIngo Weinhold
1867575abbcSIngo Weinholdstatus_t
1877575abbcSIngo WeinholdReaderImplBase::PackageResolvableAttributeHandler::HandleAttribute(
1887575abbcSIngo Weinhold	AttributeHandlerContext* context, uint8 id, const AttributeValue& value,
1897575abbcSIngo Weinhold	AttributeHandler** _handler)
1907575abbcSIngo Weinhold{
1917575abbcSIngo Weinhold	switch (id) {
1927575abbcSIngo Weinhold		case B_HPKG_ATTRIBUTE_ID_PACKAGE_PROVIDES_TYPE:
193df295396SIngo Weinhold			// obsolete
1947575abbcSIngo Weinhold			break;
1957575abbcSIngo Weinhold
1967575abbcSIngo Weinhold		case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_MAJOR:
1977575abbcSIngo Weinhold			fPackageInfoValue.resolvable.haveVersion = true;
1987575abbcSIngo Weinhold			fPackageInfoValue.resolvable.version.major = value.string;
1997575abbcSIngo Weinhold			if (_handler != NULL) {
2007575abbcSIngo Weinhold				*_handler
2017575abbcSIngo Weinhold					= new(std::nothrow) PackageVersionAttributeHandler(
2027575abbcSIngo Weinhold						fPackageInfoValue,
2037575abbcSIngo Weinhold						fPackageInfoValue.resolvable.version, false);
2047575abbcSIngo Weinhold				if (*_handler == NULL)
2057575abbcSIngo Weinhold					return B_NO_MEMORY;
2067575abbcSIngo Weinhold			}
2077575abbcSIngo Weinhold			break;
2087575abbcSIngo Weinhold
2097575abbcSIngo Weinhold		case B_HPKG_ATTRIBUTE_ID_PACKAGE_PROVIDES_COMPATIBLE:
2107575abbcSIngo Weinhold			fPackageInfoValue.resolvable.haveCompatibleVersion = true;
2117575abbcSIngo Weinhold			fPackageInfoValue.resolvable.compatibleVersion.major = value.string;
2127575abbcSIngo Weinhold			if (_handler != NULL) {
2137575abbcSIngo Weinhold				*_handler
2147575abbcSIngo Weinhold					= new(std::nothrow) PackageVersionAttributeHandler(
2157575abbcSIngo Weinhold						fPackageInfoValue,
2167575abbcSIngo Weinhold						fPackageInfoValue.resolvable.compatibleVersion, false);
2177575abbcSIngo Weinhold				if (*_handler == NULL)
2187575abbcSIngo Weinhold					return B_NO_MEMORY;
2197575abbcSIngo Weinhold			}
2207575abbcSIngo Weinhold			break;
2217575abbcSIngo Weinhold
2227575abbcSIngo Weinhold		default:
2237575abbcSIngo Weinhold			context->errorOutput->PrintError("Error: Invalid package "
2247575abbcSIngo Weinhold				"attribute section: unexpected package attribute id %d "
2257575abbcSIngo Weinhold				"encountered when parsing package resolvable\n", id);
2267575abbcSIngo Weinhold			return B_BAD_DATA;
2277575abbcSIngo Weinhold	}
2287575abbcSIngo Weinhold
2297575abbcSIngo Weinhold	return B_OK;
2307575abbcSIngo Weinhold}
2317575abbcSIngo Weinhold
2327575abbcSIngo Weinhold
2337575abbcSIngo Weinholdstatus_t
2347575abbcSIngo WeinholdReaderImplBase::PackageResolvableAttributeHandler::Delete(
2357575abbcSIngo Weinhold	AttributeHandlerContext* context)
2367575abbcSIngo Weinhold{
2377575abbcSIngo Weinhold	status_t error = context->packageContentHandler->HandlePackageAttribute(
2387575abbcSIngo Weinhold		fPackageInfoValue);
2397575abbcSIngo Weinhold	fPackageInfoValue.Clear();
2407575abbcSIngo Weinhold
2417575abbcSIngo Weinhold	delete this;
2427575abbcSIngo Weinhold	return error;
2437575abbcSIngo Weinhold}
2447575abbcSIngo Weinhold
2457575abbcSIngo Weinhold
2467575abbcSIngo Weinhold// #pragma mark - PackageResolvableExpressionAttributeHandler
2477575abbcSIngo Weinhold
2487575abbcSIngo Weinhold
2497575abbcSIngo WeinholdReaderImplBase::PackageResolvableExpressionAttributeHandler
2507575abbcSIngo Weinhold	::PackageResolvableExpressionAttributeHandler(
2517575abbcSIngo Weinhold		BPackageInfoAttributeValue& packageInfoValue)
2527575abbcSIngo Weinhold	:
2537575abbcSIngo Weinhold	fPackageInfoValue(packageInfoValue)
2547575abbcSIngo Weinhold{
2557575abbcSIngo Weinhold}
2567575abbcSIngo Weinhold
2577575abbcSIngo Weinhold
2587575abbcSIngo Weinholdstatus_t
2597575abbcSIngo WeinholdReaderImplBase::PackageResolvableExpressionAttributeHandler::HandleAttribute(
2607575abbcSIngo Weinhold	AttributeHandlerContext* context, uint8 id, const AttributeValue& value,
2617575abbcSIngo Weinhold	AttributeHandler** _handler)
2627575abbcSIngo Weinhold{
2637575abbcSIngo Weinhold	switch (id) {
2647575abbcSIngo Weinhold		case B_HPKG_ATTRIBUTE_ID_PACKAGE_RESOLVABLE_OPERATOR:
2657575abbcSIngo Weinhold			if (value.unsignedInt >= B_PACKAGE_RESOLVABLE_OP_ENUM_COUNT) {
2667575abbcSIngo Weinhold				context->errorOutput->PrintError(
2677575abbcSIngo Weinhold					"Error: Invalid package attribute section: invalid "
2687575abbcSIngo Weinhold					"package resolvable operator %lld encountered\n",
2697575abbcSIngo Weinhold					value.unsignedInt);
2707575abbcSIngo Weinhold				return B_BAD_DATA;
2717575abbcSIngo Weinhold			}
2727575abbcSIngo Weinhold			fPackageInfoValue.resolvableExpression.op
2737575abbcSIngo Weinhold				= (BPackageResolvableOperator)value.unsignedInt;
2747575abbcSIngo Weinhold			break;
2757575abbcSIngo Weinhold
2767575abbcSIngo Weinhold		case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_MAJOR:
2777575abbcSIngo Weinhold			fPackageInfoValue.resolvableExpression.haveOpAndVersion = true;
2787575abbcSIngo Weinhold			fPackageInfoValue.resolvableExpression.version.major
2797575abbcSIngo Weinhold				= value.string;
2807575abbcSIngo Weinhold			if (_handler != NULL) {
2817575abbcSIngo Weinhold				*_handler
2827575abbcSIngo Weinhold					= new(std::nothrow) PackageVersionAttributeHandler(
2837575abbcSIngo Weinhold						fPackageInfoValue,
2847575abbcSIngo Weinhold						fPackageInfoValue.resolvableExpression.version,
2857575abbcSIngo Weinhold						false);
2867575abbcSIngo Weinhold				if (*_handler == NULL)
2877575abbcSIngo Weinhold					return B_NO_MEMORY;
2887575abbcSIngo Weinhold			}
2897575abbcSIngo Weinhold			return B_OK;
2907575abbcSIngo Weinhold
2917575abbcSIngo Weinhold		default:
2927575abbcSIngo Weinhold			context->errorOutput->PrintError("Error: Invalid package "
2937575abbcSIngo Weinhold				"attribute section: unexpected package attribute id %d "
2947575abbcSIngo Weinhold				"encountered when parsing package resolvable-expression\n",
2957575abbcSIngo Weinhold				id);
2967575abbcSIngo Weinhold			return B_BAD_DATA;
2977575abbcSIngo Weinhold	}
2987575abbcSIngo Weinhold
2997575abbcSIngo Weinhold	return B_OK;
3007575abbcSIngo Weinhold}
3017575abbcSIngo Weinhold
3027575abbcSIngo Weinhold
3037575abbcSIngo Weinholdstatus_t
3047575abbcSIngo WeinholdReaderImplBase::PackageResolvableExpressionAttributeHandler::Delete(
3057575abbcSIngo Weinhold	AttributeHandlerContext* context)
3067575abbcSIngo Weinhold{
3077575abbcSIngo Weinhold	status_t error = context->packageContentHandler->HandlePackageAttribute(
3087575abbcSIngo Weinhold		fPackageInfoValue);
3097575abbcSIngo Weinhold	fPackageInfoValue.Clear();
3107575abbcSIngo Weinhold
3117575abbcSIngo Weinhold	delete this;
3127575abbcSIngo Weinhold	return error;
3137575abbcSIngo Weinhold}
3147575abbcSIngo Weinhold
3157575abbcSIngo Weinhold
3167575abbcSIngo Weinhold// #pragma mark - PackageAttributeHandler
3177575abbcSIngo Weinhold
3187575abbcSIngo Weinhold
3197575abbcSIngo Weinholdstatus_t
3207575abbcSIngo WeinholdReaderImplBase::PackageAttributeHandler::HandleAttribute(
3217575abbcSIngo Weinhold	AttributeHandlerContext* context, uint8 id, const AttributeValue& value,
3227575abbcSIngo Weinhold	AttributeHandler** _handler)
3237575abbcSIngo Weinhold{
3247575abbcSIngo Weinhold	switch (id) {
3257575abbcSIngo Weinhold		case B_HPKG_ATTRIBUTE_ID_PACKAGE_NAME:
3267575abbcSIngo Weinhold			fPackageInfoValue.SetTo(B_PACKAGE_INFO_NAME, value.string);
3277575abbcSIngo Weinhold			break;
3287575abbcSIngo Weinhold
3297575abbcSIngo Weinhold		case B_HPKG_ATTRIBUTE_ID_PACKAGE_SUMMARY:
3307575abbcSIngo Weinhold			fPackageInfoValue.SetTo(B_PACKAGE_INFO_SUMMARY, value.string);
3317575abbcSIngo Weinhold			break;
3327575abbcSIngo Weinhold
3337575abbcSIngo Weinhold		case B_HPKG_ATTRIBUTE_ID_PACKAGE_DESCRIPTION:
3347575abbcSIngo Weinhold			fPackageInfoValue.SetTo(B_PACKAGE_INFO_DESCRIPTION,
3357575abbcSIngo Weinhold				value.string);
3367575abbcSIngo Weinhold			break;
3377575abbcSIngo Weinhold
3387575abbcSIngo Weinhold		case B_HPKG_ATTRIBUTE_ID_PACKAGE_VENDOR:
3397575abbcSIngo Weinhold			fPackageInfoValue.SetTo(B_PACKAGE_INFO_VENDOR, value.string);
3407575abbcSIngo Weinhold			break;
3417575abbcSIngo Weinhold
3427575abbcSIngo Weinhold		case B_HPKG_ATTRIBUTE_ID_PACKAGE_PACKAGER:
3437575abbcSIngo Weinhold			fPackageInfoValue.SetTo(B_PACKAGE_INFO_PACKAGER, value.string);
3447575abbcSIngo Weinhold			break;
3457575abbcSIngo Weinhold
3467575abbcSIngo Weinhold		case B_HPKG_ATTRIBUTE_ID_PACKAGE_FLAGS:
3477575abbcSIngo Weinhold			fPackageInfoValue.SetTo(B_PACKAGE_INFO_FLAGS,
3487575abbcSIngo Weinhold				(uint32)value.unsignedInt);
3497575abbcSIngo Weinhold			break;
3507575abbcSIngo Weinhold
3517575abbcSIngo Weinhold		case B_HPKG_ATTRIBUTE_ID_PACKAGE_ARCHITECTURE:
3527575abbcSIngo Weinhold			if (value.unsignedInt
3537575abbcSIngo Weinhold					>= B_PACKAGE_ARCHITECTURE_ENUM_COUNT) {
3547575abbcSIngo Weinhold				context->errorOutput->PrintError(
3557575abbcSIngo Weinhold					"Error: Invalid package attribute section: "
3567575abbcSIngo Weinhold					"Invalid package architecture %lld encountered\n",
3577575abbcSIngo Weinhold					value.unsignedInt);
3587575abbcSIngo Weinhold				return B_BAD_DATA;
3597575abbcSIngo Weinhold			}
3607575abbcSIngo Weinhold			fPackageInfoValue.SetTo(B_PACKAGE_INFO_ARCHITECTURE,
3617575abbcSIngo Weinhold				(uint8)value.unsignedInt);
3627575abbcSIngo Weinhold			break;
3637575abbcSIngo Weinhold
3647575abbcSIngo Weinhold		case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_MAJOR:
3657575abbcSIngo Weinhold			fPackageInfoValue.attributeID = B_PACKAGE_INFO_VERSION;
3667575abbcSIngo Weinhold			fPackageInfoValue.version.major = value.string;
3677575abbcSIngo Weinhold			if (_handler != NULL) {
3687575abbcSIngo Weinhold				*_handler
3697575abbcSIngo Weinhold					= new(std::nothrow) PackageVersionAttributeHandler(
3707575abbcSIngo Weinhold						fPackageInfoValue, fPackageInfoValue.version, true);
3717575abbcSIngo Weinhold				if (*_handler == NULL)
3727575abbcSIngo Weinhold					return B_NO_MEMORY;
3737575abbcSIngo Weinhold			}
3747575abbcSIngo Weinhold			break;
3757575abbcSIngo Weinhold
3767575abbcSIngo Weinhold		case B_HPKG_ATTRIBUTE_ID_PACKAGE_COPYRIGHT:
3777575abbcSIngo Weinhold			fPackageInfoValue.SetTo(B_PACKAGE_INFO_COPYRIGHTS,
3787575abbcSIngo Weinhold				value.string);
3797575abbcSIngo Weinhold			break;
3807575abbcSIngo Weinhold
3817575abbcSIngo Weinhold		case B_HPKG_ATTRIBUTE_ID_PACKAGE_LICENSE:
3827575abbcSIngo Weinhold			fPackageInfoValue.SetTo(B_PACKAGE_INFO_LICENSES,
3837575abbcSIngo Weinhold				value.string);
3847575abbcSIngo Weinhold			break;
3857575abbcSIngo Weinhold
3867575abbcSIngo Weinhold		case B_HPKG_ATTRIBUTE_ID_PACKAGE_URL:
3877575abbcSIngo Weinhold			fPackageInfoValue.SetTo(B_PACKAGE_INFO_URLS, value.string);
3887575abbcSIngo Weinhold			break;
3897575abbcSIngo Weinhold
3907575abbcSIngo Weinhold		case B_HPKG_ATTRIBUTE_ID_PACKAGE_SOURCE_URL:
3917575abbcSIngo Weinhold			fPackageInfoValue.SetTo(B_PACKAGE_INFO_SOURCE_URLS, value.string);
3927575abbcSIngo Weinhold			break;
3937575abbcSIngo Weinhold
3947575abbcSIngo Weinhold		case B_HPKG_ATTRIBUTE_ID_PACKAGE_PROVIDES:
3957575abbcSIngo Weinhold			fPackageInfoValue.resolvable.name = value.string;
3967575abbcSIngo Weinhold			fPackageInfoValue.attributeID = B_PACKAGE_INFO_PROVIDES;
3977575abbcSIngo Weinhold			if (_handler != NULL) {
3987575abbcSIngo Weinhold				*_handler
3997575abbcSIngo Weinhold					= new(std::nothrow) PackageResolvableAttributeHandler(
4007575abbcSIngo Weinhold						fPackageInfoValue);
4017575abbcSIngo Weinhold				if (*_handler == NULL)
4027575abbcSIngo Weinhold					return B_NO_MEMORY;
4037575abbcSIngo Weinhold			}
4047575abbcSIngo Weinhold			break;
4057575abbcSIngo Weinhold
4067575abbcSIngo Weinhold		case B_HPKG_ATTRIBUTE_ID_PACKAGE_REQUIRES:
4077575abbcSIngo Weinhold		case B_HPKG_ATTRIBUTE_ID_PACKAGE_SUPPLEMENTS:
4087575abbcSIngo Weinhold		case B_HPKG_ATTRIBUTE_ID_PACKAGE_CONFLICTS:
4097575abbcSIngo Weinhold		case B_HPKG_ATTRIBUTE_ID_PACKAGE_FRESHENS:
4107575abbcSIngo Weinhold			fPackageInfoValue.resolvableExpression.name = value.string;
4117575abbcSIngo Weinhold			switch (id) {
4127575abbcSIngo Weinhold				case B_HPKG_ATTRIBUTE_ID_PACKAGE_REQUIRES:
4137575abbcSIngo Weinhold					fPackageInfoValue.attributeID = B_PACKAGE_INFO_REQUIRES;
4147575abbcSIngo Weinhold					break;
4157575abbcSIngo Weinhold
4167575abbcSIngo Weinhold				case B_HPKG_ATTRIBUTE_ID_PACKAGE_SUPPLEMENTS:
4177575abbcSIngo Weinhold					fPackageInfoValue.attributeID
4187575abbcSIngo Weinhold						= B_PACKAGE_INFO_SUPPLEMENTS;
4197575abbcSIngo Weinhold					break;
4207575abbcSIngo Weinhold
4217575abbcSIngo Weinhold				case B_HPKG_ATTRIBUTE_ID_PACKAGE_CONFLICTS:
4227575abbcSIngo Weinhold					fPackageInfoValue.attributeID
4237575abbcSIngo Weinhold						= B_PACKAGE_INFO_CONFLICTS;
4247575abbcSIngo Weinhold					break;
4257575abbcSIngo Weinhold
4267575abbcSIngo Weinhold				case B_HPKG_ATTRIBUTE_ID_PACKAGE_FRESHENS:
4277575abbcSIngo Weinhold					fPackageInfoValue.attributeID = B_PACKAGE_INFO_FRESHENS;
4287575abbcSIngo Weinhold					break;
4297575abbcSIngo Weinhold			}
4307575abbcSIngo Weinhold			if (_handler != NULL) {
4317575abbcSIngo Weinhold				*_handler = new(std::nothrow)
4327575abbcSIngo Weinhold					PackageResolvableExpressionAttributeHandler(
4337575abbcSIngo Weinhold						fPackageInfoValue);
4347575abbcSIngo Weinhold				if (*_handler == NULL)
4357575abbcSIngo Weinhold					return B_NO_MEMORY;
4367575abbcSIngo Weinhold			}
4377575abbcSIngo Weinhold			break;
4387575abbcSIngo Weinhold
4397575abbcSIngo Weinhold		case B_HPKG_ATTRIBUTE_ID_PACKAGE_REPLACES:
4407575abbcSIngo Weinhold			fPackageInfoValue.SetTo(B_PACKAGE_INFO_REPLACES, value.string);
4417575abbcSIngo Weinhold			break;
4427575abbcSIngo Weinhold
4437575abbcSIngo Weinhold		case B_HPKG_ATTRIBUTE_ID_PACKAGE_CHECKSUM:
4447575abbcSIngo Weinhold			fPackageInfoValue.SetTo(B_PACKAGE_INFO_CHECKSUM, value.string);
4457575abbcSIngo Weinhold			break;
4467575abbcSIngo Weinhold
4477575abbcSIngo Weinhold		case B_HPKG_ATTRIBUTE_ID_PACKAGE_INSTALL_PATH:
4487575abbcSIngo Weinhold			fPackageInfoValue.SetTo(B_PACKAGE_INFO_INSTALL_PATH, value.string);
4497575abbcSIngo Weinhold			break;
4507575abbcSIngo Weinhold
4517575abbcSIngo Weinhold		default:
4527575abbcSIngo Weinhold			context->errorOutput->PrintError(
4537575abbcSIngo Weinhold				"Error: Invalid package attribute section: unexpected "
4547575abbcSIngo Weinhold				"package attribute id %d encountered\n", id);
4557575abbcSIngo Weinhold			return B_BAD_DATA;
4567575abbcSIngo Weinhold	}
4577575abbcSIngo Weinhold
4587575abbcSIngo Weinhold	// notify unless the current attribute has children, in which case
4597575abbcSIngo Weinhold	// the child-handler will notify when it's done
4607575abbcSIngo Weinhold	if (_handler == NULL) {
4617575abbcSIngo Weinhold		status_t error = context->packageContentHandler
4627575abbcSIngo Weinhold			->HandlePackageAttribute(fPackageInfoValue);
4637575abbcSIngo Weinhold		fPackageInfoValue.Clear();
4647575abbcSIngo Weinhold		if (error != B_OK)
4657575abbcSIngo Weinhold			return error;
4667575abbcSIngo Weinhold	}
4677575abbcSIngo Weinhold
4687575abbcSIngo Weinhold	return B_OK;
4697575abbcSIngo Weinhold}
4707575abbcSIngo Weinhold
4717575abbcSIngo Weinhold
4727575abbcSIngo Weinhold// #pragma mark - LowLevelAttributeHandler
4737575abbcSIngo Weinhold
4747575abbcSIngo Weinhold
4757575abbcSIngo WeinholdReaderImplBase::LowLevelAttributeHandler::LowLevelAttributeHandler()
4767575abbcSIngo Weinhold	:
4777575abbcSIngo Weinhold	fParentToken(NULL),
4787575abbcSIngo Weinhold	fToken(NULL),
4797575abbcSIngo Weinhold	fID(B_HPKG_ATTRIBUTE_ID_ENUM_COUNT)
4807575abbcSIngo Weinhold{
4817575abbcSIngo Weinhold}
4827575abbcSIngo Weinhold
4837575abbcSIngo Weinhold
4847575abbcSIngo WeinholdReaderImplBase::LowLevelAttributeHandler::LowLevelAttributeHandler(uint8 id,
4857575abbcSIngo Weinhold	const BPackageAttributeValue& value, void* parentToken, void* token)
4867575abbcSIngo Weinhold	:
4877575abbcSIngo Weinhold	fParentToken(NULL),
4887575abbcSIngo Weinhold	fToken(token),
4897575abbcSIngo Weinhold	fID(id),
4907575abbcSIngo Weinhold	fValue(value)
4917575abbcSIngo Weinhold{
4927575abbcSIngo Weinhold}
4937575abbcSIngo Weinhold
4947575abbcSIngo Weinhold
4957575abbcSIngo Weinholdstatus_t
4967575abbcSIngo WeinholdReaderImplBase::LowLevelAttributeHandler::HandleAttribute(
4977575abbcSIngo Weinhold	AttributeHandlerContext* context, uint8 id, const AttributeValue& value,
4987575abbcSIngo Weinhold	AttributeHandler** _handler)
4997575abbcSIngo Weinhold{
5007575abbcSIngo Weinhold	// notify the content handler
5017575abbcSIngo Weinhold	void* token;
5027575abbcSIngo Weinhold	status_t error = context->lowLevelHandler->HandleAttribute(
5037575abbcSIngo Weinhold		(BHPKGAttributeID)id, value, fToken, token);
5047575abbcSIngo Weinhold	if (error != B_OK)
5057575abbcSIngo Weinhold		return error;
5067575abbcSIngo Weinhold
5077575abbcSIngo Weinhold	// create a subhandler for the attribute, if it has children
5087575abbcSIngo Weinhold	if (_handler != NULL) {
5097575abbcSIngo Weinhold		*_handler = new(std::nothrow) LowLevelAttributeHandler(id, value,
5107575abbcSIngo Weinhold			fToken, token);
5117575abbcSIngo Weinhold		if (*_handler == NULL) {
5127575abbcSIngo Weinhold			context->lowLevelHandler->HandleAttributeDone((BHPKGAttributeID)id,
5137575abbcSIngo Weinhold				value, fToken, token);
5147575abbcSIngo Weinhold			return B_NO_MEMORY;
5157575abbcSIngo Weinhold		}
5167575abbcSIngo Weinhold		return B_OK;
5177575abbcSIngo Weinhold	}
5187575abbcSIngo Weinhold
5197575abbcSIngo Weinhold	// no children -- just call the done hook
5207575abbcSIngo Weinhold	return context->lowLevelHandler->HandleAttributeDone((BHPKGAttributeID)id,
5217575abbcSIngo Weinhold		value, fToken, token);
5227575abbcSIngo Weinhold}
5237575abbcSIngo Weinhold
5247575abbcSIngo Weinhold
5257575abbcSIngo Weinholdstatus_t
5267575abbcSIngo WeinholdReaderImplBase::LowLevelAttributeHandler::Delete(
5277575abbcSIngo Weinhold	AttributeHandlerContext* context)
5287575abbcSIngo Weinhold{
5297575abbcSIngo Weinhold	status_t error = B_OK;
5307575abbcSIngo Weinhold	if (fID != B_HPKG_ATTRIBUTE_ID_ENUM_COUNT) {
5317575abbcSIngo Weinhold		error = context->lowLevelHandler->HandleAttributeDone(
5327575abbcSIngo Weinhold			(BHPKGAttributeID)fID, fValue, fParentToken, fToken);
5337575abbcSIngo Weinhold	}
5347575abbcSIngo Weinhold
5357575abbcSIngo Weinhold	delete this;
5367575abbcSIngo Weinhold	return error;
5377575abbcSIngo Weinhold}
5387575abbcSIngo Weinhold
5397575abbcSIngo Weinhold
5407575abbcSIngo Weinhold// #pragma mark - ReaderImplBase
5417575abbcSIngo Weinhold
5427575abbcSIngo Weinhold
5437575abbcSIngo WeinholdReaderImplBase::ReaderImplBase(BErrorOutput* errorOutput)
5447575abbcSIngo Weinhold	:
5457575abbcSIngo Weinhold	fPackageAttributesSection("package attributes"),
5467575abbcSIngo Weinhold	fErrorOutput(errorOutput),
5477575abbcSIngo Weinhold	fFD(-1),
5487575abbcSIngo Weinhold	fOwnsFD(false),
5497575abbcSIngo Weinhold	fCurrentSection(NULL),
5507575abbcSIngo Weinhold	fScratchBuffer(NULL),
5517575abbcSIngo Weinhold	fScratchBufferSize(0)
5527575abbcSIngo Weinhold{
5537575abbcSIngo Weinhold}
5547575abbcSIngo Weinhold
5557575abbcSIngo Weinhold
5567575abbcSIngo WeinholdReaderImplBase::~ReaderImplBase()
5577575abbcSIngo Weinhold{
5587575abbcSIngo Weinhold	if (fOwnsFD && fFD >= 0)
5597575abbcSIngo Weinhold		close(fFD);
5607575abbcSIngo Weinhold
5617575abbcSIngo Weinhold	delete[] fScratchBuffer;
5627575abbcSIngo Weinhold}
5637575abbcSIngo Weinhold
5647575abbcSIngo Weinhold
5657575abbcSIngo Weinholdstatus_t
5667575abbcSIngo WeinholdReaderImplBase::Init(int fd, bool keepFD)
5677575abbcSIngo Weinhold{
5687575abbcSIngo Weinhold	fFD = fd;
5697575abbcSIngo Weinhold	fOwnsFD = keepFD;
5707575abbcSIngo Weinhold
5717575abbcSIngo Weinhold	// allocate a scratch buffer
5727575abbcSIngo Weinhold	fScratchBuffer = new(std::nothrow) uint8[kScratchBufferSize];
5737575abbcSIngo Weinhold	if (fScratchBuffer == NULL) {
5747575abbcSIngo Weinhold		fErrorOutput->PrintError("Error: Out of memory!\n");
5757575abbcSIngo Weinhold		return B_NO_MEMORY;
5767575abbcSIngo Weinhold	}
5777575abbcSIngo Weinhold	fScratchBufferSize = kScratchBufferSize;
5787575abbcSIngo Weinhold
5797575abbcSIngo Weinhold	return B_OK;
5807575abbcSIngo Weinhold}
5817575abbcSIngo Weinhold
5827575abbcSIngo Weinhold
5837575abbcSIngo Weinholdconst char*
5847575abbcSIngo WeinholdReaderImplBase::CheckCompression(const SectionInfo& section) const
5857575abbcSIngo Weinhold{
5867575abbcSIngo Weinhold	switch (section.compression) {
5877575abbcSIngo Weinhold		case B_HPKG_COMPRESSION_NONE:
5887575abbcSIngo Weinhold			if (section.compressedLength != section.uncompressedLength) {
5897575abbcSIngo Weinhold				return "Uncompressed, but compressed and uncompressed length "
5907575abbcSIngo Weinhold					"don't match";
5917575abbcSIngo Weinhold			}
5927575abbcSIngo Weinhold			return NULL;
5937575abbcSIngo Weinhold
5947575abbcSIngo Weinhold		case B_HPKG_COMPRESSION_ZLIB:
5957575abbcSIngo Weinhold			if (section.compressedLength >= section.uncompressedLength) {
5967575abbcSIngo Weinhold				return "Compressed, but compressed length is not less than "
5977575abbcSIngo Weinhold					"uncompressed length";
5987575abbcSIngo Weinhold			}
5997575abbcSIngo Weinhold			return NULL;
6007575abbcSIngo Weinhold
6017575abbcSIngo Weinhold		default:
6027575abbcSIngo Weinhold			return "Invalid compression algorithm ID";
6037575abbcSIngo Weinhold	}
6047575abbcSIngo Weinhold}
6057575abbcSIngo Weinhold
6067575abbcSIngo Weinhold
6077575abbcSIngo Weinholdstatus_t
6087575abbcSIngo WeinholdReaderImplBase::ParseStrings()
6097575abbcSIngo Weinhold{
6107575abbcSIngo Weinhold	// allocate table, if there are any strings
6117575abbcSIngo Weinhold	if (fCurrentSection->stringsCount == 0) {
6127575abbcSIngo Weinhold		fCurrentSection->currentOffset += fCurrentSection->stringsLength;
6137575abbcSIngo Weinhold		return B_OK;
6147575abbcSIngo Weinhold	}
6157575abbcSIngo Weinhold
6167575abbcSIngo Weinhold	fCurrentSection->strings
6177575abbcSIngo Weinhold		= new(std::nothrow) char*[fCurrentSection->stringsCount];
6187575abbcSIngo Weinhold	if (fCurrentSection->strings == NULL) {
6197575abbcSIngo Weinhold		fErrorOutput->PrintError("Error: Out of memory!\n");
6207575abbcSIngo Weinhold		return B_NO_MEMORY;
6217575abbcSIngo Weinhold	}
6227575abbcSIngo Weinhold
6237575abbcSIngo Weinhold	// parse the section and fill the table
6247575abbcSIngo Weinhold	char* position
6257575abbcSIngo Weinhold		= (char*)fCurrentSection->data + fCurrentSection->currentOffset;
6267575abbcSIngo Weinhold	char* sectionEnd = position + fCurrentSection->stringsLength;
6277575abbcSIngo Weinhold	uint32 index = 0;
6287575abbcSIngo Weinhold	while (true) {
6297575abbcSIngo Weinhold		if (position >= sectionEnd) {
6307575abbcSIngo Weinhold			fErrorOutput->PrintError("Error: Malformed %s strings section\n",
6317575abbcSIngo Weinhold				fCurrentSection->name);
6327575abbcSIngo Weinhold			return B_BAD_DATA;
6337575abbcSIngo Weinhold		}
6347575abbcSIngo Weinhold
6357575abbcSIngo Weinhold		size_t stringLength = strnlen(position, (char*)sectionEnd - position);
6367575abbcSIngo Weinhold
6377575abbcSIngo Weinhold		if (stringLength == 0) {
6387575abbcSIngo Weinhold			if (position + 1 != sectionEnd) {
6397575abbcSIngo Weinhold				fErrorOutput->PrintError(
6407575abbcSIngo Weinhold					"Error: %ld excess bytes in %s strings section\n",
6417575abbcSIngo Weinhold					sectionEnd - (position + 1), fCurrentSection->name);
6427575abbcSIngo Weinhold				return B_BAD_DATA;
6437575abbcSIngo Weinhold			}
6447575abbcSIngo Weinhold
6457575abbcSIngo Weinhold			if (index != fCurrentSection->stringsCount) {
6467575abbcSIngo Weinhold				fErrorOutput->PrintError("Error: Invalid %s strings section: "
6477575abbcSIngo Weinhold					"Less strings (%lld) than specified in the header (%lld)\n",
6487575abbcSIngo Weinhold					fCurrentSection->name, index,
6497575abbcSIngo Weinhold					fCurrentSection->stringsCount);
6507575abbcSIngo Weinhold				return B_BAD_DATA;
6517575abbcSIngo Weinhold			}
6527575abbcSIngo Weinhold
6537575abbcSIngo Weinhold			fCurrentSection->currentOffset += fCurrentSection->stringsLength;
6547575abbcSIngo Weinhold
6557575abbcSIngo Weinhold			return B_OK;
6567575abbcSIngo Weinhold		}
6577575abbcSIngo Weinhold
6587575abbcSIngo Weinhold		if (index >= fCurrentSection->stringsCount) {
6597575abbcSIngo Weinhold			fErrorOutput->PrintError("Error: Invalid %s strings section: "
6607575abbcSIngo Weinhold				"More strings (%lld) than specified in the header (%lld)\n",
6617575abbcSIngo Weinhold				fCurrentSection->name, index, fCurrentSection->stringsCount);
6627575abbcSIngo Weinhold			return B_BAD_DATA;
6637575abbcSIngo Weinhold		}
6647575abbcSIngo Weinhold
6657575abbcSIngo Weinhold		fCurrentSection->strings[index++] = position;
6667575abbcSIngo Weinhold		position += stringLength + 1;
6677575abbcSIngo Weinhold	}
6687575abbcSIngo Weinhold}
6697575abbcSIngo Weinhold
6707575abbcSIngo Weinhold
6717575abbcSIngo Weinholdstatus_t
6727575abbcSIngo WeinholdReaderImplBase::ParsePackageAttributesSection(
6737575abbcSIngo Weinhold	AttributeHandlerContext* context, AttributeHandler* rootAttributeHandler)
6747575abbcSIngo Weinhold{
6757575abbcSIngo Weinhold	// parse package attributes
6767575abbcSIngo Weinhold	SetCurrentSection(&fPackageAttributesSection);
6777575abbcSIngo Weinhold
6787575abbcSIngo Weinhold	// init the attribute handler stack
6797575abbcSIngo Weinhold	rootAttributeHandler->SetLevel(0);
6807575abbcSIngo Weinhold	ClearAttributeHandlerStack();
6817575abbcSIngo Weinhold	PushAttributeHandler(rootAttributeHandler);
6827575abbcSIngo Weinhold
6837575abbcSIngo Weinhold	bool sectionHandled;
6847575abbcSIngo Weinhold	status_t error = ParseAttributeTree(context, sectionHandled);
6857575abbcSIngo Weinhold	if (error == B_OK && sectionHandled) {
6867575abbcSIngo Weinhold		if (fPackageAttributesSection.currentOffset
6877575abbcSIngo Weinhold				< fPackageAttributesSection.uncompressedLength) {
6887575abbcSIngo Weinhold			fErrorOutput->PrintError("Error: %llu excess byte(s) in package "
6897575abbcSIngo Weinhold				"attributes section\n",
6907575abbcSIngo Weinhold				fPackageAttributesSection.uncompressedLength
6917575abbcSIngo Weinhold					- fPackageAttributesSection.currentOffset);
6927575abbcSIngo Weinhold			error = B_BAD_DATA;
6937575abbcSIngo Weinhold		}
6947575abbcSIngo Weinhold	}
6957575abbcSIngo Weinhold
6967575abbcSIngo Weinhold	SetCurrentSection(NULL);
6977575abbcSIngo Weinhold
6987575abbcSIngo Weinhold	// clean up on error
6997575abbcSIngo Weinhold	if (error != B_OK) {
7007575abbcSIngo Weinhold		context->ErrorOccurred();
7017575abbcSIngo Weinhold		while (AttributeHandler* handler = PopAttributeHandler()) {
7027575abbcSIngo Weinhold			if (handler != rootAttributeHandler)
7037575abbcSIngo Weinhold				handler->Delete(context);
7047575abbcSIngo Weinhold		}
7057575abbcSIngo Weinhold		return error;
7067575abbcSIngo Weinhold	}
7077575abbcSIngo Weinhold
7087575abbcSIngo Weinhold	return B_OK;
7097575abbcSIngo Weinhold}
7107575abbcSIngo Weinhold
7117575abbcSIngo Weinhold
7127575abbcSIngo Weinholdstatus_t
7137575abbcSIngo WeinholdReaderImplBase::ParseAttributeTree(AttributeHandlerContext* context,
7147575abbcSIngo Weinhold	bool& _sectionHandled)
7157575abbcSIngo Weinhold{
7167575abbcSIngo Weinhold	if (context->hasLowLevelHandler) {
7177575abbcSIngo Weinhold		bool handleSection = false;
7187575abbcSIngo Weinhold		status_t error = context->lowLevelHandler->HandleSectionStart(
7197575abbcSIngo Weinhold			context->section, handleSection);
7207575abbcSIngo Weinhold		if (error != B_OK)
7217575abbcSIngo Weinhold			return error;
7227575abbcSIngo Weinhold
7237575abbcSIngo Weinhold		if (!handleSection) {
7247575abbcSIngo Weinhold			_sectionHandled = false;
7257575abbcSIngo Weinhold			return B_OK;
7267575abbcSIngo Weinhold		}
7277575abbcSIngo Weinhold	}
7287575abbcSIngo Weinhold
7297575abbcSIngo Weinhold	status_t error = _ParseAttributeTree(context);
7307575abbcSIngo Weinhold
7317575abbcSIngo Weinhold	if (context->hasLowLevelHandler) {
7327575abbcSIngo Weinhold		status_t endError = context->lowLevelHandler->HandleSectionEnd(
7337575abbcSIngo Weinhold			context->section);
7347575abbcSIngo Weinhold		if (error == B_OK)
7357575abbcSIngo Weinhold			error = endError;
7367575abbcSIngo Weinhold	}
7377575abbcSIngo Weinhold
7387575abbcSIngo Weinhold	_sectionHandled = true;
7397575abbcSIngo Weinhold	return error;
7407575abbcSIngo Weinhold}
7417575abbcSIngo Weinhold
7427575abbcSIngo Weinhold
7437575abbcSIngo Weinholdstatus_t
7447575abbcSIngo WeinholdReaderImplBase::_ParseAttributeTree(AttributeHandlerContext* context)
7457575abbcSIngo Weinhold{
7467575abbcSIngo Weinhold	int level = 0;
7477575abbcSIngo Weinhold
7487575abbcSIngo Weinhold	while (true) {
7497575abbcSIngo Weinhold		uint8 id;
7507575abbcSIngo Weinhold		AttributeValue value;
7517575abbcSIngo Weinhold		bool hasChildren;
7527575abbcSIngo Weinhold		uint64 tag;
7537575abbcSIngo Weinhold
7547575abbcSIngo Weinhold		status_t error = _ReadAttribute(id, value, &hasChildren, &tag);
7557575abbcSIngo Weinhold		if (error != B_OK)
7567575abbcSIngo Weinhold			return error;
7577575abbcSIngo Weinhold
7587575abbcSIngo Weinhold		if (tag == 0) {
7597575abbcSIngo Weinhold			AttributeHandler* handler = PopAttributeHandler();
7607575abbcSIngo Weinhold			if (level-- == 0)
7617575abbcSIngo Weinhold				return B_OK;
7627575abbcSIngo Weinhold
7637575abbcSIngo Weinhold			error = handler->Delete(context);
7647575abbcSIngo Weinhold			if (error != B_OK)
7657575abbcSIngo Weinhold				return error;
7667575abbcSIngo Weinhold
7677575abbcSIngo Weinhold			continue;
7687575abbcSIngo Weinhold		}
7697575abbcSIngo Weinhold
7707575abbcSIngo Weinhold		AttributeHandler* childHandler = NULL;
7717575abbcSIngo Weinhold		error = CurrentAttributeHandler()->HandleAttribute(context, id, value,
7727575abbcSIngo Weinhold			hasChildren ? &childHandler : NULL);
7737575abbcSIngo Weinhold		if (error != B_OK)
7747575abbcSIngo Weinhold			return error;
7757575abbcSIngo Weinhold
7767575abbcSIngo Weinhold		// parse children
7777575abbcSIngo Weinhold		if (hasChildren) {
7787575abbcSIngo Weinhold			// create an ignore handler, if necessary
7797575abbcSIngo Weinhold			if (childHandler == NULL) {
7807575abbcSIngo Weinhold				childHandler = new(std::nothrow) IgnoreAttributeHandler;
7817575abbcSIngo Weinhold				if (childHandler == NULL) {
7827575abbcSIngo Weinhold					fErrorOutput->PrintError("Error: Out of memory!\n");
7837575abbcSIngo Weinhold					return B_NO_MEMORY;
7847575abbcSIngo Weinhold				}
7857575abbcSIngo Weinhold			}
7867575abbcSIngo Weinhold
7877575abbcSIngo Weinhold			childHandler->SetLevel(++level);
7887575abbcSIngo Weinhold			PushAttributeHandler(childHandler);
7897575abbcSIngo Weinhold		}
7907575abbcSIngo Weinhold	}
7917575abbcSIngo Weinhold}
7927575abbcSIngo Weinhold
7937575abbcSIngo Weinhold
7947575abbcSIngo Weinholdstatus_t
7957575abbcSIngo WeinholdReaderImplBase::_ReadAttribute(uint8& _id, AttributeValue& _value,
7967575abbcSIngo Weinhold	bool* _hasChildren, uint64* _tag)
7977575abbcSIngo Weinhold{
7987575abbcSIngo Weinhold	uint64 tag;
7997575abbcSIngo Weinhold	status_t error = ReadUnsignedLEB128(tag);
8007575abbcSIngo Weinhold	if (error != B_OK)
8017575abbcSIngo Weinhold		return error;
8027575abbcSIngo Weinhold
8037575abbcSIngo Weinhold	if (tag != 0) {
8047575abbcSIngo Weinhold		// get the type
8057575abbcSIngo Weinhold		uint16 type = attribute_tag_type(tag);
8067575abbcSIngo Weinhold		if (type >= B_HPKG_ATTRIBUTE_TYPE_ENUM_COUNT) {
8077575abbcSIngo Weinhold			fErrorOutput->PrintError("Error: Invalid %s section: attribute "
8087575abbcSIngo Weinhold				"type %d not supported!\n", fCurrentSection->name, type);
8097575abbcSIngo Weinhold			return B_BAD_DATA;
8107575abbcSIngo Weinhold		}
8117575abbcSIngo Weinhold
8127575abbcSIngo Weinhold		// get the value
8137575abbcSIngo Weinhold		error = ReadAttributeValue(type, attribute_tag_encoding(tag),
8147575abbcSIngo Weinhold			_value);
8157575abbcSIngo Weinhold		if (error != B_OK)
8167575abbcSIngo Weinhold			return error;
8177575abbcSIngo Weinhold
8187575abbcSIngo Weinhold		_id = attribute_tag_id(tag);
8197575abbcSIngo Weinhold		if (_id >= B_HPKG_ATTRIBUTE_ID_ENUM_COUNT) {
8207575abbcSIngo Weinhold			fErrorOutput->PrintError("Error: Invalid %s section: "
8217575abbcSIngo Weinhold				"attribute id %d not supported!\n", fCurrentSection->name, _id);
8227575abbcSIngo Weinhold			return B_BAD_DATA;
8237575abbcSIngo Weinhold		}
8247575abbcSIngo Weinhold	}
8257575abbcSIngo Weinhold
8267575abbcSIngo Weinhold	if (_hasChildren != NULL)
8277575abbcSIngo Weinhold		*_hasChildren = attribute_tag_has_children(tag);
8287575abbcSIngo Weinhold	if (_tag != NULL)
8297575abbcSIngo Weinhold		*_tag = tag;
8307575abbcSIngo Weinhold
8317575abbcSIngo Weinhold	return B_OK;
8327575abbcSIngo Weinhold}
8337575abbcSIngo Weinhold
8347575abbcSIngo Weinhold
8357575abbcSIngo Weinholdstatus_t
8367575abbcSIngo WeinholdReaderImplBase::ReadAttributeValue(uint8 type, uint8 encoding,
8377575abbcSIngo Weinhold	AttributeValue& _value)
8387575abbcSIngo Weinhold{
8397575abbcSIngo Weinhold	switch (type) {
8407575abbcSIngo Weinhold		case B_HPKG_ATTRIBUTE_TYPE_INT:
8417575abbcSIngo Weinhold		case B_HPKG_ATTRIBUTE_TYPE_UINT:
8427575abbcSIngo Weinhold		{
8437575abbcSIngo Weinhold			uint64 intValue;
8447575abbcSIngo Weinhold			status_t error;
8457575abbcSIngo Weinhold
8467575abbcSIngo Weinhold			switch (encoding) {
8477575abbcSIngo Weinhold				case B_HPKG_ATTRIBUTE_ENCODING_INT_8_BIT:
8487575abbcSIngo Weinhold				{
8497575abbcSIngo Weinhold					uint8 value;
8507575abbcSIngo Weinhold					error = _Read(value);
8517575abbcSIngo Weinhold					intValue = value;
8527575abbcSIngo Weinhold					break;
8537575abbcSIngo Weinhold				}
8547575abbcSIngo Weinhold				case B_HPKG_ATTRIBUTE_ENCODING_INT_16_BIT:
8557575abbcSIngo Weinhold				{
8567575abbcSIngo Weinhold					uint16 value;
8577575abbcSIngo Weinhold					error = _Read(value);
8587575abbcSIngo Weinhold					intValue = B_BENDIAN_TO_HOST_INT16(value);
8597575abbcSIngo Weinhold					break;
8607575abbc