1ad6a8dbeSOliver Tappe/*
232832cbeSIngo Weinhold * Copyright 2009-2014, Ingo Weinhold, ingo_weinhold@gmx.de.
3ad6a8dbeSOliver Tappe * Copyright 2011, Oliver Tappe <zooey@hirschkaefer.de>
4ad6a8dbeSOliver Tappe * Distributed under the terms of the MIT License.
5ad6a8dbeSOliver Tappe */
6ad6a8dbeSOliver Tappe
7ad6a8dbeSOliver Tappe
8ad6a8dbeSOliver Tappe#include <package/hpkg/ReaderImplBase.h>
9ad6a8dbeSOliver Tappe
10ad6a8dbeSOliver Tappe#include <errno.h>
11ad6a8dbeSOliver Tappe#include <stdio.h>
12ad6a8dbeSOliver Tappe#include <stdlib.h>
13ad6a8dbeSOliver Tappe#include <string.h>
146a89a36aSIngo Weinhold#include <unistd.h>
15ad6a8dbeSOliver Tappe
16ad6a8dbeSOliver Tappe#include <algorithm>
17ad6a8dbeSOliver Tappe#include <new>
18ad6a8dbeSOliver Tappe
19ad6a8dbeSOliver Tappe#include <ByteOrder.h>
2032832cbeSIngo Weinhold#include <DataIO.h>
21ad6a8dbeSOliver Tappe
22b3263ad3SIngo Weinhold#include <ZlibCompressionAlgorithm.h>
2381375d4fSJérôme Duval#ifdef ZSTD_ENABLED
2481375d4fSJérôme Duval#include <ZstdCompressionAlgorithm.h>
2581375d4fSJérôme Duval#endif
26ad6a8dbeSOliver Tappe
27b3263ad3SIngo Weinhold#include <package/hpkg/HPKGDefsPrivate.h>
281f633814SIngo Weinhold#include <package/hpkg/PackageFileHeapReader.h>
29ad6a8dbeSOliver Tappe
30ad6a8dbeSOliver Tappe
31ad6a8dbeSOliver Tappenamespace BPackageKit {
32ad6a8dbeSOliver Tappe
33ad6a8dbeSOliver Tappenamespace BHPKG {
34ad6a8dbeSOliver Tappe
35ad6a8dbeSOliver Tappenamespace BPrivate {
36ad6a8dbeSOliver Tappe
37ad6a8dbeSOliver Tappe
3879d5ddb7SIngo Weinholdstatic const uint16 kAttributeTypes[B_HPKG_ATTRIBUTE_ID_ENUM_COUNT] = {
3979d5ddb7SIngo Weinhold	#define B_DEFINE_HPKG_ATTRIBUTE(id, type, name, constant)	\
4079d5ddb7SIngo Weinhold		B_HPKG_ATTRIBUTE_TYPE_##type,
4179d5ddb7SIngo Weinhold	#include <package/hpkg/PackageAttributes.h>
4279d5ddb7SIngo Weinhold	#undef B_DEFINE_HPKG_ATTRIBUTE
4379d5ddb7SIngo Weinhold};
44ad6a8dbeSOliver Tappe
45ad6a8dbeSOliver Tappe// #pragma mark - AttributeHandlerContext
46ad6a8dbeSOliver Tappe
47ad6a8dbeSOliver Tappe
48ad6a8dbeSOliver TappeReaderImplBase::AttributeHandlerContext::AttributeHandlerContext(
4997aabbedSIngo Weinhold	BErrorOutput* errorOutput, BPackageContentHandler* packageContentHandler,
5047039b85SIngo Weinhold	BHPKGPackageSectionID section, bool ignoreUnknownAttributes)
51ad6a8dbeSOliver Tappe	:
52ad6a8dbeSOliver Tappe	errorOutput(errorOutput),
53ad6a8dbeSOliver Tappe	packageContentHandler(packageContentHandler),
5497aabbedSIngo Weinhold	hasLowLevelHandler(false),
5547039b85SIngo Weinhold	ignoreUnknownAttributes(ignoreUnknownAttributes),
5697aabbedSIngo Weinhold	section(section)
57ad6a8dbeSOliver Tappe{
58ad6a8dbeSOliver Tappe}
59ad6a8dbeSOliver Tappe
60ad6a8dbeSOliver Tappe
61ad6a8dbeSOliver TappeReaderImplBase::AttributeHandlerContext::AttributeHandlerContext(
6297aabbedSIngo Weinhold	BErrorOutput* errorOutput, BLowLevelPackageContentHandler* lowLevelHandler,
6347039b85SIngo Weinhold	BHPKGPackageSectionID section, bool ignoreUnknownAttributes)
64ad6a8dbeSOliver Tappe	:
65ad6a8dbeSOliver Tappe	errorOutput(errorOutput),
66ad6a8dbeSOliver Tappe	lowLevelHandler(lowLevelHandler),
6797aabbedSIngo Weinhold	hasLowLevelHandler(true),
6847039b85SIngo Weinhold	ignoreUnknownAttributes(ignoreUnknownAttributes),
6997aabbedSIngo Weinhold	section(section)
70ad6a8dbeSOliver Tappe{
71ad6a8dbeSOliver Tappe}
72ad6a8dbeSOliver Tappe
73ad6a8dbeSOliver Tappe
74ad6a8dbeSOliver Tappevoid
75ad6a8dbeSOliver TappeReaderImplBase::AttributeHandlerContext::ErrorOccurred()
76ad6a8dbeSOliver Tappe{
77ad6a8dbeSOliver Tappe	if (hasLowLevelHandler)
78ad6a8dbeSOliver Tappe		lowLevelHandler->HandleErrorOccurred();
79ad6a8dbeSOliver Tappe	else
80ad6a8dbeSOliver Tappe		packageContentHandler->HandleErrorOccurred();
81ad6a8dbeSOliver Tappe}
82ad6a8dbeSOliver Tappe
83ad6a8dbeSOliver Tappe
84ad6a8dbeSOliver Tappe// #pragma mark - AttributeHandler
85ad6a8dbeSOliver Tappe
86ad6a8dbeSOliver Tappe
87ad6a8dbeSOliver TappeReaderImplBase::AttributeHandler::~AttributeHandler()
88ad6a8dbeSOliver Tappe{
89ad6a8dbeSOliver Tappe}
90ad6a8dbeSOliver Tappe
91ad6a8dbeSOliver Tappe
92ad6a8dbeSOliver Tappevoid
93ad6a8dbeSOliver TappeReaderImplBase::AttributeHandler::SetLevel(int level)
94ad6a8dbeSOliver Tappe{
95ad6a8dbeSOliver Tappe	fLevel = level;
96ad6a8dbeSOliver Tappe}
97ad6a8dbeSOliver Tappe
98ad6a8dbeSOliver Tappe
99ad6a8dbeSOliver Tappestatus_t
100ad6a8dbeSOliver TappeReaderImplBase::AttributeHandler::HandleAttribute(
101ad6a8dbeSOliver Tappe	AttributeHandlerContext* context, uint8 id, const AttributeValue& value,
102ad6a8dbeSOliver Tappe	AttributeHandler** _handler)
103ad6a8dbeSOliver Tappe{
104ad6a8dbeSOliver Tappe	return B_OK;
105ad6a8dbeSOliver Tappe}
106ad6a8dbeSOliver Tappe
107ad6a8dbeSOliver Tappe
1080a345af7SOliver Tappestatus_t
1090a345af7SOliver TappeReaderImplBase::AttributeHandler::NotifyDone(
1100a345af7SOliver Tappe	AttributeHandlerContext* context)
1110a345af7SOliver Tappe{
1120a345af7SOliver Tappe	return B_OK;
1130a345af7SOliver Tappe}
1140a345af7SOliver Tappe
1150a345af7SOliver Tappe
116ad6a8dbeSOliver Tappestatus_t
117ad6a8dbeSOliver TappeReaderImplBase::AttributeHandler::Delete(AttributeHandlerContext* context)
118ad6a8dbeSOliver Tappe{
119ad6a8dbeSOliver Tappe	delete this;
120ad6a8dbeSOliver Tappe	return B_OK;
121ad6a8dbeSOliver Tappe}
122ad6a8dbeSOliver Tappe
123ad6a8dbeSOliver Tappe
124fe707a23SIngo Weinhold// #pragma mark - PackageInfoAttributeHandlerBase
125fe707a23SIngo Weinhold
126fe707a23SIngo Weinhold
127fe707a23SIngo WeinholdReaderImplBase::PackageInfoAttributeHandlerBase
128fe707a23SIngo Weinhold	::PackageInfoAttributeHandlerBase(
129fe707a23SIngo Weinhold		BPackageInfoAttributeValue& packageInfoValue)
130fe707a23SIngo Weinhold	:
131fe707a23SIngo Weinhold	fPackageInfoValue(packageInfoValue)
132fe707a23SIngo Weinhold{
133fe707a23SIngo Weinhold}
134fe707a23SIngo Weinhold
135fe707a23SIngo Weinhold
136fe707a23SIngo Weinholdstatus_t
1370a345af7SOliver TappeReaderImplBase::PackageInfoAttributeHandlerBase::NotifyDone(
138fe707a23SIngo Weinhold	AttributeHandlerContext* context)
139fe707a23SIngo Weinhold{
140fe707a23SIngo Weinhold	status_t error = context->packageContentHandler->HandlePackageAttribute(
141fe707a23SIngo Weinhold		fPackageInfoValue);
14231d70c10SAlexander G. M. Smith	if (context->ignoreUnknownAttributes && error == B_NOT_SUPPORTED)
14331d70c10SAlexander G. M. Smith		error = B_OK; // Safe to skip a future/unknown attribute.
144fe707a23SIngo Weinhold	fPackageInfoValue.Clear();
145fe707a23SIngo Weinhold	return error;
146fe707a23SIngo Weinhold}
147fe707a23SIngo Weinhold
148fe707a23SIngo Weinhold
149ad6a8dbeSOliver Tappe// #pragma mark - PackageVersionAttributeHandler
150ad6a8dbeSOliver Tappe
151ad6a8dbeSOliver Tappe
152ad6a8dbeSOliver TappeReaderImplBase::PackageVersionAttributeHandler::PackageVersionAttributeHandler(
153ad6a8dbeSOliver Tappe	BPackageInfoAttributeValue& packageInfoValue,
154ad6a8dbeSOliver Tappe	BPackageVersionData& versionData, bool notify)
155ad6a8dbeSOliver Tappe	:
1560a345af7SOliver Tappe	super(packageInfoValue),
157ad6a8dbeSOliver Tappe	fPackageVersionData(versionData),
158ad6a8dbeSOliver Tappe	fNotify(notify)
159ad6a8dbeSOliver Tappe{
160ad6a8dbeSOliver Tappe}
161ad6a8dbeSOliver Tappe
162ad6a8dbeSOliver Tappe
163ad6a8dbeSOliver Tappestatus_t
164ad6a8dbeSOliver TappeReaderImplBase::PackageVersionAttributeHandler::HandleAttribute(
165ad6a8dbeSOliver Tappe	AttributeHandlerContext* context, uint8 id, const AttributeValue& value,
166ad6a8dbeSOliver Tappe	AttributeHandler** _handler)
167ad6a8dbeSOliver Tappe{
168ad6a8dbeSOliver Tappe	switch (id) {
169ad6a8dbeSOliver Tappe		case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_MINOR:
170ad6a8dbeSOliver Tappe			fPackageVersionData.minor = value.string;
171ad6a8dbeSOliver Tappe			break;
172ad6a8dbeSOliver Tappe
173ad6a8dbeSOliver Tappe		case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_MICRO:
174ad6a8dbeSOliver Tappe			fPackageVersionData.micro = value.string;
175ad6a8dbeSOliver Tappe			break;
176ad6a8dbeSOliver Tappe
177ed6d59a9SIngo Weinhold		case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_PRE_RELEASE:
178ed6d59a9SIngo Weinhold			fPackageVersionData.preRelease = value.string;
179ed6d59a9SIngo Weinhold			break;
180ed6d59a9SIngo Weinhold
181202c1daaSIngo Weinhold		case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_REVISION:
182202c1daaSIngo Weinhold			fPackageVersionData.revision = value.unsignedInt;
183ad6a8dbeSOliver Tappe			break;
184ad6a8dbeSOliver Tappe
185ad6a8dbeSOliver Tappe		default:
18647039b85SIngo Weinhold			if (context->ignoreUnknownAttributes)
18747039b85SIngo Weinhold				break;
18847039b85SIngo Weinhold
189ad6a8dbeSOliver Tappe			context->errorOutput->PrintError("Error: Invalid package "
190ad6a8dbeSOliver Tappe				"attribute section: unexpected package attribute id %d "
191ad6a8dbeSOliver Tappe				"encountered when parsing package version\n", id);
192ad6a8dbeSOliver Tappe			return B_BAD_DATA;
193ad6a8dbeSOliver Tappe	}
194ad6a8dbeSOliver Tappe
195ad6a8dbeSOliver Tappe	return B_OK;
196ad6a8dbeSOliver Tappe}
197ad6a8dbeSOliver Tappe
198ad6a8dbeSOliver Tappe
199ad6a8dbeSOliver Tappestatus_t
2000a345af7SOliver TappeReaderImplBase::PackageVersionAttributeHandler::NotifyDone(
201ad6a8dbeSOliver Tappe	AttributeHandlerContext* context)
202ad6a8dbeSOliver Tappe{
2030a345af7SOliver Tappe	if (!fNotify)
2040a345af7SOliver Tappe		return B_OK;
205ad6a8dbeSOliver Tappe
2060a345af7SOliver Tappe	fPackageInfoValue.attributeID = B_PACKAGE_INFO_VERSION;
2070a345af7SOliver Tappe	return super::NotifyDone(context);
208ad6a8dbeSOliver Tappe}
209ad6a8dbeSOliver Tappe
210ad6a8dbeSOliver Tappe
211ad6a8dbeSOliver Tappe// #pragma mark - PackageResolvableAttributeHandler
212ad6a8dbeSOliver Tappe
213ad6a8dbeSOliver Tappe
214ad6a8dbeSOliver TappeReaderImplBase::PackageResolvableAttributeHandler
215ad6a8dbeSOliver Tappe	::PackageResolvableAttributeHandler(
216ad6a8dbeSOliver Tappe		BPackageInfoAttributeValue& packageInfoValue)
217ad6a8dbeSOliver Tappe	:
2180a345af7SOliver Tappe	super(packageInfoValue)
219ad6a8dbeSOliver Tappe{
220ad6a8dbeSOliver Tappe}
221ad6a8dbeSOliver Tappe
222ad6a8dbeSOliver Tappe
223ad6a8dbeSOliver Tappestatus_t
224ad6a8dbeSOliver TappeReaderImplBase::PackageResolvableAttributeHandler::HandleAttribute(
225ad6a8dbeSOliver Tappe	AttributeHandlerContext* context, uint8 id, const AttributeValue& value,
226ad6a8dbeSOliver Tappe	AttributeHandler** _handler)
227ad6a8dbeSOliver Tappe{
228ad6a8dbeSOliver Tappe	switch (id) {
229ad6a8dbeSOliver Tappe		case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_MAJOR:
230ad6a8dbeSOliver Tappe			fPackageInfoValue.resolvable.haveVersion = true;
231ad6a8dbeSOliver Tappe			fPackageInfoValue.resolvable.version.major = value.string;
232ad6a8dbeSOliver Tappe			if (_handler != NULL) {
233ad6a8dbeSOliver Tappe				*_handler
234ad6a8dbeSOliver Tappe					= new(std::nothrow) PackageVersionAttributeHandler(
235ad6a8dbeSOliver Tappe						fPackageInfoValue,
236ad6a8dbeSOliver Tappe						fPackageInfoValue.resolvable.version, false);
237ad6a8dbeSOliver Tappe				if (*_handler == NULL)
238ad6a8dbeSOliver Tappe					return B_NO_MEMORY;
239ad6a8dbeSOliver Tappe			}
240ad6a8dbeSOliver Tappe			break;
241ad6a8dbeSOliver Tappe
242ee9c9351SIngo Weinhold		case B_HPKG_ATTRIBUTE_ID_PACKAGE_PROVIDES_COMPATIBLE:
243ee9c9351SIngo Weinhold			fPackageInfoValue.resolvable.haveCompatibleVersion = true;
244ee9c9351SIngo Weinhold			fPackageInfoValue.resolvable.compatibleVersion.major = value.string;
245ee9c9351SIngo Weinhold			if (_handler != NULL) {
246ee9c9351SIngo Weinhold				*_handler
247ee9c9351SIngo Weinhold					= new(std::nothrow) PackageVersionAttributeHandler(
248ee9c9351SIngo Weinhold						fPackageInfoValue,
249ee9c9351SIngo Weinhold						fPackageInfoValue.resolvable.compatibleVersion, false);
250ee9c9351SIngo Weinhold				if (*_handler == NULL)
251ee9c9351SIngo Weinhold					return B_NO_MEMORY;
252ee9c9351SIngo Weinhold			}
253ee9c9351SIngo Weinhold			break;
254ee9c9351SIngo Weinhold
255ad6a8dbeSOliver Tappe		default:
25647039b85SIngo Weinhold			if (context->ignoreUnknownAttributes)
25747039b85SIngo Weinhold				break;
25847039b85SIngo Weinhold
259ad6a8dbeSOliver Tappe			context->errorOutput->PrintError("Error: Invalid package "
260ad6a8dbeSOliver Tappe				"attribute section: unexpected package attribute id %d "
261ad6a8dbeSOliver Tappe				"encountered when parsing package resolvable\n", id);
262ad6a8dbeSOliver Tappe			return B_BAD_DATA;
263ad6a8dbeSOliver Tappe	}
264ad6a8dbeSOliver Tappe
265ad6a8dbeSOliver Tappe	return B_OK;
266ad6a8dbeSOliver Tappe}
267ad6a8dbeSOliver Tappe
268ad6a8dbeSOliver Tappe
269ad6a8dbeSOliver Tappe// #pragma mark - PackageResolvableExpressionAttributeHandler
270ad6a8dbeSOliver Tappe
271ad6a8dbeSOliver Tappe
272ad6a8dbeSOliver TappeReaderImplBase::PackageResolvableExpressionAttributeHandler
273ad6a8dbeSOliver Tappe	::PackageResolvableExpressionAttributeHandler(
274ad6a8dbeSOliver Tappe		BPackageInfoAttributeValue& packageInfoValue)
275ad6a8dbeSOliver Tappe	:
2760a345af7SOliver Tappe	super(packageInfoValue)
277ad6a8dbeSOliver Tappe{
278ad6a8dbeSOliver Tappe}
279ad6a8dbeSOliver Tappe
280ad6a8dbeSOliver Tappe
281ad6a8dbeSOliver Tappestatus_t
282ad6a8dbeSOliver TappeReaderImplBase::PackageResolvableExpressionAttributeHandler::HandleAttribute(
283ad6a8dbeSOliver Tappe	AttributeHandlerContext* context, uint8 id, const AttributeValue& value,
284ad6a8dbeSOliver Tappe	AttributeHandler** _handler)
285ad6a8dbeSOliver Tappe{
286ad6a8dbeSOliver Tappe	switch (id) {
287ad6a8dbeSOliver Tappe		case B_HPKG_ATTRIBUTE_ID_PACKAGE_RESOLVABLE_OPERATOR:
288ad6a8dbeSOliver Tappe			if (value.unsignedInt >= B_PACKAGE_RESOLVABLE_OP_ENUM_COUNT) {
289ad6a8dbeSOliver Tappe				context->errorOutput->PrintError(
290ad6a8dbeSOliver Tappe					"Error: Invalid package attribute section: invalid "
291ad6a8dbeSOliver Tappe					"package resolvable operator %lld encountered\n",
292ad6a8dbeSOliver Tappe					value.unsignedInt);
293ad6a8dbeSOliver Tappe				return B_BAD_DATA;
294ad6a8dbeSOliver Tappe			}
295ad6a8dbeSOliver Tappe			fPackageInfoValue.resolvableExpression.op
296ad6a8dbeSOliver Tappe				= (BPackageResolvableOperator)value.unsignedInt;
297ad6a8dbeSOliver Tappe			break;
298ad6a8dbeSOliver Tappe
299ad6a8dbeSOliver Tappe		case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_MAJOR:
300ad6a8dbeSOliver Tappe			fPackageInfoValue.resolvableExpression.haveOpAndVersion = true;
301ad6a8dbeSOliver Tappe			fPackageInfoValue.resolvableExpression.version.major
302ad6a8dbeSOliver Tappe				= value.string;
303ad6a8dbeSOliver Tappe			if (_handler != NULL) {
304ad6a8dbeSOliver Tappe				*_handler
305ad6a8dbeSOliver Tappe					= new(std::nothrow) PackageVersionAttributeHandler(
306ad6a8dbeSOliver Tappe						fPackageInfoValue,
307ad6a8dbeSOliver Tappe						fPackageInfoValue.resolvableExpression.version,
308ad6a8dbeSOliver Tappe						false);
309ad6a8dbeSOliver Tappe				if (*_handler == NULL)
310ad6a8dbeSOliver Tappe					return B_NO_MEMORY;
311ad6a8dbeSOliver Tappe			}
312ad6a8dbeSOliver Tappe			return B_OK;
313ad6a8dbeSOliver Tappe
314ad6a8dbeSOliver Tappe		default:
31547039b85SIngo Weinhold			if (context->ignoreUnknownAttributes)
31647039b85SIngo Weinhold				break;
31747039b85SIngo Weinhold
318ad6a8dbeSOliver Tappe			context->errorOutput->PrintError("Error: Invalid package "
319ad6a8dbeSOliver Tappe				"attribute section: unexpected package attribute id %d "
320ad6a8dbeSOliver Tappe				"encountered when parsing package resolvable-expression\n",
321ad6a8dbeSOliver Tappe				id);
322ad6a8dbeSOliver Tappe			return B_BAD_DATA;
323ad6a8dbeSOliver Tappe	}
324ad6a8dbeSOliver Tappe
325ad6a8dbeSOliver Tappe	return B_OK;
326ad6a8dbeSOliver Tappe}
327ad6a8dbeSOliver Tappe
328ad6a8dbeSOliver Tappe
3294489c88bSIngo Weinhold// #pragma mark - GlobalWritableFileInfoAttributeHandler
330fe707a23SIngo Weinhold
331fe707a23SIngo Weinhold
3324489c88bSIngo WeinholdReaderImplBase::GlobalWritableFileInfoAttributeHandler
3334489c88bSIngo Weinhold	::GlobalWritableFileInfoAttributeHandler(
334fe707a23SIngo Weinhold		BPackageInfoAttributeValue& packageInfoValue)
335fe707a23SIngo Weinhold	:
3360a345af7SOliver Tappe	super(packageInfoValue)
337fe707a23SIngo Weinhold{
338fe707a23SIngo Weinhold}
339fe707a23SIngo Weinhold
340fe707a23SIngo Weinhold
341ad6a8dbeSOliver Tappestatus_t
3424489c88bSIngo WeinholdReaderImplBase::GlobalWritableFileInfoAttributeHandler::HandleAttribute(
343fe707a23SIngo Weinhold	AttributeHandlerContext* context, uint8 id, const AttributeValue& value,
344fe707a23SIngo Weinhold	AttributeHandler** _handler)
345ad6a8dbeSOliver Tappe{
346fe707a23SIngo Weinhold	switch (id) {
3474489c88bSIngo Weinhold		case B_HPKG_ATTRIBUTE_ID_PACKAGE_WRITABLE_FILE_UPDATE_TYPE:
3484489c88bSIngo Weinhold			if (value.unsignedInt >= B_WRITABLE_FILE_UPDATE_TYPE_ENUM_COUNT) {
349fe707a23SIngo Weinhold				context->errorOutput->PrintError(
350fe707a23SIngo Weinhold					"Error: Invalid package attribute section: invalid "
351fe707a23SIngo Weinhold					"global settings file update type %" B_PRIu64
352fe707a23SIngo Weinhold					" encountered\n", value.unsignedInt);
353fe707a23SIngo Weinhold				return B_BAD_DATA;
354fe707a23SIngo Weinhold			}
3554489c88bSIngo Weinhold			fPackageInfoValue.globalWritableFileInfo.updateType
3564489c88bSIngo Weinhold				= (BWritableFileUpdateType)value.unsignedInt;
357fe707a23SIngo Weinhold			break;
358ad6a8dbeSOliver Tappe
359a266b57aSIngo Weinhold		case B_HPKG_ATTRIBUTE_ID_PACKAGE_IS_WRITABLE_DIRECTORY:
360a266b57aSIngo Weinhold			fPackageInfoValue.globalWritableFileInfo.isDirectory
361a266b57aSIngo Weinhold				= value.unsignedInt != 0;
362a266b57aSIngo Weinhold			break;
363a266b57aSIngo Weinhold
364fe707a23SIngo Weinhold		default:
365fe707a23SIngo Weinhold			if (context->ignoreUnknownAttributes)
366fe707a23SIngo Weinhold				break;
367fe707a23SIngo Weinhold
368fe707a23SIngo Weinhold			context->errorOutput->PrintError("Error: Invalid package "
369fe707a23SIngo Weinhold				"attribute section: unexpected package attribute id %d "
370fe707a23SIngo Weinhold				"encountered when parsing global settings file info\n",
371fe707a23SIngo Weinhold				id);
372fe707a23SIngo Weinhold			return B_BAD_DATA;
373fe707a23SIngo Weinhold	}
374fe707a23SIngo Weinhold
375fe707a23SIngo Weinhold	return B_OK;
376fe707a23SIngo Weinhold}
377fe707a23SIngo Weinhold
378fe707a23SIngo Weinhold
379fe707a23SIngo Weinhold// #pragma mark - UserSettingsFileInfoAttributeHandler
380fe707a23SIngo Weinhold
381fe707a23SIngo Weinhold
382fe707a23SIngo WeinholdReaderImplBase::UserSettingsFileInfoAttributeHandler
383fe707a23SIngo Weinhold	::UserSettingsFileInfoAttributeHandler(
384fe707a23SIngo Weinhold		BPackageInfoAttributeValue& packageInfoValue)
385fe707a23SIngo Weinhold	:
3860a345af7SOliver Tappe	super(packageInfoValue)
387fe707a23SIngo Weinhold{
388ad6a8dbeSOliver Tappe}
389ad6a8dbeSOliver Tappe
390ad6a8dbeSOliver Tappe
391fe707a23SIngo Weinholdstatus_t
392fe707a23SIngo WeinholdReaderImplBase::UserSettingsFileInfoAttributeHandler::HandleAttribute(
393fe707a23SIngo Weinhold	AttributeHandlerContext* context, uint8 id, const AttributeValue& value,
394fe707a23SIngo Weinhold	AttributeHandler** _handler)
395fe707a23SIngo Weinhold{
396fe707a23SIngo Weinhold	switch (id) {
397fe707a23SIngo Weinhold		case B_HPKG_ATTRIBUTE_ID_PACKAGE_SETTINGS_FILE_TEMPLATE:
398fe707a23SIngo Weinhold			fPackageInfoValue.userSettingsFileInfo.templatePath = value.string;
399fe707a23SIngo Weinhold			break;
400fe707a23SIngo Weinhold
401a266b57aSIngo Weinhold		case B_HPKG_ATTRIBUTE_ID_PACKAGE_IS_WRITABLE_DIRECTORY:
402a266b57aSIngo Weinhold			fPackageInfoValue.userSettingsFileInfo.isDirectory
403a266b57aSIngo Weinhold				= value.unsignedInt != 0;
404a266b57aSIngo Weinhold			break;
405a266b57aSIngo Weinhold
406fe707a23SIngo Weinhold		default:
407fe707a23SIngo Weinhold			if (context->ignoreUnknownAttributes)
408fe707a23SIngo Weinhold				break;
409fe707a23SIngo Weinhold
410fe707a23SIngo Weinhold			context->errorOutput->PrintError("Error: Invalid package "
411fe707a23SIngo Weinhold				"attribute section: unexpected package attribute id %d "
412fe707a23SIngo Weinhold				"encountered when parsing user settings file info\n",
413fe707a23SIngo Weinhold				id);
414fe707a23SIngo Weinhold			return B_BAD_DATA;
415fe707a23SIngo Weinhold	}
416fe707a23SIngo Weinhold
417fe707a23SIngo Weinhold	return B_OK;
418fe707a23SIngo Weinhold}
419fe707a23SIngo Weinhold
4200f4e11e7SIngo Weinhold
4210f4e11e7SIngo Weinhold// #pragma mark - UserAttributeHandler
4220f4e11e7SIngo Weinhold
4230f4e11e7SIngo Weinhold
4240f4e11e7SIngo WeinholdReaderImplBase::UserAttributeHandler::UserAttributeHandler(
4250f4e11e7SIngo Weinhold		BPackageInfoAttributeValue& packageInfoValue)
4260f4e11e7SIngo Weinhold	:
4270a345af7SOliver Tappe	super(packageInfoValue),
4280f4e11e7SIngo Weinhold	fGroups()
4290f4e11e7SIngo Weinhold{
4300f4e11e7SIngo Weinhold}
4310f4e11e7SIngo Weinhold
4320f4e11e7SIngo Weinhold
4330f4e11e7SIngo Weinholdstatus_t
4340f4e11e7SIngo WeinholdReaderImplBase::UserAttributeHandler::HandleAttribute(
4350f4e11e7SIngo Weinhold	AttributeHandlerContext* context, uint8 id, const AttributeValue& value,
4360f4e11e7SIngo Weinhold	AttributeHandler** _handler)
4370f4e11e7SIngo Weinhold{
4380f4e11e7SIngo Weinhold	switch (id) {
4390f4e11e7SIngo Weinhold		case B_HPKG_ATTRIBUTE_ID_PACKAGE_USER_REAL_NAME:
4400f4e11e7SIngo Weinhold			fPackageInfoValue.user.realName = value.string;
4410f4e11e7SIngo Weinhold			break;
4420f4e11e7SIngo Weinhold
4430f4e11e7SIngo Weinhold		case B_HPKG_ATTRIBUTE_ID_PACKAGE_USER_HOME:
4440f4e11e7SIngo Weinhold			fPackageInfoValue.user.home = value.string;
4450f4e11e7SIngo Weinhold			break;
4460f4e11e7SIngo Weinhold
4470f4e11e7SIngo Weinhold		case B_HPKG_ATTRIBUTE_ID_PACKAGE_USER_SHELL:
4480f4e11e7SIngo Weinhold			fPackageInfoValue.user.shell = value.string;
4490f4e11e7SIngo Weinhold			break;
4500f4e11e7SIngo Weinhold
4510f4e11e7SIngo Weinhold		case B_HPKG_ATTRIBUTE_ID_PACKAGE_USER_GROUP:
4520f4e11e7SIngo Weinhold			if (!fGroups.Add(value.string))
4530f4e11e7SIngo Weinhold				return B_NO_MEMORY;
4540f4e11e7SIngo Weinhold			break;
4550f4e11e7SIngo Weinhold
4560f4e11e7SIngo Weinhold		default:
4570f4e11e7SIngo Weinhold			if (context->ignoreUnknownAttributes)
4580f4e11e7SIngo Weinhold				break;
4590f4e11e7SIngo Weinhold
4600f4e11e7SIngo Weinhold			context->errorOutput->PrintError("Error: Invalid package "
4610f4e11e7SIngo Weinhold				"attribute section: unexpected package attribute id %d "
4620f4e11e7SIngo Weinhold				"encountered when parsing user settings file info\n",
4630f4e11e7SIngo Weinhold				id);
4640f4e11e7SIngo Weinhold			return B_BAD_DATA;
4650f4e11e7SIngo Weinhold	}
4660f4e11e7SIngo Weinhold
4670f4e11e7SIngo Weinhold	return B_OK;
4680f4e11e7SIngo Weinhold}
4690f4e11e7SIngo Weinhold
4700f4e11e7SIngo Weinhold
4710f4e11e7SIngo Weinholdstatus_t
4720a345af7SOliver TappeReaderImplBase::UserAttributeHandler::NotifyDone(
4730a345af7SOliver Tappe	AttributeHandlerContext* context)
4740f4e11e7SIngo Weinhold{
4750f4e11e7SIngo Weinhold	if (!fGroups.IsEmpty()) {
4760f4e11e7SIngo Weinhold		fPackageInfoValue.user.groups = fGroups.Elements();
4770f4e11e7SIngo Weinhold		fPackageInfoValue.user.groupCount = fGroups.Count();
4780f4e11e7SIngo Weinhold	}
4790f4e11e7SIngo Weinhold
4800a345af7SOliver Tappe	return super::NotifyDone(context);
4810f4e11e7SIngo Weinhold}
4820f4e11e7SIngo Weinhold
4830f4e11e7SIngo Weinhold
484ad6a8dbeSOliver Tappe// #pragma mark - PackageAttributeHandler
485ad6a8dbeSOliver Tappe
486ad6a8dbeSOliver Tappe
487ad6a8dbeSOliver Tappestatus_t
488ad6a8dbeSOliver TappeReaderImplBase::PackageAttributeHandler::HandleAttribute(
489ad6a8dbeSOliver Tappe	AttributeHandlerContext* context, uint8 id, const AttributeValue& value,
490ad6a8dbeSOliver Tappe	AttributeHandler** _handler)
491ad6a8dbeSOliver Tappe{
492ad6a8dbeSOliver Tappe	switch (id) {
493ad6a8dbeSOliver Tappe		case B_HPKG_ATTRIBUTE_ID_PACKAGE_NAME:
494ad6a8dbeSOliver Tappe			fPackageInfoValue.SetTo(B_PACKAGE_INFO_NAME, value.string);
495ad6a8dbeSOliver Tappe			break;
496ad6a8dbeSOliver Tappe
497ad6a8dbeSOliver Tappe		case B_HPKG_ATTRIBUTE_ID_PACKAGE_SUMMARY:
498ad6a8dbeSOliver Tappe			fPackageInfoValue.SetTo(B_PACKAGE_INFO_SUMMARY, value.string);
499ad6a8dbeSOliver Tappe			break;
500ad6a8dbeSOliver Tappe
501ad6a8dbeSOliver Tappe		case B_HPKG_ATTRIBUTE_ID_PACKAGE_DESCRIPTION:
502ad6a8dbeSOliver Tappe			fPackageInfoValue.SetTo(B_PACKAGE_INFO_DESCRIPTION,
503ad6a8dbeSOliver Tappe				value.string);
504ad6a8dbeSOliver Tappe			break;
505ad6a8dbeSOliver Tappe
506ad6a8dbeSOliver Tappe		case B_HPKG_ATTRIBUTE_ID_PACKAGE_VENDOR:
507ad6a8dbeSOliver Tappe			fPackageInfoValue.SetTo(B_PACKAGE_INFO_VENDOR, value.string);
508ad6a8dbeSOliver Tappe			break;
509ad6a8dbeSOliver Tappe
510ad6a8dbeSOliver Tappe		case B_HPKG_ATTRIBUTE_ID_PACKAGE_PACKAGER:
511ad6a8dbeSOliver Tappe			fPackageInfoValue.SetTo(B_PACKAGE_INFO_PACKAGER, value.string);
512ad6a8dbeSOliver Tappe			break;
513ad6a8dbeSOliver Tappe
5147adfd76bSIngo Weinhold		case B_HPKG_ATTRIBUTE_ID_PACKAGE_BASE_PACKAGE:
5157adfd76bSIngo Weinhold			fPackageInfoValue.SetTo(B_PACKAGE_INFO_BASE_PACKAGE, value.string);
5167adfd76bSIngo Weinhold			break;
5177adfd76bSIngo Weinhold
518ad6a8dbeSOliver Tappe		case B_HPKG_ATTRIBUTE_ID_PACKAGE_FLAGS:
519ad6a8dbeSOliver Tappe			fPackageInfoValue.SetTo(B_PACKAGE_INFO_FLAGS,
520ad6a8dbeSOliver Tappe				(uint32)value.unsignedInt);
521ad6a8dbeSOliver Tappe			break;
522ad6a8dbeSOliver Tappe
523ad6a8dbeSOliver Tappe		case B_HPKG_ATTRIBUTE_ID_PACKAGE_ARCHITECTURE:
524ad6a8dbeSOliver Tappe			if (value.unsignedInt
525ad6a8dbeSOliver Tappe					>= B_PACKAGE_ARCHITECTURE_ENUM_COUNT) {
526ad6a8dbeSOliver Tappe				context->errorOutput->PrintError(
527ad6a8dbeSOliver Tappe					"Error: Invalid package attribute section: "
528ad6a8dbeSOliver Tappe					"Invalid package architecture %lld encountered\n",
529ad6a8dbeSOliver Tappe					value.unsignedInt);
530ad6a8dbeSOliver Tappe				return B_BAD_DATA;
531ad6a8dbeSOliver Tappe			}
532ad6a8dbeSOliver Tappe			fPackageInfoValue.SetTo(B_PACKAGE_INFO_ARCHITECTURE,
533ad6a8dbeSOliver Tappe				(uint8)value.unsignedInt);
534ad6a8dbeSOliver Tappe			break;
535ad6a8dbeSOliver Tappe
536ad6a8dbeSOliver Tappe		case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_MAJOR:
537ad6a8dbeSOliver Tappe			fPackageInfoValue.attributeID = B_PACKAGE_INFO_VERSION;
538ad6a8dbeSOliver Tappe			fPackageInfoValue.version.major = value.string;
539ad6a8dbeSOliver Tappe			if (_handler != NULL) {
540ad6a8dbeSOliver Tappe				*_handler
541ad6a8dbeSOliver Tappe					= new(std::nothrow) PackageVersionAttributeHandler(
542ad6a8dbeSOliver Tappe						fPackageInfoValue, fPackageInfoValue.version, true);
543ad6a8dbeSOliver Tappe				if (*_handler == NULL)
544ad6a8dbeSOliver Tappe					return B_NO_MEMORY;
545ad6a8dbeSOliver Tappe			}
546ad6a8dbeSOliver Tappe			break;
547ad6a8dbeSOliver Tappe
548ad6a8dbeSOliver Tappe		case B_HPKG_ATTRIBUTE_ID_PACKAGE_COPYRIGHT:
549ad6a8dbeSOliver Tappe			fPackageInfoValue.SetTo(B_PACKAGE_INFO_COPYRIGHTS,
550ad6a8dbeSOliver Tappe				value.string);
551ad6a8dbeSOliver Tappe			break;
552ad6a8dbeSOliver Tappe
553ad6a8dbeSOliver Tappe		case B_HPKG_ATTRIBUTE_ID_PACKAGE_LICENSE:
554ad6a8dbeSOliver Tappe			fPackageInfoValue.SetTo(B_PACKAGE_INFO_LICENSES,
555ad6a8dbeSOliver Tappe				value.string);
556ad6a8dbeSOliver Tappe			break;
557ad6a8dbeSOliver Tappe
558116852feSIngo Weinhold		case B_HPKG_ATTRIBUTE_ID_PACKAGE_URL:
559116852feSIngo Weinhold			fPackageInfoValue.SetTo(B_PACKAGE_INFO_URLS, value.string);
560116852feSIngo Weinhold			break;
561116852feSIngo Weinhold
562116852feSIngo Weinhold		case B_HPKG_ATTRIBUTE_ID_PACKAGE_SOURCE_URL:
563116852feSIngo Weinhold			fPackageInfoValue.SetTo(B_PACKAGE_INFO_SOURCE_URLS, value.string);
564116852feSIngo Weinhold			break;
565116852feSIngo Weinhold
566ad6a8dbeSOliver Tappe		case B_HPKG_ATTRIBUTE_ID_PACKAGE_PROVIDES:
567ad6a8dbeSOliver Tappe			fPackageInfoValue.resolvable.name = value.string;
568ad6a8dbeSOliver Tappe			fPackageInfoValue.attributeID = B_PACKAGE_INFO_PROVIDES;
569ad6a8dbeSOliver Tappe			if (_handler != NULL) {
570ad6a8dbeSOliver Tappe				*_handler
571ad6a8dbeSOliver Tappe					= new(std::nothrow) PackageResolvableAttributeHandler(
572ad6a8dbeSOliver Tappe						fPackageInfoValue);
573ad6a8dbeSOliver Tappe				if (*_handler == NULL)
574ad6a8dbeSOliver Tappe					return B_NO_MEMORY;
575ad6a8dbeSOliver Tappe			}
576ad6a8dbeSOliver Tappe			break;
577ad6a8dbeSOliver Tappe
578ad6a8dbeSOliver Tappe		case B_HPKG_ATTRIBUTE_ID_PACKAGE_REQUIRES:
579ad6a8dbeSOliver Tappe		case B_HPKG_ATTRIBUTE_ID_PACKAGE_SUPPLEMENTS:
580ad6a8dbeSOliver Tappe		case B_HPKG_ATTRIBUTE_ID_PACKAGE_CONFLICTS:
581ad6a8dbeSOliver Tappe		case B_HPKG_ATTRIBUTE_ID_PACKAGE_FRESHENS:
582ad6a8dbeSOliver Tappe			fPackageInfoValue.resolvableExpression.name = value.string;
583ad6a8dbeSOliver Tappe			switch (id) {
584ad6a8dbeSOliver Tappe				case B_HPKG_ATTRIBUTE_ID_PACKAGE_REQUIRES:
585ad6a8dbeSOliver Tappe					fPackageInfoValue.attributeID = B_PACKAGE_INFO_REQUIRES;
586ad6a8dbeSOliver Tappe					break;
587ad6a8dbeSOliver Tappe
588ad6a8dbeSOliver Tappe				case B_HPKG_ATTRIBUTE_ID_PACKAGE_SUPPLEMENTS:
589ad6a8dbeSOliver Tappe					fPackageInfoValue.attributeID
590ad6a8dbeSOliver Tappe						= B_PACKAGE_INFO_SUPPLEMENTS;
591ad6a8dbeSOliver Tappe					break;
592ad6a8dbeSOliver Tappe
593ad6a8dbeSOliver Tappe				case B_HPKG_ATTRIBUTE_ID_PACKAGE_CONFLICTS:
594ad6a8dbeSOliver Tappe					fPackageInfoValue.attributeID
595ad6a8dbeSOliver Tappe						= B_PACKAGE_INFO_CONFLICTS;
596ad6a8dbeSOliver Tappe					break;
597ad6a8dbeSOliver Tappe
598ad6a8dbeSOliver Tappe				case B_HPKG_ATTRIBUTE_ID_PACKAGE_FRESHENS:
599ad6a8dbeSOliver Tappe					fPackageInfoValue.attributeID = B_PACKAGE_INFO_FRESHENS;
600ad6a8dbeSOliver Tappe					break;
601ad6a8dbeSOliver Tappe			}
602ad6a8dbeSOliver Tappe			if (_handler != NULL) {
603ad6a8dbeSOliver Tappe				*_handler = new(std::nothrow)
604ad6a8dbeSOliver Tappe					PackageResolvableExpressionAttributeHandler(
605ad6a8dbeSOliver Tappe						fPackageInfoValue);
606ad6a8dbeSOliver Tappe				if (*_handler == NULL)
607ad6a8dbeSOliver Tappe					return B_NO_MEMORY;
608ad6a8dbeSOliver Tappe			}
609ad6a8dbeSOliver Tappe			break;
610ad6a8dbeSOliver Tappe
611ad6a8dbeSOliver Tappe		case B_HPKG_ATTRIBUTE_ID_PACKAGE_REPLACES:
612ad6a8dbeSOliver Tappe			fPackageInfoValue.SetTo(B_PACKAGE_INFO_REPLACES, value.string);
613ad6a8dbeSOliver Tappe			break;
614ad6a8dbeSOliver Tappe
61534d56c1bSOliver Tappe		case B_HPKG_ATTRIBUTE_ID_PACKAGE_CHECKSUM:
61634d56c1bSOliver Tappe			fPackageInfoValue.SetTo(B_PACKAGE_INFO_CHECKSUM, value.string);
61734d56c1bSOliver Tappe			break;
61834d56c1bSOliver Tappe
619f19957b8SIngo Weinhold		case B_HPKG_ATTRIBUTE_ID_PACKAGE_INSTALL_PATH:
620f19957b8SIngo Weinhold			fPackageInfoValue.SetTo(B_PACKAGE_INFO_INSTALL_PATH, value.string);
621f19957b8SIngo Weinhold			break;
622f19957b8SIngo Weinhold
6234489c88bSIngo Weinhold		case B_HPKG_ATTRIBUTE_ID_PACKAGE_GLOBAL_WRITABLE_FILE:
6244489c88bSIngo Weinhold			fPackageInfoValue.globalWritableFileInfo.path = value.string;
6254489c88bSIngo Weinhold			fPackageInfoValue.globalWritableFileInfo.updateType
6264489c88bSIngo Weinhold				= B_WRITABLE_FILE_UPDATE_TYPE_ENUM_COUNT;
627fe707a23SIngo Weinhold			fPackageInfoValue.attributeID
6284489c88bSIngo Weinhold				= B_PACKAGE_INFO_GLOBAL_WRITABLE_FILES;
629fe707a23SIngo Weinhold			if (_handler != NULL) {
630fe707a23SIngo Weinhold				*_handler
6314489c88bSIngo Weinhold					= new(std::nothrow) GlobalWritableFileInfoAttributeHandler(
632fe707a23SIngo Weinhold						fPackageInfoValue);
633fe707a23SIngo Weinhold				if (*_handler == NULL)
634fe707a23SIngo Weinhold					return B_NO_MEMORY;
635fe707a23SIngo Weinhold			}
636fe707a23SIngo Weinhold			break;
637fe707a23SIngo Weinhold
638fe707a23SIngo Weinhold		case B_HPKG_ATTRIBUTE_ID_PACKAGE_USER_SETTINGS_FILE:
639bf88057bSIngo Weinhold			fPackageInfoValue.userSettingsFileInfo.path = value.string;
640fe707a23SIngo Weinhold			fPackageInfoValue.attributeID
641fe707a23SIngo Weinhold				= B_PACKAGE_INFO_USER_SETTINGS_FILES;
642fe707a23SIngo Weinhold			if (_handler != NULL) {
643fe707a23SIngo Weinhold				*_handler
644fe707a23SIngo Weinhold					= new(std::nothrow) UserSettingsFileInfoAttributeHandler(
645fe707a23SIngo Weinhold						fPackageInfoValue);
646fe707a23SIngo Weinhold				if (*_handler == NULL)
647fe707a23SIngo Weinhold					return B_NO_MEMORY;
648fe707a23SIngo Weinhold			}
649fe707a23SIngo Weinhold			break;
650fe707a23SIngo Weinhold
6510f4e11e7SIngo Weinhold		case B_HPKG_ATTRIBUTE_ID_PACKAGE_USER:
6520f4e11e7SIngo Weinhold			fPackageInfoValue.user.name = value.string;
6530f4e11e7SIngo Weinhold			fPackageInfoValue.attributeID = B_PACKAGE_INFO_USERS;
6540f4e11e7SIngo Weinhold			if (_handler != NULL) {
6550f4e11e7SIngo Weinhold				*_handler = new(std::nothrow) UserAttributeHandler(
6560f4e11e7SIngo Weinhold					fPackageInfoValue);
6570f4e11e7SIngo Weinhold				if (*_handler == NULL)
6580f4e11e7SIngo Weinhold					return B_NO_MEMORY;
6590f4e11e7SIngo Weinhold			}
6600f4e11e7SIngo Weinhold			break;
6610f4e11e7SIngo Weinhold
6620f4e11e7SIngo Weinhold		case B_HPKG_ATTRIBUTE_ID_PACKAGE_GROUP:
6630f4e11e7SIngo Weinhold			fPackageInfoValue.SetTo(B_PACKAGE_INFO_GROUPS, value.string);
6640f4e11e7SIngo Weinhold			break;
6650f4e11e7SIngo Weinhold
666c0ab1409SIngo Weinhold		case B_HPKG_ATTRIBUTE_ID_PACKAGE_POST_INSTALL_SCRIPT:
667c0ab1409SIngo Weinhold			fPackageInfoValue.SetTo(B_PACKAGE_INFO_POST_INSTALL_SCRIPTS,
668c0ab1409SIngo Weinhold				value.string);
669c0ab1409SIngo Weinhold			break;
670c0ab1409SIngo Weinhold
671ad6a8dbeSOliver Tappe		default:
67247039b85SIngo Weinhold			if (context->ignoreUnknownAttributes)
67347039b85SIngo Weinhold				break;
67447039b85SIngo Weinhold
675ad6a8dbeSOliver Tappe			context->errorOutput->PrintError(
676ad6a8dbeSOliver Tappe				"Error: Invalid package attribute section: unexpected "
677ad6a8dbeSOliver Tappe				"package attribute id %d encountered\n", id);
678ad6a8dbeSOliver Tappe			return B_BAD_DATA;
679ad6a8dbeSOliver Tappe	}
680ad6a8dbeSOliver Tappe
681ad6a8dbeSOliver Tappe	// notify unless the current attribute has children, in which case
682ad6a8dbeSOliver Tappe	// the child-handler will notify when it's done
683ad6a8dbeSOliver Tappe	if (_handler == NULL) {
684ad6a8dbeSOliver Tappe		status_t error = context->packageContentHandler
685ad6a8dbeSOliver Tappe			->HandlePackageAttribute(fPackageInfoValue);
68631d70c10SAlexander G. M. Smith		if (context->ignoreUnknownAttributes && error == B_NOT_SUPPORTED)
68731d70c10SAlexander G. M. Smith			error = B_OK; // Safe to skip a future/unknown attribute.
688ad6a8dbeSOliver Tappe		fPackageInfoValue.Clear();
689ad6a8dbeSOliver Tappe		if (error != B_OK)
690ad6a8dbeSOliver Tappe			return error;
691ad6a8dbeSOliver Tappe	}
692ad6a8dbeSOliver Tappe
693ad6a8dbeSOliver Tappe	return B_OK;
694ad6a8dbeSOliver Tappe}
695ad6a8dbeSOliver Tappe
696ad6a8dbeSOliver Tappe
697ad6a8dbeSOliver Tappe// #pragma mark - LowLevelAttributeHandler
698ad6a8dbeSOliver Tappe
699ad6a8dbeSOliver Tappe
700ad6a8dbeSOliver TappeReaderImplBase::LowLevelAttributeHandler::LowLevelAttributeHandler()
701ad6a8dbeSOliver Tappe	:
702697b9545SIngo Weinhold	fParentToken(NULL),
703ad6a8dbeSOliver Tappe	fToken(NULL),
704ad6a8dbeSOliver Tappe	fID(B_HPKG_ATTRIBUTE_ID_ENUM_COUNT)
705ad6a8dbeSOliver Tappe{
706ad6a8dbeSOliver Tappe}
707ad6a8dbeSOliver Tappe
708ad6a8dbeSOliver Tappe
709ad6a8dbeSOliver TappeReaderImplBase::LowLevelAttributeHandler::LowLevelAttributeHandler(uint8 id,
710697b9545SIngo Weinhold	const BPackageAttributeValue& value, void* parentToken, void* token)
711ad6a8dbeSOliver Tappe	:
712697b9545SIngo Weinhold	fParentToken(NULL),
713ad6a8dbeSOliver Tappe	fToken(token),
714ad6a8dbeSOliver Tappe	fID(id),
715ad6a8dbeSOliver Tappe	fValue(value)
716ad6a8dbeSOliver Tappe{
717ad6a8dbeSOliver Tappe}
718ad6a8dbeSOliver Tappe
719ad6a8dbeSOliver Tappe
720ad6a8dbeSOliver Tappestatus_t
721ad6a8dbeSOliver TappeReaderImplBase::LowLevelAttributeHandler::HandleAttribute(
722ad6a8dbeSOliver Tappe	AttributeHandlerContext* context, uint8 id, const AttributeValue& value,
723ad6a8dbeSOliver Tappe	AttributeHandler** _handler)
724ad6a8dbeSOliver Tappe{
725ad6a8dbeSOliver Tappe	// notify the content handler
726ad6a8dbeSOliver Tappe	void* token;
727ad6a8dbeSOliver Tappe	status_t error = context->lowLevelHandler->HandleAttribute(
728ad6a8dbeSOliver Tappe		(BHPKGAttributeID)id, value, fToken, token);
729ad6a8dbeSOliver Tappe	if (error != B_OK)
730ad6a8dbeSOliver Tappe		return error;
731ad6a8dbeSOliver Tappe
732ad6a8dbeSOliver Tappe	// create a subhandler for the attribute, if it has children
733ad6a8dbeSOliver Tappe	if (_handler != NULL) {
734ad6a8dbeSOliver Tappe		*_handler = new(std::nothrow) LowLevelAttributeHandler(id, value,
735697b9545SIngo Weinhold			fToken, token);
736ad6a8dbeSOliver Tappe		if (*_handler == NULL) {
737ad6a8dbeSOliver Tappe			context->lowLevelHandler->HandleAttributeDone((BHPKGAttributeID)id,
738697b9545SIngo Weinhold				value, fToken, token);
739ad6a8dbeSOliver Tappe			return B_NO_MEMORY;
740ad6a8dbeSOliver Tappe		}
741ad6a8dbeSOliver Tappe		return B_OK;
742ad6a8dbeSOliver Tappe	}
743ad6a8dbeSOliver Tappe
744ad6a8dbeSOliver Tappe	// no children -- just call the done hook
745ad6a8dbeSOliver Tappe	return context->lowLevelHandler->HandleAttributeDone((BHPKGAttributeID)id,
746697b9545SIngo Weinhold		value, fToken, token);
747ad6a8dbeSOliver Tappe}
748ad6a8dbeSOliver Tappe
749ad6a8dbeSOliver Tappe
750ad6a8dbeSOliver Tappestatus_t
7510a345af7SOliver TappeReaderImplBase::LowLevelAttributeHandler::NotifyDone(
752ad6a8dbeSOliver Tappe	AttributeHandlerContext* context)
753ad6a8dbeSOliver Tappe{
754ad6a8dbeSOliver Tappe	if (fID != B_HPKG_ATTRIBUTE_ID_ENUM_COUNT) {
7550a345af7SOliver Tappe		status_t error = context->lowLevelHandler->HandleAttributeDone(
756697b9545SIngo Weinhold			(BHPKGAttributeID)fID, fValue, fParentToken, fToken);
7570a345af7SOliver Tappe		if (error != B_OK)
7580a345af7SOliver Tappe			return error;
759ad6a8dbeSOliver Tappe	}
7600a345af7SOliver Tappe	return super::NotifyDone(context);
761ad6a8dbeSOliver Tappe}
762ad6a8dbeSOliver Tappe
763ad6a8dbeSOliver Tappe
764ad6a8dbeSOliver Tappe// #pragma mark - ReaderImplBase
765ad6a8dbeSOliver Tappe
766ad6a8dbeSOliver Tappe
7671f633814SIngo WeinholdReaderImplBase::ReaderImplBase(const char* fileType, BErrorOutput* errorOutput)
768ad6a8dbeSOliver Tappe	:
769ad6a8dbeSOliver Tappe	fPackageAttributesSection("package attributes"),
7701f633814SIngo Weinhold	fFileType(fileType),
771ad6a8dbeSOliver Tappe	fErrorOutput(errorOutput),
772e527b796SIngo Weinhold	fFile(NULL),
773e527b796SIngo Weinhold	fOwnsFile(false),
77446122852SIngo Weinhold	fRawHeapReader(NULL),
7751f633814SIngo Weinhold	fHeapReader(NULL),
7760dab9e5cSIngo Weinhold	fCurrentSection(NULL)
777ad6a8dbeSOliver Tappe{
778ad6a8dbeSOliver Tappe}
779ad6a8dbeSOliver Tappe
780ad6a8dbeSOliver Tappe
781ad6a8dbeSOliver TappeReaderImplBase::~ReaderImplBase()
782ad6a8dbeSOliver Tappe{
7831f633814SIngo Weinhold	delete fHeapReader;
78446122852SIngo Weinhold	if (fRawHeapReader != fHeapReader)
78546122852SIngo Weinhold		delete fRawHeapReader;
7861f633814SIngo Weinhold
787e527b796SIngo Weinhold	if (fOwnsFile)
788e527b796SIngo Weinhold		delete fFile;
789ad6a8dbeSOliver Tappe}
790ad6a8dbeSOliver Tappe
791ad6a8dbeSOliver Tappe
79246122852SIngo Weinholduint64
79346122852SIngo WeinholdReaderImplBase::UncompressedHeapSize() const
794ad6a8dbeSOliver Tappe{
79546122852SIngo Weinhold	return fRawHeapReader->UncompressedHeapSize();
79646122852SIngo Weinhold}
797ad6a8dbeSOliver Tappe
798ad6a8dbeSOliver Tappe
79946122852SIngo WeinholdBAbstractBufferedDataReader*
800e527b796SIngo WeinholdReaderImplBase::DetachHeapReader(PackageFileHeapReader*& _rawHeapReader)
80146122852SIngo Weinhold{
80246122852SIngo Weinhold	BAbstractBufferedDataReader* heapReader = fHeapReader;
803e527b796SIngo Weinhold	_rawHeapReader = fRawHeapReader;
80446122852SIngo Weinhold	fHeapReader = NULL;
80546122852SIngo Weinhold	fRawHeapReader = NULL;
80646122852SIngo Weinhold
80746122852SIngo Weinhold	return heapReader;
808ad6a8dbeSOliver Tappe}
809ad6a8dbeSOliver Tappe
810ad6a8dbeSOliver Tappe
8111f633814SIngo Weinholdstatus_t
8121f633814SIngo WeinholdReaderImplBase::InitHeapReader(uint32 compression, uint32 chunkSize,
8131f633814SIngo Weinhold	off_t offset, uint64 compressedSize, uint64 uncompressedSize)
814ad6a8dbeSOliver Tappe{
8158f5130edSIngo Weinhold	DecompressionAlgorithmOwner* decompressionAlgorithm = NULL;
8168f5130edSIngo Weinhold	BReference<DecompressionAlgorithmOwner> decompressionAlgorithmReference;
8178f5130edSIngo Weinhold
8188f5130edSIngo Weinhold	switch (compression) {
8198f5130edSIngo Weinhold		case B_HPKG_COMPRESSION_NONE:
8208f5130edSIngo Weinhold			break;
8218f5130edSIngo Weinhold		case B_HPKG_COMPRESSION_ZLIB:
8228f5130edSIngo Weinhold			decompressionAlgorithm = DecompressionAlgorithmOwner::Create(
8238f5130edSIngo Weinhold				new(std::nothrow) BZlibCompressionAlgorithm,
8248f5130edSIngo Weinhold				new(std::nothrow) BZlibDecompressionParameters);
8258f5130edSIngo Weinhold			decompressionAlgorithmReference.SetTo(decompressionAlgorithm, true);
8268f5130edSIngo Weinhold			if (decompressionAlgorithm == NULL
8278f5130edSIngo Weinhold				|| decompressionAlgorithm->algorithm == NULL
8288f5130edSIngo Weinhold				|| decompressionAlgorithm->parameters == NULL) {
8298f5130edSIngo Weinhold				return B_NO_MEMORY;
8308f5130edSIngo Weinhold			}
8318f5130edSIngo Weinhold			break;
832