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#ifndef _PACKAGE__HPKG__PRIVATE__READER_IMPL_BASE_H_
7#define _PACKAGE__HPKG__PRIVATE__READER_IMPL_BASE_H_
8
9
10#include <errno.h>
11#include <sys/stat.h>
12
13#include <ByteOrder.h>
14#include <DataIO.h>
15
16#include <Array.h>
17#include <util/SinglyLinkedList.h>
18
19#include <package/hpkg/ErrorOutput.h>
20#include <package/hpkg/PackageAttributeValue.h>
21#include <package/hpkg/PackageContentHandler.h>
22#include <package/hpkg/PackageInfoAttributeValue.h>
23
24
25class BCompressionAlgorithm;
26class BDecompressionParameters;
27
28
29namespace BPackageKit {
30
31namespace BHPKG {
32
33
34class BAbstractBufferedDataReader;
35class BErrorOutput;
36
37
38namespace BPrivate {
39
40
41class PackageFileHeapReader;
42
43
44struct PackageFileSection {
45	uint32			uncompressedLength;
46	uint8*			data;
47	uint64			offset;
48	uint64			currentOffset;
49	uint64			stringsLength;
50	uint64			stringsCount;
51	char**			strings;
52	const char*		name;
53
54	PackageFileSection(const char* _name)
55		:
56		data(NULL),
57		strings(NULL),
58		name(_name)
59	{
60	}
61
62	~PackageFileSection()
63	{
64		delete[] strings;
65		delete[] data;
66	}
67};
68
69
70class ReaderImplBase {
71public:
72	inline	const PackageFileSection& PackageAttributesSection() const
73									{ return fPackageAttributesSection; }
74
75protected:
76								ReaderImplBase(const char* fileType,
77									BErrorOutput* errorOutput);
78	virtual						~ReaderImplBase();
79
80			BPositionIO*		File() const;
81
82			BErrorOutput*		ErrorOutput() const;
83
84			uint16				MinorFormatVersion() const
85									{ return fMinorFormatVersion; }
86
87			uint64				UncompressedHeapSize() const;
88
89			PackageFileHeapReader* RawHeapReader() const
90									{ return fRawHeapReader; }
91			BAbstractBufferedDataReader* HeapReader() const
92									{ return fHeapReader; }
93									// equals RawHeapReader(), if uncached
94
95			BAbstractBufferedDataReader* DetachHeapReader(
96									PackageFileHeapReader*& _rawHeapReader);
97									// Detaches both raw and (if applicable)
98									// cached heap reader. The called gains
99									// ownership of both. The file may need to
100									// be set on the raw heap reader, if it
101									// shall be used after destroying this
102									// object and Init() has been called with
103									// keepFile == true.
104
105protected:
106			class AttributeHandlerContext;
107			class AttributeHandler;
108			class IgnoreAttributeHandler;
109			class PackageInfoAttributeHandlerBase;
110			class PackageVersionAttributeHandler;
111			class PackageResolvableAttributeHandler;
112			class PackageResolvableExpressionAttributeHandler;
113			class GlobalWritableFileInfoAttributeHandler;
114			class UserSettingsFileInfoAttributeHandler;
115			class UserAttributeHandler;
116			class PackageAttributeHandler;
117			class LowLevelAttributeHandler;
118
119			typedef BPackageAttributeValue AttributeValue;
120			typedef SinglyLinkedList<AttributeHandler> AttributeHandlerList;
121
122protected:
123			template<typename Header, uint32 kMagic, uint16 kVersion,
124				uint16 kMinorVersion>
125			status_t			Init(BPositionIO* file, bool keepFile,
126									Header& header, uint32 flags);
127			status_t			InitHeapReader(uint32 compression,
128									uint32 chunkSize, off_t offset,
129									uint64 compressedSize,
130									uint64 uncompressedSize);
131	virtual	status_t			CreateCachedHeapReader(
132									PackageFileHeapReader* heapReader,
133									BAbstractBufferedDataReader*&
134										_cachedReader);
135			status_t			InitSection(PackageFileSection& section,
136									uint64 endOffset, uint64 length,
137									uint64 maxSaneLength, uint64 stringsLength,
138									uint64 stringsCount);
139			status_t			PrepareSection(PackageFileSection& section);
140
141			status_t			ParseStrings();
142
143			status_t			ParsePackageAttributesSection(
144									AttributeHandlerContext* context,
145									AttributeHandler* rootAttributeHandler);
146			status_t			ParseAttributeTree(
147									AttributeHandlerContext* context,
148									bool& _sectionHandled);
149
150	virtual	status_t			ReadAttributeValue(uint8 type, uint8 encoding,
151									AttributeValue& _value);
152
153			status_t			ReadUnsignedLEB128(uint64& _value);
154
155			status_t			ReadBuffer(off_t offset, void* buffer,
156									size_t size);
157			status_t			ReadSection(const PackageFileSection& section);
158
159	inline	AttributeHandler*	CurrentAttributeHandler() const;
160	inline	void				PushAttributeHandler(
161									AttributeHandler* handler);
162	inline	AttributeHandler*	PopAttributeHandler();
163	inline	void				ClearAttributeHandlerStack();
164
165	inline	PackageFileSection*	CurrentSection();
166	inline	void				SetCurrentSection(PackageFileSection* section);
167
168protected:
169			PackageFileSection	fPackageAttributesSection;
170
171private:
172			status_t			_Init(BPositionIO* file, bool keepFile);
173
174			status_t			_ParseAttributeTree(
175									AttributeHandlerContext* context);
176
177	template<typename Type>
178	inline	status_t			_Read(Type& _value);
179
180			status_t			_ReadSectionBuffer(void* buffer, size_t size);
181
182			status_t			_ReadAttribute(uint8& _id,
183									AttributeValue& _value,
184									bool* _hasChildren = NULL,
185									uint64* _tag = NULL);
186
187			status_t			_ReadString(const char*& _string,
188									size_t* _stringLength = NULL);
189
190private:
191			const char*			fFileType;
192			BErrorOutput*		fErrorOutput;
193			BPositionIO*		fFile;
194			bool				fOwnsFile;
195			uint16				fMinorFormatVersion;
196			uint16				fCurrentMinorFormatVersion;
197
198			PackageFileHeapReader* fRawHeapReader;
199			BAbstractBufferedDataReader* fHeapReader;
200
201			PackageFileSection*	fCurrentSection;
202
203			AttributeHandlerList fAttributeHandlerStack;
204};
205
206
207// #pragma mark - attribute handlers
208
209
210class ReaderImplBase::AttributeHandlerContext {
211public:
212			BErrorOutput*			errorOutput;
213			union {
214				BPackageContentHandler*			packageContentHandler;
215				BLowLevelPackageContentHandler*	lowLevelHandler;
216			};
217			bool					hasLowLevelHandler;
218			bool					ignoreUnknownAttributes;
219
220			BHPKGPackageSectionID	section;
221
222public:
223								AttributeHandlerContext(
224									BErrorOutput* errorOutput,
225									BPackageContentHandler*
226										packageContentHandler,
227									BHPKGPackageSectionID section,
228									bool ignoreUnknownAttributes);
229								AttributeHandlerContext(
230									BErrorOutput* errorOutput,
231									BLowLevelPackageContentHandler*
232										lowLevelHandler,
233									BHPKGPackageSectionID section,
234									bool ignoreUnknownAttributes);
235
236			void				ErrorOccurred();
237};
238
239
240class ReaderImplBase::AttributeHandler
241	: public SinglyLinkedListLinkImpl<AttributeHandler> {
242public:
243	virtual						~AttributeHandler();
244
245			void				SetLevel(int level);
246	virtual	status_t			HandleAttribute(
247									AttributeHandlerContext* context, uint8 id,
248									const AttributeValue& value,
249									AttributeHandler** _handler);
250
251	virtual	status_t			NotifyDone(AttributeHandlerContext* context);
252
253	virtual	status_t			Delete(AttributeHandlerContext* context);
254
255protected:
256			int					fLevel;
257};
258
259
260class ReaderImplBase::IgnoreAttributeHandler : public AttributeHandler {
261};
262
263
264class ReaderImplBase::PackageInfoAttributeHandlerBase
265	: public AttributeHandler {
266private:
267	typedef	AttributeHandler	super;
268public:
269								PackageInfoAttributeHandlerBase(
270									BPackageInfoAttributeValue&
271										packageInfoValue);
272
273	virtual	status_t			NotifyDone(AttributeHandlerContext* context);
274
275protected:
276			BPackageInfoAttributeValue& fPackageInfoValue;
277};
278
279
280class ReaderImplBase::PackageVersionAttributeHandler
281	: public PackageInfoAttributeHandlerBase {
282private:
283	typedef	PackageInfoAttributeHandlerBase	super;
284public:
285								PackageVersionAttributeHandler(
286									BPackageInfoAttributeValue&
287										packageInfoValue,
288									BPackageVersionData& versionData,
289									bool notify);
290
291	virtual	status_t			HandleAttribute(
292									AttributeHandlerContext* context, uint8 id,
293									const AttributeValue& value,
294									AttributeHandler** _handler);
295
296	virtual	status_t			NotifyDone(AttributeHandlerContext* context);
297
298private:
299			BPackageVersionData& fPackageVersionData;
300			bool				fNotify;
301};
302
303
304class ReaderImplBase::PackageResolvableAttributeHandler
305	: public PackageInfoAttributeHandlerBase {
306private:
307	typedef	PackageInfoAttributeHandlerBase	super;
308public:
309								PackageResolvableAttributeHandler(
310									BPackageInfoAttributeValue&
311										packageInfoValue);
312
313	virtual	status_t			HandleAttribute(
314									AttributeHandlerContext* context, uint8 id,
315									const AttributeValue& value,
316									AttributeHandler** _handler);
317};
318
319
320class ReaderImplBase::PackageResolvableExpressionAttributeHandler
321	: public PackageInfoAttributeHandlerBase {
322private:
323	typedef	PackageInfoAttributeHandlerBase	super;
324public:
325								PackageResolvableExpressionAttributeHandler(
326									BPackageInfoAttributeValue&
327										packageInfoValue);
328
329	virtual	status_t			HandleAttribute(
330									AttributeHandlerContext* context, uint8 id,
331									const AttributeValue& value,
332									AttributeHandler** _handler);
333};
334
335
336class ReaderImplBase::GlobalWritableFileInfoAttributeHandler
337	: public PackageInfoAttributeHandlerBase {
338private:
339	typedef	PackageInfoAttributeHandlerBase	super;
340public:
341								GlobalWritableFileInfoAttributeHandler(
342									BPackageInfoAttributeValue&
343										packageInfoValue);
344
345	virtual	status_t			HandleAttribute(
346									AttributeHandlerContext* context, uint8 id,
347									const AttributeValue& value,
348									AttributeHandler** _handler);
349};
350
351
352class ReaderImplBase::UserSettingsFileInfoAttributeHandler
353	: public PackageInfoAttributeHandlerBase {
354private:
355	typedef	PackageInfoAttributeHandlerBase	super;
356public:
357								UserSettingsFileInfoAttributeHandler(
358									BPackageInfoAttributeValue&
359										packageInfoValue);
360
361	virtual	status_t			HandleAttribute(
362									AttributeHandlerContext* context, uint8 id,
363									const AttributeValue& value,
364									AttributeHandler** _handler);
365};
366
367
368class ReaderImplBase::UserAttributeHandler
369	: public PackageInfoAttributeHandlerBase {
370private:
371	typedef	PackageInfoAttributeHandlerBase	super;
372public:
373								UserAttributeHandler(
374									BPackageInfoAttributeValue&
375										packageInfoValue);
376
377	virtual	status_t			HandleAttribute(
378									AttributeHandlerContext* context, uint8 id,
379									const AttributeValue& value,
380									AttributeHandler** _handler);
381
382	virtual	status_t			NotifyDone(AttributeHandlerContext* context);
383
384private:
385			Array<const char*>	fGroups;
386};
387
388
389class ReaderImplBase::PackageAttributeHandler : public AttributeHandler {
390private:
391	typedef	AttributeHandler	super;
392public:
393	virtual	status_t			HandleAttribute(
394									AttributeHandlerContext* context, uint8 id,
395									const AttributeValue& value,
396									AttributeHandler** _handler);
397
398private:
399			BPackageInfoAttributeValue fPackageInfoValue;
400};
401
402
403class ReaderImplBase::LowLevelAttributeHandler : public AttributeHandler {
404private:
405	typedef	AttributeHandler	super;
406public:
407								LowLevelAttributeHandler();
408								LowLevelAttributeHandler(uint8 id,
409									const BPackageAttributeValue& value,
410									void* parentToken, void* token);
411
412	virtual	status_t			HandleAttribute(
413									AttributeHandlerContext* context, uint8 id,
414									const AttributeValue& value,
415									AttributeHandler** _handler);
416
417	virtual	status_t			NotifyDone(AttributeHandlerContext* context);
418
419private:
420			void*				fParentToken;
421			void*				fToken;
422			uint8				fID;
423			AttributeValue		fValue;
424};
425
426
427// #pragma mark - template and inline methods
428
429
430template<typename Header, uint32 kMagic, uint16 kVersion, uint16 kMinorVersion>
431status_t
432ReaderImplBase::Init(BPositionIO* file, bool keepFile, Header& header, uint32 flags)
433{
434	status_t error = _Init(file, keepFile);
435	if (error != B_OK)
436		return error;
437
438	// get the file size
439	off_t fileSize;
440	error = fFile->GetSize(&fileSize);
441	if (error != B_OK) {
442		if (error != B_NOT_SUPPORTED) {
443			ErrorOutput()->PrintError(
444				"Error: Failed to get size of %s file: %s\n",
445				fFileType, strerror(error));
446			return error;
447		}
448
449		// Might be a stream. We only use the file size for checking the total
450		// heap size, which we don't have to do.
451		fileSize = -1;
452	}
453
454	// validate file is longer than header (when not a stream)
455	if (fileSize >= 0 && fileSize < (off_t)sizeof(header)) {
456		ErrorOutput()->PrintError("Error: Invalid %s file: Length shorter than "
457			"header!\n", fFileType);
458		return B_BAD_DATA;
459	}
460
461	// read the header
462	if ((error = ReadBuffer(0, &header, sizeof(header))) != B_OK)
463		return error;
464
465	// check the header
466
467	// magic
468	if (B_BENDIAN_TO_HOST_INT32(header.magic) != kMagic) {
469		ErrorOutput()->PrintError("Error: Invalid %s file: Invalid "
470			"magic\n", fFileType);
471		return B_BAD_DATA;
472	}
473
474	// version
475	if (B_BENDIAN_TO_HOST_INT16(header.version) != kVersion) {
476		if ((flags & B_HPKG_READER_DONT_PRINT_VERSION_MISMATCH_MESSAGE) == 0) {
477			ErrorOutput()->PrintError("Error: Invalid/unsupported %s file "
478				"version (%d)\n", fFileType,
479				B_BENDIAN_TO_HOST_INT16(header.version));
480		}
481		return B_MISMATCHED_VALUES;
482	}
483
484	fMinorFormatVersion = B_BENDIAN_TO_HOST_INT16(header.minor_version);
485	fCurrentMinorFormatVersion = kMinorVersion;
486
487	// header size
488	uint64 heapOffset = B_BENDIAN_TO_HOST_INT16(header.header_size);
489	if (heapOffset < (off_t)sizeof(header)) {
490		ErrorOutput()->PrintError("Error: Invalid %s file: Invalid header "
491			"size (%" B_PRIu64 ")\n", fFileType, heapOffset);
492		return B_BAD_DATA;
493	}
494
495	// total size
496	uint64 totalSize = B_BENDIAN_TO_HOST_INT64(header.total_size);
497	if (fileSize >= 0 && totalSize != (uint64)fileSize) {
498		ErrorOutput()->PrintError("Error: Invalid %s file: Total size in "
499			"header (%" B_PRIu64 ") doesn't agree with total file size (%"
500			B_PRIdOFF ")\n", fFileType, totalSize, fileSize);
501		return B_BAD_DATA;
502	}
503
504	// heap size
505	uint64 compressedHeapSize
506		= B_BENDIAN_TO_HOST_INT64(header.heap_size_compressed);
507	if (compressedHeapSize > totalSize
508		|| heapOffset > totalSize - compressedHeapSize) {
509		ErrorOutput()->PrintError("Error: Invalid %s file: Heap size in "
510			"header (%" B_PRIu64 ") doesn't agree with total file size (%"
511			B_PRIu64 ") and heap offset (%" B_PRIu64 ")\n", fFileType,
512			compressedHeapSize, totalSize, heapOffset);
513		return B_BAD_DATA;
514	}
515
516	error = InitHeapReader(
517		B_BENDIAN_TO_HOST_INT16(header.heap_compression),
518		B_BENDIAN_TO_HOST_INT32(header.heap_chunk_size), heapOffset,
519		compressedHeapSize,
520		B_BENDIAN_TO_HOST_INT64(header.heap_size_uncompressed));
521	if (error != B_OK)
522		return error;
523
524	return B_OK;
525}
526
527
528inline BPositionIO*
529ReaderImplBase::File() const
530{
531	return fFile;
532}
533
534
535inline BErrorOutput*
536ReaderImplBase::ErrorOutput() const
537{
538	return fErrorOutput;
539}
540
541
542PackageFileSection*
543ReaderImplBase::CurrentSection()
544{
545	return fCurrentSection;
546}
547
548
549void
550ReaderImplBase::SetCurrentSection(PackageFileSection* section)
551{
552	fCurrentSection = section;
553}
554
555
556template<typename Type>
557status_t
558ReaderImplBase::_Read(Type& _value)
559{
560	return _ReadSectionBuffer(&_value, sizeof(Type));
561}
562
563
564inline ReaderImplBase::AttributeHandler*
565ReaderImplBase::CurrentAttributeHandler() const
566{
567	return fAttributeHandlerStack.Head();
568}
569
570
571inline void
572ReaderImplBase::PushAttributeHandler(AttributeHandler* handler)
573{
574	fAttributeHandlerStack.Add(handler);
575}
576
577
578inline ReaderImplBase::AttributeHandler*
579ReaderImplBase::PopAttributeHandler()
580{
581	return fAttributeHandlerStack.RemoveHead();
582}
583
584
585inline void
586ReaderImplBase::ClearAttributeHandlerStack()
587{
588	fAttributeHandlerStack.MakeEmpty();
589}
590
591
592}	// namespace BPrivate
593
594}	// namespace BHPKG
595
596}	// namespace BPackageKit
597
598
599#endif	// _PACKAGE__HPKG__PRIVATE__READER_IMPL_BASE_H_
600