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