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