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