xref: /haiku/src/kits/package/hpkg/ReaderImplBase.cpp (revision 0dab9e5cb4e244814a39d562cef87f9508780760)
1 /*
2  * Copyright 2009-2014, 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 #include <DataIO.h>
20 
21 #include <package/hpkg/HPKGDefsPrivate.h>
22 
23 #include <package/hpkg/PackageFileHeapReader.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 static const uint16 kAttributeTypes[B_HPKG_ATTRIBUTE_ID_ENUM_COUNT] = {
37 	#define B_DEFINE_HPKG_ATTRIBUTE(id, type, name, constant)	\
38 		B_HPKG_ATTRIBUTE_TYPE_##type,
39 	#include <package/hpkg/PackageAttributes.h>
40 	#undef B_DEFINE_HPKG_ATTRIBUTE
41 };
42 
43 // #pragma mark - AttributeHandlerContext
44 
45 
46 ReaderImplBase::AttributeHandlerContext::AttributeHandlerContext(
47 	BErrorOutput* errorOutput, BPackageContentHandler* packageContentHandler,
48 	BHPKGPackageSectionID section, bool ignoreUnknownAttributes)
49 	:
50 	errorOutput(errorOutput),
51 	packageContentHandler(packageContentHandler),
52 	hasLowLevelHandler(false),
53 	ignoreUnknownAttributes(ignoreUnknownAttributes),
54 	section(section)
55 {
56 }
57 
58 
59 ReaderImplBase::AttributeHandlerContext::AttributeHandlerContext(
60 	BErrorOutput* errorOutput, BLowLevelPackageContentHandler* lowLevelHandler,
61 	BHPKGPackageSectionID section, bool ignoreUnknownAttributes)
62 	:
63 	errorOutput(errorOutput),
64 	lowLevelHandler(lowLevelHandler),
65 	hasLowLevelHandler(true),
66 	ignoreUnknownAttributes(ignoreUnknownAttributes),
67 	section(section)
68 {
69 }
70 
71 
72 void
73 ReaderImplBase::AttributeHandlerContext::ErrorOccurred()
74 {
75 	if (hasLowLevelHandler)
76 		lowLevelHandler->HandleErrorOccurred();
77 	else
78 		packageContentHandler->HandleErrorOccurred();
79 }
80 
81 
82 // #pragma mark - AttributeHandler
83 
84 
85 ReaderImplBase::AttributeHandler::~AttributeHandler()
86 {
87 }
88 
89 
90 void
91 ReaderImplBase::AttributeHandler::SetLevel(int level)
92 {
93 	fLevel = level;
94 }
95 
96 
97 status_t
98 ReaderImplBase::AttributeHandler::HandleAttribute(
99 	AttributeHandlerContext* context, uint8 id, const AttributeValue& value,
100 	AttributeHandler** _handler)
101 {
102 	return B_OK;
103 }
104 
105 
106 status_t
107 ReaderImplBase::AttributeHandler::NotifyDone(
108 	AttributeHandlerContext* context)
109 {
110 	return B_OK;
111 }
112 
113 
114 status_t
115 ReaderImplBase::AttributeHandler::Delete(AttributeHandlerContext* context)
116 {
117 	delete this;
118 	return B_OK;
119 }
120 
121 
122 // #pragma mark - PackageInfoAttributeHandlerBase
123 
124 
125 ReaderImplBase::PackageInfoAttributeHandlerBase
126 	::PackageInfoAttributeHandlerBase(
127 		BPackageInfoAttributeValue& packageInfoValue)
128 	:
129 	fPackageInfoValue(packageInfoValue)
130 {
131 }
132 
133 
134 status_t
135 ReaderImplBase::PackageInfoAttributeHandlerBase::NotifyDone(
136 	AttributeHandlerContext* context)
137 {
138 	status_t error = context->packageContentHandler->HandlePackageAttribute(
139 		fPackageInfoValue);
140 	fPackageInfoValue.Clear();
141 	return error;
142 }
143 
144 
145 // #pragma mark - PackageVersionAttributeHandler
146 
147 
148 ReaderImplBase::PackageVersionAttributeHandler::PackageVersionAttributeHandler(
149 	BPackageInfoAttributeValue& packageInfoValue,
150 	BPackageVersionData& versionData, bool notify)
151 	:
152 	super(packageInfoValue),
153 	fPackageVersionData(versionData),
154 	fNotify(notify)
155 {
156 }
157 
158 
159 status_t
160 ReaderImplBase::PackageVersionAttributeHandler::HandleAttribute(
161 	AttributeHandlerContext* context, uint8 id, const AttributeValue& value,
162 	AttributeHandler** _handler)
163 {
164 	switch (id) {
165 		case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_MINOR:
166 			fPackageVersionData.minor = value.string;
167 			break;
168 
169 		case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_MICRO:
170 			fPackageVersionData.micro = value.string;
171 			break;
172 
173 		case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_PRE_RELEASE:
174 			fPackageVersionData.preRelease = value.string;
175 			break;
176 
177 		case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_REVISION:
178 			fPackageVersionData.revision = value.unsignedInt;
179 			break;
180 
181 		default:
182 			if (context->ignoreUnknownAttributes)
183 				break;
184 
185 			context->errorOutput->PrintError("Error: Invalid package "
186 				"attribute section: unexpected package attribute id %d "
187 				"encountered when parsing package version\n", id);
188 			return B_BAD_DATA;
189 	}
190 
191 	return B_OK;
192 }
193 
194 
195 status_t
196 ReaderImplBase::PackageVersionAttributeHandler::NotifyDone(
197 	AttributeHandlerContext* context)
198 {
199 	if (!fNotify)
200 		return B_OK;
201 
202 	fPackageInfoValue.attributeID = B_PACKAGE_INFO_VERSION;
203 	return super::NotifyDone(context);
204 }
205 
206 
207 // #pragma mark - PackageResolvableAttributeHandler
208 
209 
210 ReaderImplBase::PackageResolvableAttributeHandler
211 	::PackageResolvableAttributeHandler(
212 		BPackageInfoAttributeValue& packageInfoValue)
213 	:
214 	super(packageInfoValue)
215 {
216 }
217 
218 
219 status_t
220 ReaderImplBase::PackageResolvableAttributeHandler::HandleAttribute(
221 	AttributeHandlerContext* context, uint8 id, const AttributeValue& value,
222 	AttributeHandler** _handler)
223 {
224 	switch (id) {
225 		case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_MAJOR:
226 			fPackageInfoValue.resolvable.haveVersion = true;
227 			fPackageInfoValue.resolvable.version.major = value.string;
228 			if (_handler != NULL) {
229 				*_handler
230 					= new(std::nothrow) PackageVersionAttributeHandler(
231 						fPackageInfoValue,
232 						fPackageInfoValue.resolvable.version, false);
233 				if (*_handler == NULL)
234 					return B_NO_MEMORY;
235 			}
236 			break;
237 
238 		case B_HPKG_ATTRIBUTE_ID_PACKAGE_PROVIDES_COMPATIBLE:
239 			fPackageInfoValue.resolvable.haveCompatibleVersion = true;
240 			fPackageInfoValue.resolvable.compatibleVersion.major = value.string;
241 			if (_handler != NULL) {
242 				*_handler
243 					= new(std::nothrow) PackageVersionAttributeHandler(
244 						fPackageInfoValue,
245 						fPackageInfoValue.resolvable.compatibleVersion, false);
246 				if (*_handler == NULL)
247 					return B_NO_MEMORY;
248 			}
249 			break;
250 
251 		default:
252 			if (context->ignoreUnknownAttributes)
253 				break;
254 
255 			context->errorOutput->PrintError("Error: Invalid package "
256 				"attribute section: unexpected package attribute id %d "
257 				"encountered when parsing package resolvable\n", id);
258 			return B_BAD_DATA;
259 	}
260 
261 	return B_OK;
262 }
263 
264 
265 // #pragma mark - PackageResolvableExpressionAttributeHandler
266 
267 
268 ReaderImplBase::PackageResolvableExpressionAttributeHandler
269 	::PackageResolvableExpressionAttributeHandler(
270 		BPackageInfoAttributeValue& packageInfoValue)
271 	:
272 	super(packageInfoValue)
273 {
274 }
275 
276 
277 status_t
278 ReaderImplBase::PackageResolvableExpressionAttributeHandler::HandleAttribute(
279 	AttributeHandlerContext* context, uint8 id, const AttributeValue& value,
280 	AttributeHandler** _handler)
281 {
282 	switch (id) {
283 		case B_HPKG_ATTRIBUTE_ID_PACKAGE_RESOLVABLE_OPERATOR:
284 			if (value.unsignedInt >= B_PACKAGE_RESOLVABLE_OP_ENUM_COUNT) {
285 				context->errorOutput->PrintError(
286 					"Error: Invalid package attribute section: invalid "
287 					"package resolvable operator %lld encountered\n",
288 					value.unsignedInt);
289 				return B_BAD_DATA;
290 			}
291 			fPackageInfoValue.resolvableExpression.op
292 				= (BPackageResolvableOperator)value.unsignedInt;
293 			break;
294 
295 		case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_MAJOR:
296 			fPackageInfoValue.resolvableExpression.haveOpAndVersion = true;
297 			fPackageInfoValue.resolvableExpression.version.major
298 				= value.string;
299 			if (_handler != NULL) {
300 				*_handler
301 					= new(std::nothrow) PackageVersionAttributeHandler(
302 						fPackageInfoValue,
303 						fPackageInfoValue.resolvableExpression.version,
304 						false);
305 				if (*_handler == NULL)
306 					return B_NO_MEMORY;
307 			}
308 			return B_OK;
309 
310 		default:
311 			if (context->ignoreUnknownAttributes)
312 				break;
313 
314 			context->errorOutput->PrintError("Error: Invalid package "
315 				"attribute section: unexpected package attribute id %d "
316 				"encountered when parsing package resolvable-expression\n",
317 				id);
318 			return B_BAD_DATA;
319 	}
320 
321 	return B_OK;
322 }
323 
324 
325 // #pragma mark - GlobalWritableFileInfoAttributeHandler
326 
327 
328 ReaderImplBase::GlobalWritableFileInfoAttributeHandler
329 	::GlobalWritableFileInfoAttributeHandler(
330 		BPackageInfoAttributeValue& packageInfoValue)
331 	:
332 	super(packageInfoValue)
333 {
334 }
335 
336 
337 status_t
338 ReaderImplBase::GlobalWritableFileInfoAttributeHandler::HandleAttribute(
339 	AttributeHandlerContext* context, uint8 id, const AttributeValue& value,
340 	AttributeHandler** _handler)
341 {
342 	switch (id) {
343 		case B_HPKG_ATTRIBUTE_ID_PACKAGE_WRITABLE_FILE_UPDATE_TYPE:
344 			if (value.unsignedInt >= B_WRITABLE_FILE_UPDATE_TYPE_ENUM_COUNT) {
345 				context->errorOutput->PrintError(
346 					"Error: Invalid package attribute section: invalid "
347 					"global settings file update type %" B_PRIu64
348 					" encountered\n", value.unsignedInt);
349 				return B_BAD_DATA;
350 			}
351 			fPackageInfoValue.globalWritableFileInfo.updateType
352 				= (BWritableFileUpdateType)value.unsignedInt;
353 			break;
354 
355 		case B_HPKG_ATTRIBUTE_ID_PACKAGE_IS_WRITABLE_DIRECTORY:
356 			fPackageInfoValue.globalWritableFileInfo.isDirectory
357 				= value.unsignedInt != 0;
358 			break;
359 
360 		default:
361 			if (context->ignoreUnknownAttributes)
362 				break;
363 
364 			context->errorOutput->PrintError("Error: Invalid package "
365 				"attribute section: unexpected package attribute id %d "
366 				"encountered when parsing global settings file info\n",
367 				id);
368 			return B_BAD_DATA;
369 	}
370 
371 	return B_OK;
372 }
373 
374 
375 // #pragma mark - UserSettingsFileInfoAttributeHandler
376 
377 
378 ReaderImplBase::UserSettingsFileInfoAttributeHandler
379 	::UserSettingsFileInfoAttributeHandler(
380 		BPackageInfoAttributeValue& packageInfoValue)
381 	:
382 	super(packageInfoValue)
383 {
384 }
385 
386 
387 status_t
388 ReaderImplBase::UserSettingsFileInfoAttributeHandler::HandleAttribute(
389 	AttributeHandlerContext* context, uint8 id, const AttributeValue& value,
390 	AttributeHandler** _handler)
391 {
392 	switch (id) {
393 		case B_HPKG_ATTRIBUTE_ID_PACKAGE_SETTINGS_FILE_TEMPLATE:
394 			fPackageInfoValue.userSettingsFileInfo.templatePath = value.string;
395 			break;
396 
397 		case B_HPKG_ATTRIBUTE_ID_PACKAGE_IS_WRITABLE_DIRECTORY:
398 			fPackageInfoValue.userSettingsFileInfo.isDirectory
399 				= value.unsignedInt != 0;
400 			break;
401 
402 		default:
403 			if (context->ignoreUnknownAttributes)
404 				break;
405 
406 			context->errorOutput->PrintError("Error: Invalid package "
407 				"attribute section: unexpected package attribute id %d "
408 				"encountered when parsing user settings file info\n",
409 				id);
410 			return B_BAD_DATA;
411 	}
412 
413 	return B_OK;
414 }
415 
416 
417 // #pragma mark - UserAttributeHandler
418 
419 
420 ReaderImplBase::UserAttributeHandler::UserAttributeHandler(
421 		BPackageInfoAttributeValue& packageInfoValue)
422 	:
423 	super(packageInfoValue),
424 	fGroups()
425 {
426 }
427 
428 
429 status_t
430 ReaderImplBase::UserAttributeHandler::HandleAttribute(
431 	AttributeHandlerContext* context, uint8 id, const AttributeValue& value,
432 	AttributeHandler** _handler)
433 {
434 	switch (id) {
435 		case B_HPKG_ATTRIBUTE_ID_PACKAGE_USER_REAL_NAME:
436 			fPackageInfoValue.user.realName = value.string;
437 			break;
438 
439 		case B_HPKG_ATTRIBUTE_ID_PACKAGE_USER_HOME:
440 			fPackageInfoValue.user.home = value.string;
441 			break;
442 
443 		case B_HPKG_ATTRIBUTE_ID_PACKAGE_USER_SHELL:
444 			fPackageInfoValue.user.shell = value.string;
445 			break;
446 
447 		case B_HPKG_ATTRIBUTE_ID_PACKAGE_USER_GROUP:
448 			if (!fGroups.Add(value.string))
449 				return B_NO_MEMORY;
450 			break;
451 
452 		default:
453 			if (context->ignoreUnknownAttributes)
454 				break;
455 
456 			context->errorOutput->PrintError("Error: Invalid package "
457 				"attribute section: unexpected package attribute id %d "
458 				"encountered when parsing user settings file info\n",
459 				id);
460 			return B_BAD_DATA;
461 	}
462 
463 	return B_OK;
464 }
465 
466 
467 status_t
468 ReaderImplBase::UserAttributeHandler::NotifyDone(
469 	AttributeHandlerContext* context)
470 {
471 	if (!fGroups.IsEmpty()) {
472 		fPackageInfoValue.user.groups = fGroups.Elements();
473 		fPackageInfoValue.user.groupCount = fGroups.Count();
474 	}
475 
476 	return super::NotifyDone(context);
477 }
478 
479 
480 // #pragma mark - PackageAttributeHandler
481 
482 
483 status_t
484 ReaderImplBase::PackageAttributeHandler::HandleAttribute(
485 	AttributeHandlerContext* context, uint8 id, const AttributeValue& value,
486 	AttributeHandler** _handler)
487 {
488 	switch (id) {
489 		case B_HPKG_ATTRIBUTE_ID_PACKAGE_NAME:
490 			fPackageInfoValue.SetTo(B_PACKAGE_INFO_NAME, value.string);
491 			break;
492 
493 		case B_HPKG_ATTRIBUTE_ID_PACKAGE_SUMMARY:
494 			fPackageInfoValue.SetTo(B_PACKAGE_INFO_SUMMARY, value.string);
495 			break;
496 
497 		case B_HPKG_ATTRIBUTE_ID_PACKAGE_DESCRIPTION:
498 			fPackageInfoValue.SetTo(B_PACKAGE_INFO_DESCRIPTION,
499 				value.string);
500 			break;
501 
502 		case B_HPKG_ATTRIBUTE_ID_PACKAGE_VENDOR:
503 			fPackageInfoValue.SetTo(B_PACKAGE_INFO_VENDOR, value.string);
504 			break;
505 
506 		case B_HPKG_ATTRIBUTE_ID_PACKAGE_PACKAGER:
507 			fPackageInfoValue.SetTo(B_PACKAGE_INFO_PACKAGER, value.string);
508 			break;
509 
510 		case B_HPKG_ATTRIBUTE_ID_PACKAGE_BASE_PACKAGE:
511 			fPackageInfoValue.SetTo(B_PACKAGE_INFO_BASE_PACKAGE, value.string);
512 			break;
513 
514 		case B_HPKG_ATTRIBUTE_ID_PACKAGE_FLAGS:
515 			fPackageInfoValue.SetTo(B_PACKAGE_INFO_FLAGS,
516 				(uint32)value.unsignedInt);
517 			break;
518 
519 		case B_HPKG_ATTRIBUTE_ID_PACKAGE_ARCHITECTURE:
520 			if (value.unsignedInt
521 					>= B_PACKAGE_ARCHITECTURE_ENUM_COUNT) {
522 				context->errorOutput->PrintError(
523 					"Error: Invalid package attribute section: "
524 					"Invalid package architecture %lld encountered\n",
525 					value.unsignedInt);
526 				return B_BAD_DATA;
527 			}
528 			fPackageInfoValue.SetTo(B_PACKAGE_INFO_ARCHITECTURE,
529 				(uint8)value.unsignedInt);
530 			break;
531 
532 		case B_HPKG_ATTRIBUTE_ID_PACKAGE_VERSION_MAJOR:
533 			fPackageInfoValue.attributeID = B_PACKAGE_INFO_VERSION;
534 			fPackageInfoValue.version.major = value.string;
535 			if (_handler != NULL) {
536 				*_handler
537 					= new(std::nothrow) PackageVersionAttributeHandler(
538 						fPackageInfoValue, fPackageInfoValue.version, true);
539 				if (*_handler == NULL)
540 					return B_NO_MEMORY;
541 			}
542 			break;
543 
544 		case B_HPKG_ATTRIBUTE_ID_PACKAGE_COPYRIGHT:
545 			fPackageInfoValue.SetTo(B_PACKAGE_INFO_COPYRIGHTS,
546 				value.string);
547 			break;
548 
549 		case B_HPKG_ATTRIBUTE_ID_PACKAGE_LICENSE:
550 			fPackageInfoValue.SetTo(B_PACKAGE_INFO_LICENSES,
551 				value.string);
552 			break;
553 
554 		case B_HPKG_ATTRIBUTE_ID_PACKAGE_URL:
555 			fPackageInfoValue.SetTo(B_PACKAGE_INFO_URLS, value.string);
556 			break;
557 
558 		case B_HPKG_ATTRIBUTE_ID_PACKAGE_SOURCE_URL:
559 			fPackageInfoValue.SetTo(B_PACKAGE_INFO_SOURCE_URLS, value.string);
560 			break;
561 
562 		case B_HPKG_ATTRIBUTE_ID_PACKAGE_PROVIDES:
563 			fPackageInfoValue.resolvable.name = value.string;
564 			fPackageInfoValue.attributeID = B_PACKAGE_INFO_PROVIDES;
565 			if (_handler != NULL) {
566 				*_handler
567 					= new(std::nothrow) PackageResolvableAttributeHandler(
568 						fPackageInfoValue);
569 				if (*_handler == NULL)
570 					return B_NO_MEMORY;
571 			}
572 			break;
573 
574 		case B_HPKG_ATTRIBUTE_ID_PACKAGE_REQUIRES:
575 		case B_HPKG_ATTRIBUTE_ID_PACKAGE_SUPPLEMENTS:
576 		case B_HPKG_ATTRIBUTE_ID_PACKAGE_CONFLICTS:
577 		case B_HPKG_ATTRIBUTE_ID_PACKAGE_FRESHENS:
578 			fPackageInfoValue.resolvableExpression.name = value.string;
579 			switch (id) {
580 				case B_HPKG_ATTRIBUTE_ID_PACKAGE_REQUIRES:
581 					fPackageInfoValue.attributeID = B_PACKAGE_INFO_REQUIRES;
582 					break;
583 
584 				case B_HPKG_ATTRIBUTE_ID_PACKAGE_SUPPLEMENTS:
585 					fPackageInfoValue.attributeID
586 						= B_PACKAGE_INFO_SUPPLEMENTS;
587 					break;
588 
589 				case B_HPKG_ATTRIBUTE_ID_PACKAGE_CONFLICTS:
590 					fPackageInfoValue.attributeID
591 						= B_PACKAGE_INFO_CONFLICTS;
592 					break;
593 
594 				case B_HPKG_ATTRIBUTE_ID_PACKAGE_FRESHENS:
595 					fPackageInfoValue.attributeID = B_PACKAGE_INFO_FRESHENS;
596 					break;
597 			}
598 			if (_handler != NULL) {
599 				*_handler = new(std::nothrow)
600 					PackageResolvableExpressionAttributeHandler(
601 						fPackageInfoValue);
602 				if (*_handler == NULL)
603 					return B_NO_MEMORY;
604 			}
605 			break;
606 
607 		case B_HPKG_ATTRIBUTE_ID_PACKAGE_REPLACES:
608 			fPackageInfoValue.SetTo(B_PACKAGE_INFO_REPLACES, value.string);
609 			break;
610 
611 		case B_HPKG_ATTRIBUTE_ID_PACKAGE_CHECKSUM:
612 			fPackageInfoValue.SetTo(B_PACKAGE_INFO_CHECKSUM, value.string);
613 			break;
614 
615 		case B_HPKG_ATTRIBUTE_ID_PACKAGE_INSTALL_PATH:
616 			fPackageInfoValue.SetTo(B_PACKAGE_INFO_INSTALL_PATH, value.string);
617 			break;
618 
619 		case B_HPKG_ATTRIBUTE_ID_PACKAGE_GLOBAL_WRITABLE_FILE:
620 			fPackageInfoValue.globalWritableFileInfo.path = value.string;
621 			fPackageInfoValue.globalWritableFileInfo.updateType
622 				= B_WRITABLE_FILE_UPDATE_TYPE_ENUM_COUNT;
623 			fPackageInfoValue.attributeID
624 				= B_PACKAGE_INFO_GLOBAL_WRITABLE_FILES;
625 			if (_handler != NULL) {
626 				*_handler
627 					= new(std::nothrow) GlobalWritableFileInfoAttributeHandler(
628 						fPackageInfoValue);
629 				if (*_handler == NULL)
630 					return B_NO_MEMORY;
631 			}
632 			break;
633 
634 		case B_HPKG_ATTRIBUTE_ID_PACKAGE_USER_SETTINGS_FILE:
635 			fPackageInfoValue.userSettingsFileInfo.path = value.string;
636 			fPackageInfoValue.attributeID
637 				= B_PACKAGE_INFO_USER_SETTINGS_FILES;
638 			if (_handler != NULL) {
639 				*_handler
640 					= new(std::nothrow) UserSettingsFileInfoAttributeHandler(
641 						fPackageInfoValue);
642 				if (*_handler == NULL)
643 					return B_NO_MEMORY;
644 			}
645 			break;
646 
647 		case B_HPKG_ATTRIBUTE_ID_PACKAGE_USER:
648 			fPackageInfoValue.user.name = value.string;
649 			fPackageInfoValue.attributeID = B_PACKAGE_INFO_USERS;
650 			if (_handler != NULL) {
651 				*_handler = new(std::nothrow) UserAttributeHandler(
652 					fPackageInfoValue);
653 				if (*_handler == NULL)
654 					return B_NO_MEMORY;
655 			}
656 			break;
657 
658 		case B_HPKG_ATTRIBUTE_ID_PACKAGE_GROUP:
659 			fPackageInfoValue.SetTo(B_PACKAGE_INFO_GROUPS, value.string);
660 			break;
661 
662 		case B_HPKG_ATTRIBUTE_ID_PACKAGE_POST_INSTALL_SCRIPT:
663 			fPackageInfoValue.SetTo(B_PACKAGE_INFO_POST_INSTALL_SCRIPTS,
664 				value.string);
665 			break;
666 
667 		default:
668 			if (context->ignoreUnknownAttributes)
669 				break;
670 
671 			context->errorOutput->PrintError(
672 				"Error: Invalid package attribute section: unexpected "
673 				"package attribute id %d encountered\n", id);
674 			return B_BAD_DATA;
675 	}
676 
677 	// notify unless the current attribute has children, in which case
678 	// the child-handler will notify when it's done
679 	if (_handler == NULL) {
680 		status_t error = context->packageContentHandler
681 			->HandlePackageAttribute(fPackageInfoValue);
682 		fPackageInfoValue.Clear();
683 		if (error != B_OK)
684 			return error;
685 	}
686 
687 	return B_OK;
688 }
689 
690 
691 // #pragma mark - LowLevelAttributeHandler
692 
693 
694 ReaderImplBase::LowLevelAttributeHandler::LowLevelAttributeHandler()
695 	:
696 	fParentToken(NULL),
697 	fToken(NULL),
698 	fID(B_HPKG_ATTRIBUTE_ID_ENUM_COUNT)
699 {
700 }
701 
702 
703 ReaderImplBase::LowLevelAttributeHandler::LowLevelAttributeHandler(uint8 id,
704 	const BPackageAttributeValue& value, void* parentToken, void* token)
705 	:
706 	fParentToken(NULL),
707 	fToken(token),
708 	fID(id),
709 	fValue(value)
710 {
711 }
712 
713 
714 status_t
715 ReaderImplBase::LowLevelAttributeHandler::HandleAttribute(
716 	AttributeHandlerContext* context, uint8 id, const AttributeValue& value,
717 	AttributeHandler** _handler)
718 {
719 	// notify the content handler
720 	void* token;
721 	status_t error = context->lowLevelHandler->HandleAttribute(
722 		(BHPKGAttributeID)id, value, fToken, token);
723 	if (error != B_OK)
724 		return error;
725 
726 	// create a subhandler for the attribute, if it has children
727 	if (_handler != NULL) {
728 		*_handler = new(std::nothrow) LowLevelAttributeHandler(id, value,
729 			fToken, token);
730 		if (*_handler == NULL) {
731 			context->lowLevelHandler->HandleAttributeDone((BHPKGAttributeID)id,
732 				value, fToken, token);
733 			return B_NO_MEMORY;
734 		}
735 		return B_OK;
736 	}
737 
738 	// no children -- just call the done hook
739 	return context->lowLevelHandler->HandleAttributeDone((BHPKGAttributeID)id,
740 		value, fToken, token);
741 }
742 
743 
744 status_t
745 ReaderImplBase::LowLevelAttributeHandler::NotifyDone(
746 	AttributeHandlerContext* context)
747 {
748 	if (fID != B_HPKG_ATTRIBUTE_ID_ENUM_COUNT) {
749 		status_t error = context->lowLevelHandler->HandleAttributeDone(
750 			(BHPKGAttributeID)fID, fValue, fParentToken, fToken);
751 		if (error != B_OK)
752 			return error;
753 	}
754 	return super::NotifyDone(context);
755 }
756 
757 
758 // #pragma mark - ReaderImplBase
759 
760 
761 ReaderImplBase::ReaderImplBase(const char* fileType, BErrorOutput* errorOutput)
762 	:
763 	fPackageAttributesSection("package attributes"),
764 	fFileType(fileType),
765 	fErrorOutput(errorOutput),
766 	fFD(-1),
767 	fOwnsFD(false),
768 	fRawHeapReader(NULL),
769 	fHeapReader(NULL),
770 	fCurrentSection(NULL)
771 {
772 }
773 
774 
775 ReaderImplBase::~ReaderImplBase()
776 {
777 	delete fHeapReader;
778 	if (fRawHeapReader != fHeapReader)
779 		delete fRawHeapReader;
780 
781 	if (fOwnsFD && fFD >= 0)
782 		close(fFD);
783 }
784 
785 
786 uint64
787 ReaderImplBase::UncompressedHeapSize() const
788 {
789 	return fRawHeapReader->UncompressedHeapSize();
790 }
791 
792 
793 BAbstractBufferedDataReader*
794 ReaderImplBase::DetachHeapReader(PackageFileHeapReader** _rawHeapReader)
795 {
796 	BAbstractBufferedDataReader* heapReader = fHeapReader;
797 	fHeapReader = NULL;
798 
799 	if (_rawHeapReader != NULL)
800 		*_rawHeapReader = fRawHeapReader;
801 	fRawHeapReader = NULL;
802 
803 	return heapReader;
804 }
805 
806 
807 status_t
808 ReaderImplBase::InitHeapReader(uint32 compression, uint32 chunkSize,
809 	off_t offset, uint64 compressedSize, uint64 uncompressedSize)
810 {
811 	if (compression != B_HPKG_COMPRESSION_ZLIB) {
812 		fErrorOutput->PrintError("Error: Invalid heap compression\n");
813 		return B_BAD_DATA;
814 	}
815 
816 	fRawHeapReader = new(std::nothrow) PackageFileHeapReader(fErrorOutput, fFD,
817 		offset, compressedSize, uncompressedSize);
818 	if (fRawHeapReader == NULL)
819 		return B_NO_MEMORY;
820 
821 	status_t error = fRawHeapReader->Init();
822 	if (error != B_OK)
823 		return error;
824 
825 	error = CreateCachedHeapReader(fRawHeapReader, fHeapReader);
826 	if (error != B_OK) {
827 		if (error != B_NOT_SUPPORTED)
828 			return error;
829 
830 		fHeapReader = fRawHeapReader;
831 	}
832 
833 	return B_OK;
834 }
835 
836 
837 status_t
838 ReaderImplBase::CreateCachedHeapReader(PackageFileHeapReader* heapReader,
839 	BAbstractBufferedDataReader*& _cachedReader)
840 {
841 	return B_NOT_SUPPORTED;
842 }
843 
844 
845 status_t
846 ReaderImplBase::InitSection(PackageFileSection& section, uint64 endOffset,
847 	uint64 length, uint64 maxSaneLength, uint64 stringsLength,
848 	uint64 stringsCount)
849 {
850 	// check length vs. endOffset
851 	if (length > endOffset) {
852 		ErrorOutput()->PrintError("Error: %s file %s section size is %"
853 			B_PRIu64 " bytes. This is greater than the available space\n",
854 			fFileType, section.name, length);
855 		return B_BAD_DATA;
856 	}
857 
858 	// check sanity length
859 	if (maxSaneLength > 0 && length > maxSaneLength) {
860 		ErrorOutput()->PrintError("Error: %s file %s section size is %"
861 			B_PRIu64 " bytes. This is beyond the reader's sanity limit\n",
862 			fFileType, section.name, length);
863 		return B_NOT_SUPPORTED;
864 	}
865 
866 	// check strings subsection size/count
867 	if ((stringsLength <= 1) != (stringsCount == 0) || stringsLength > length) {
868 		ErrorOutput()->PrintError("Error: strings subsection description of %s "
869 			"file %s section is invalid (%" B_PRIu64 " strings, length: %"
870 			B_PRIu64 ", section length: %" B_PRIu64 ")\n",
871 			fFileType, section.name, stringsCount, stringsLength, length);
872 		return B_BAD_DATA;
873 	}
874 
875 	section.uncompressedLength = length;
876 	section.offset = endOffset - length;
877 	section.currentOffset = 0;
878 	section.stringsLength = stringsLength;
879 	section.stringsCount = stringsCount;
880 
881 	return B_OK;
882 }
883 
884 
885 status_t
886 ReaderImplBase::PrepareSection(PackageFileSection& section)
887 {
888 	// allocate memory for the section data and read it in
889 	section.data = new(std::nothrow) uint8[section.uncompressedLength];
890 	if (section.data == NULL) {
891 		ErrorOutput()->PrintError("Error: Out of memory!\n");
892 		return B_NO_MEMORY;
893 	}
894 
895 	status_t error = ReadSection(section);
896 	if (error != B_OK)
897 		return error;
898 
899 	// parse the section strings
900 	section.currentOffset = 0;
901 	SetCurrentSection(&section);
902 
903 	error = ParseStrings();
904 	if (error != B_OK)
905 		return error;
906 
907 	return B_OK;
908 }
909 
910 
911 status_t
912 ReaderImplBase::ParseStrings()
913 {
914 	// allocate table, if there are any strings
915 	if (fCurrentSection->stringsCount == 0) {
916 		fCurrentSection->currentOffset += fCurrentSection->stringsLength;
917 		return B_OK;
918 	}
919 
920 	fCurrentSection->strings
921 		= new(std::nothrow) char*[fCurrentSection->stringsCount];
922 	if (fCurrentSection->strings == NULL) {
923 		fErrorOutput->PrintError("Error: Out of memory!\n");
924 		return B_NO_MEMORY;
925 	}
926 
927 	// parse the section and fill the table
928 	char* position
929 		= (char*)fCurrentSection->data + fCurrentSection->currentOffset;
930 	char* sectionEnd = position + fCurrentSection->stringsLength;
931 	uint32 index = 0;
932 	while (true) {
933 		if (position >= sectionEnd) {
934 			fErrorOutput->PrintError("Error: Malformed %s strings section\n",
935 				fCurrentSection->name);
936 			return B_BAD_DATA;
937 		}
938 
939 		size_t stringLength = strnlen(position, (char*)sectionEnd - position);
940 
941 		if (stringLength == 0) {
942 			if (position + 1 != sectionEnd) {
943 				fErrorOutput->PrintError(
944 					"Error: %ld excess bytes in %s strings section\n",
945 					sectionEnd - (position + 1), fCurrentSection->name);
946 				return B_BAD_DATA;
947 			}
948 
949 			if (index != fCurrentSection->stringsCount) {
950 				fErrorOutput->PrintError("Error: Invalid %s strings section: "
951 					"Less strings (%lld) than specified in the header (%lld)\n",
952 					fCurrentSection->name, index,
953 					fCurrentSection->stringsCount);
954 				return B_BAD_DATA;
955 			}
956 
957 			fCurrentSection->currentOffset += fCurrentSection->stringsLength;
958 
959 			return B_OK;
960 		}
961 
962 		if (index >= fCurrentSection->stringsCount) {
963 			fErrorOutput->PrintError("Error: Invalid %s strings section: "
964 				"More strings (%lld) than specified in the header (%lld)\n",
965 				fCurrentSection->name, index, fCurrentSection->stringsCount);
966 			return B_BAD_DATA;
967 		}
968 
969 		fCurrentSection->strings[index++] = position;
970 		position += stringLength + 1;
971 	}
972 }
973 
974 
975 status_t
976 ReaderImplBase::ParsePackageAttributesSection(
977 	AttributeHandlerContext* context, AttributeHandler* rootAttributeHandler)
978 {
979 	// parse package attributes
980 	SetCurrentSection(&fPackageAttributesSection);
981 
982 	// init the attribute handler stack
983 	rootAttributeHandler->SetLevel(0);
984 	ClearAttributeHandlerStack();
985 	PushAttributeHandler(rootAttributeHandler);
986 
987 	bool sectionHandled;
988 	status_t error = ParseAttributeTree(context, sectionHandled);
989 	if (error == B_OK && sectionHandled) {
990 		if (fPackageAttributesSection.currentOffset
991 				< fPackageAttributesSection.uncompressedLength) {
992 			fErrorOutput->PrintError("Error: %llu excess byte(s) in package "
993 				"attributes section\n",
994 				fPackageAttributesSection.uncompressedLength
995 					- fPackageAttributesSection.currentOffset);
996 			error = B_BAD_DATA;
997 		}
998 	}
999 
1000 	SetCurrentSection(NULL);
1001 
1002 	// clean up on error
1003 	if (error != B_OK) {
1004 		context->ErrorOccurred();
1005 		while (AttributeHandler* handler = PopAttributeHandler()) {
1006 			if (handler != rootAttributeHandler)
1007 				handler->Delete(context);
1008 		}
1009 		return error;
1010 	}
1011 
1012 	return B_OK;
1013 }
1014 
1015 
1016 status_t
1017 ReaderImplBase::ParseAttributeTree(AttributeHandlerContext* context,
1018 	bool& _sectionHandled)
1019 {
1020 	if (context->hasLowLevelHandler) {
1021 		bool handleSection = false;
1022 		status_t error = context->lowLevelHandler->HandleSectionStart(
1023 			context->section, handleSection);
1024 		if (error != B_OK)
1025 			return error;
1026 
1027 		if (!handleSection) {
1028 			_sectionHandled = false;
1029 			return B_OK;
1030 		}
1031 	}
1032 
1033 	status_t error = _ParseAttributeTree(context);
1034 
1035 	if (context->hasLowLevelHandler) {
1036 		status_t endError = context->lowLevelHandler->HandleSectionEnd(
1037 			context->section);
1038 		if (error == B_OK)
1039 			error = endError;
1040 	}
1041 
1042 	_sectionHandled = true;
1043 	return error;
1044 }
1045 
1046 
1047 status_t
1048 ReaderImplBase::_Init(int fd, bool keepFD)
1049 {
1050 	fFD = fd;
1051 	fOwnsFD = keepFD;
1052 
1053 	return B_OK;
1054 }
1055 
1056 
1057 status_t
1058 ReaderImplBase::_ParseAttributeTree(AttributeHandlerContext* context)
1059 {
1060 	int level = 0;
1061 
1062 	while (true) {
1063 		uint8 id;
1064 		AttributeValue value;
1065 		bool hasChildren;
1066 		uint64 tag;
1067 
1068 		status_t error = _ReadAttribute(id, value, &hasChildren, &tag);
1069 		if (error != B_OK)
1070 			return error;
1071 
1072 		if (tag == 0) {
1073 			AttributeHandler* handler = PopAttributeHandler();
1074 			error = handler->NotifyDone(context);
1075 			if (error != B_OK)
1076 				return error;
1077 			if (level-- == 0)
1078 				return B_OK;
1079 
1080 			error = handler->Delete(context);
1081 			if (error != B_OK)
1082 				return error;
1083 
1084 			continue;
1085 		}
1086 
1087 		AttributeHandler* childHandler = NULL;
1088 		error = CurrentAttributeHandler()->HandleAttribute(context, id, value,
1089 			hasChildren ? &childHandler : NULL);
1090 		if (error != B_OK)
1091 			return error;
1092 
1093 		// parse children
1094 		if (hasChildren) {
1095 			// create an ignore handler, if necessary
1096 			if (childHandler == NULL) {
1097 				childHandler = new(std::nothrow) IgnoreAttributeHandler;
1098 				if (childHandler == NULL) {
1099 					fErrorOutput->PrintError("Error: Out of memory!\n");
1100 					return B_NO_MEMORY;
1101 				}
1102 			}
1103 
1104 			childHandler->SetLevel(++level);
1105 			PushAttributeHandler(childHandler);
1106 		}
1107 	}
1108 }
1109 
1110 
1111 status_t
1112 ReaderImplBase::_ReadAttribute(uint8& _id, AttributeValue& _value,
1113 	bool* _hasChildren, uint64* _tag)
1114 {
1115 	uint64 tag;
1116 	status_t error = ReadUnsignedLEB128(tag);
1117 	if (error != B_OK)
1118 		return error;
1119 
1120 	if (tag != 0) {
1121 		// get the type
1122 		uint16 type = attribute_tag_type(tag);
1123 		if (type >= B_HPKG_ATTRIBUTE_TYPE_ENUM_COUNT) {
1124 			fErrorOutput->PrintError("Error: Invalid %s section: attribute "
1125 				"type %d not supported!\n", fCurrentSection->name, type);
1126 			return B_BAD_DATA;
1127 		}
1128 
1129 		// get the ID
1130 		_id = attribute_tag_id(tag);
1131 		if (_id < B_HPKG_ATTRIBUTE_ID_ENUM_COUNT) {
1132 			if (type != kAttributeTypes[_id]) {
1133 				fErrorOutput->PrintError("Error: Invalid %s section: "
1134 					"unexpected type %d for attribute id %d (expected %d)!\n",
1135 					fCurrentSection->name, type, _id, kAttributeTypes[_id]);
1136 				return B_BAD_DATA;
1137 			}
1138 		} else if (fMinorFormatVersion <= fCurrentMinorFormatVersion) {
1139 			fErrorOutput->PrintError("Error: Invalid %s section: "
1140 				"attribute id %d not supported!\n", fCurrentSection->name, _id);
1141 			return B_BAD_DATA;
1142 		}
1143 
1144 		// get the value
1145 		error = ReadAttributeValue(type, attribute_tag_encoding(tag),
1146 			_value);
1147 		if (error != B_OK)
1148 			return error;
1149 	}
1150 
1151 	if (_hasChildren != NULL)
1152 		*_hasChildren = attribute_tag_has_children(tag);
1153 	if (_tag != NULL)
1154 		*_tag = tag;
1155 
1156 	return B_OK;
1157 }
1158 
1159 
1160 status_t
1161 ReaderImplBase::ReadAttributeValue(uint8 type, uint8 encoding,
1162 	AttributeValue& _value)
1163 {
1164 	switch (type) {
1165 		case B_HPKG_ATTRIBUTE_TYPE_INT:
1166 		case B_HPKG_ATTRIBUTE_TYPE_UINT:
1167 		{
1168 			uint64 intValue;
1169 			status_t error;
1170 
1171 			switch (encoding) {
1172 				case B_HPKG_ATTRIBUTE_ENCODING_INT_8_BIT:
1173 				{
1174 					uint8 value;
1175 					error = _Read(value);
1176 					intValue = value;
1177 					break;
1178 				}
1179 				case B_HPKG_ATTRIBUTE_ENCODING_INT_16_BIT:
1180 				{
1181 					uint16 value;
1182 					error = _Read(value);
1183 					intValue = B_BENDIAN_TO_HOST_INT16(value);
1184 					break;
1185 				}
1186 				case B_HPKG_ATTRIBUTE_ENCODING_INT_32_BIT:
1187 				{
1188 					uint32 value;
1189 					error = _Read(value);
1190 					intValue = B_BENDIAN_TO_HOST_INT32(value);
1191 					break;
1192 				}
1193 				case B_HPKG_ATTRIBUTE_ENCODING_INT_64_BIT:
1194 				{
1195 					uint64 value;
1196 					error = _Read(value);
1197 					intValue = B_BENDIAN_TO_HOST_INT64(value);
1198 					break;
1199 				}
1200 				default:
1201 				{
1202 					fErrorOutput->PrintError("Error: Invalid %s section: "
1203 						"invalid encoding %d for int value type %d\n",
1204 						fCurrentSection->name, encoding, type);
1205 					return B_BAD_VALUE;
1206 				}
1207 			}
1208 
1209 			if (error != B_OK)
1210 				return error;
1211 
1212 			if (type == B_HPKG_ATTRIBUTE_TYPE_INT)
1213 				_value.SetTo((int64)intValue);
1214 			else
1215 				_value.SetTo(intValue);
1216 
1217 			return B_OK;
1218 		}
1219 
1220 		case B_HPKG_ATTRIBUTE_TYPE_STRING:
1221 		{
1222 			if (encoding == B_HPKG_ATTRIBUTE_ENCODING_STRING_TABLE) {
1223 				uint64 index;
1224 				status_t error = ReadUnsignedLEB128(index);
1225 				if (error != B_OK)
1226 					return error;
1227 
1228 				if (index > fCurrentSection->stringsCount) {
1229 					fErrorOutput->PrintError("Error: Invalid %s section: "
1230 						"string reference (%lld) out of bounds (%lld)\n",
1231 						fCurrentSection->name, index,
1232 						fCurrentSection->stringsCount);
1233 					return B_BAD_DATA;
1234 				}
1235 
1236 				_value.SetTo(fCurrentSection->strings[index]);
1237 			} else if (encoding == B_HPKG_ATTRIBUTE_ENCODING_STRING_INLINE) {
1238 				const char* string;
1239 				status_t error = _ReadString(string);
1240 				if (error != B_OK)
1241 					return error;
1242 
1243 				_value.SetTo(string);
1244 			} else {
1245 				fErrorOutput->PrintError("Error: Invalid %s section: invalid "
1246 					"string encoding (%u)\n", fCurrentSection->name, encoding);
1247 				return B_BAD_DATA;
1248 			}
1249 
1250 			return B_OK;
1251 		}
1252 
1253 		default:
1254 			fErrorOutput->PrintError("Error: Invalid %s section: invalid "
1255 				"value type: %d\n", fCurrentSection->name, type);
1256 			return B_BAD_DATA;
1257 	}
1258 }
1259 
1260 
1261 status_t
1262 ReaderImplBase::ReadUnsignedLEB128(uint64& _value)
1263 {
1264 	uint64 result = 0;
1265 	int shift = 0;
1266 	while (true) {
1267 		uint8 byte;
1268 		status_t error = _Read(byte);
1269 		if (error != B_OK)
1270 			return error;
1271 
1272 		result |= uint64(byte & 0x7f) << shift;
1273 		if ((byte & 0x80) == 0)
1274 			break;
1275 		shift += 7;
1276 	}
1277 
1278 	_value = result;
1279 	return B_OK;
1280 }
1281 
1282 
1283 status_t
1284 ReaderImplBase::_ReadString(const char*& _string, size_t* _stringLength)
1285 {
1286 	const char* string
1287 		= (const char*)fCurrentSection->data + fCurrentSection->currentOffset;
1288 	size_t stringLength = strnlen(string,
1289 		fCurrentSection->uncompressedLength - fCurrentSection->currentOffset);
1290 
1291 	if (stringLength
1292 		== fCurrentSection->uncompressedLength
1293 			- fCurrentSection->currentOffset) {
1294 		fErrorOutput->PrintError(
1295 			"_ReadString(): string extends beyond %s end\n",
1296 			fCurrentSection->name);
1297 		return B_BAD_DATA;
1298 	}
1299 
1300 	_string = string;
1301 	if (_stringLength != NULL)
1302 		*_stringLength = stringLength;
1303 
1304 	fCurrentSection->currentOffset += stringLength + 1;
1305 	return B_OK;
1306 }
1307 
1308 
1309 status_t
1310 ReaderImplBase::_ReadSectionBuffer(void* buffer, size_t size)
1311 {
1312 	if (size > fCurrentSection->uncompressedLength
1313 			- fCurrentSection->currentOffset) {
1314 		fErrorOutput->PrintError(
1315 			"_ReadSectionBuffer(%lu): read beyond %s end\n", size,
1316 			fCurrentSection->name);
1317 		return B_BAD_DATA;
1318 	}
1319 
1320 	memcpy(buffer, fCurrentSection->data + fCurrentSection->currentOffset,
1321 		size);
1322 	fCurrentSection->currentOffset += size;
1323 	return B_OK;
1324 }
1325 
1326 
1327 status_t
1328 ReaderImplBase::ReadBuffer(off_t offset, void* buffer, size_t size)
1329 {
1330 	ssize_t bytesRead = pread(fFD, buffer, size, offset);
1331 	if (bytesRead < 0) {
1332 		fErrorOutput->PrintError("_ReadBuffer(%p, %lu) failed to read data: "
1333 			"%s\n", buffer, size, strerror(errno));
1334 		return errno;
1335 	}
1336 	if ((size_t)bytesRead != size) {
1337 		fErrorOutput->PrintError("_ReadBuffer(%p, %lu) failed to read all "
1338 			"data\n", buffer, size);
1339 		return B_ERROR;
1340 	}
1341 
1342 	return B_OK;
1343 }
1344 
1345 
1346 status_t
1347 ReaderImplBase::ReadSection(const PackageFileSection& section)
1348 {
1349 	return fHeapReader->ReadData(section.offset,
1350 		section.data, section.uncompressedLength);
1351 }
1352 
1353 
1354 }	// namespace BPrivate
1355 
1356 }	// namespace BHPKG
1357 
1358 }	// namespace BPackageKit
1359