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
AttributeHandlerContext(BErrorOutput * errorOutput,BPackageContentHandler * packageContentHandler,BHPKGPackageSectionID section)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
AttributeHandlerContext(BErrorOutput * errorOutput,BLowLevelPackageContentHandler * lowLevelHandler,BHPKGPackageSectionID section)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
ErrorOccurred()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
~AttributeHandler()81 ReaderImplBase::AttributeHandler::~AttributeHandler()
82 {
83 }
84
85
86 void
SetLevel(int level)87 ReaderImplBase::AttributeHandler::SetLevel(int level)
88 {
89 fLevel = level;
90 }
91
92
93 status_t
HandleAttribute(AttributeHandlerContext * context,uint8 id,const AttributeValue & value,AttributeHandler ** _handler)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
Delete(AttributeHandlerContext * context)103 ReaderImplBase::AttributeHandler::Delete(AttributeHandlerContext* context)
104 {
105 delete this;
106 return B_OK;
107 }
108
109
110 // #pragma mark - PackageVersionAttributeHandler
111
112
PackageVersionAttributeHandler(BPackageInfoAttributeValue & packageInfoValue,BPackageVersionData & versionData,bool notify)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
HandleAttribute(AttributeHandlerContext * context,uint8 id,const AttributeValue & value,AttributeHandler ** _handler)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
Delete(AttributeHandlerContext * context)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
PackageResolvableAttributeHandler(BPackageInfoAttributeValue & packageInfoValue)178 ::PackageResolvableAttributeHandler(
179 BPackageInfoAttributeValue& packageInfoValue)
180 :
181 fPackageInfoValue(packageInfoValue)
182 {
183 }
184
185
186 status_t
HandleAttribute(AttributeHandlerContext * context,uint8 id,const AttributeValue & value,AttributeHandler ** _handler)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
Delete(AttributeHandlerContext * context)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
PackageResolvableExpressionAttributeHandler(BPackageInfoAttributeValue & packageInfoValue)250 ::PackageResolvableExpressionAttributeHandler(
251 BPackageInfoAttributeValue& packageInfoValue)
252 :
253 fPackageInfoValue(packageInfoValue)
254 {
255 }
256
257
258 status_t
HandleAttribute(AttributeHandlerContext * context,uint8 id,const AttributeValue & value,AttributeHandler ** _handler)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
Delete(AttributeHandlerContext * context)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
HandleAttribute(AttributeHandlerContext * context,uint8 id,const AttributeValue & value,AttributeHandler ** _handler)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
LowLevelAttributeHandler()475 ReaderImplBase::LowLevelAttributeHandler::LowLevelAttributeHandler()
476 :
477 fParentToken(NULL),
478 fToken(NULL),
479 fID(B_HPKG_ATTRIBUTE_ID_ENUM_COUNT)
480 {
481 }
482
483
LowLevelAttributeHandler(uint8 id,const BPackageAttributeValue & value,void * parentToken,void * token)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
HandleAttribute(AttributeHandlerContext * context,uint8 id,const AttributeValue & value,AttributeHandler ** _handler)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
Delete(AttributeHandlerContext * context)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
ReaderImplBase(BErrorOutput * errorOutput)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
~ReaderImplBase()556 ReaderImplBase::~ReaderImplBase()
557 {
558 if (fOwnsFD && fFD >= 0)
559 close(fFD);
560
561 delete[] fScratchBuffer;
562 }
563
564
565 status_t
Init(int fd,bool keepFD)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*
CheckCompression(const SectionInfo & section) const584 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
ParseStrings()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
ParsePackageAttributesSection(AttributeHandlerContext * context,AttributeHandler * rootAttributeHandler)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
ParseAttributeTree(AttributeHandlerContext * context,bool & _sectionHandled)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
_ParseAttributeTree(AttributeHandlerContext * context)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
_ReadAttribute(uint8 & _id,AttributeValue & _value,bool * _hasChildren,uint64 * _tag)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
ReadAttributeValue(uint8 type,uint8 encoding,AttributeValue & _value)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
ReadUnsignedLEB128(uint64 & _value)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
_ReadString(const char * & _string,size_t * _stringLength)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
_ReadSectionBuffer(void * buffer,size_t size)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
ReadBuffer(off_t offset,void * buffer,size_t size)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
ReadCompressedBuffer(const SectionInfo & section)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