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