/*
 * The internal definitions
 *
 * Copyright (C) 2008-2018, Joachim Metz <joachim.metz@gmail.com>
 *
 * Refer to AUTHORS for acknowledgements.
 *
 * This software is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this software.  If not, see <http://www.gnu.org/licenses/>.
 */

#if !defined( _LIBPFF_INTERNAL_DEFINITIONS_H )
#define _LIBPFF_INTERNAL_DEFINITIONS_H

#include <common.h>
#include <byte_stream.h>

/* The endian definitions
 */
#define LIBPFF_ENDIAN_BIG						_BYTE_STREAM_ENDIAN_BIG
#define LIBPFF_ENDIAN_LITTLE						_BYTE_STREAM_ENDIAN_LITTLE

/* Define HAVE_LOCAL_LIBPFF for local use of libpff
 */
#if !defined( HAVE_LOCAL_LIBPFF )
#include <libpff/definitions.h>

/* The definitions in <libpff/definitions.h> are copied here
 * for local use of libpff
 */
#else
#define LIBPFF_VERSION							20180714

/* The version string
 */
#define LIBPFF_VERSION_STRING						"20180714"

/* The file access flags
 * bit 1        set to 1 for read access
 * bit 2        set to 1 for write access
 * bit 3-8      not used
 */
enum LIBPFF_ACCESS_FLAGS
{
	LIBPFF_ACCESS_FLAG_READ						= 0x01,
/* Reserved: not supported yet */
	LIBPFF_ACCESS_FLAG_WRITE					= 0x02
};

/* The file access macros
 */
#define LIBPFF_OPEN_READ						( LIBPFF_ACCESS_FLAG_READ )
/* Reserved: not supported yet */
#define LIBPFF_OPEN_WRITE						( LIBPFF_ACCESS_FLAG_WRITE )
/* Reserved: not supported yet */
#define LIBPFF_OPEN_READ_WRITE						( LIBPFF_ACCESS_FLAG_READ | LIBPFF_ACCESS_FLAG_WRITE )

/* The recovery flags
 */
enum LIBPFF_RECOVERY_FLAGS
{
	LIBPFF_RECOVERY_FLAG_IGNORE_ALLOCATION_DATA			= 0x01,
	LIBPFF_RECOVERY_FLAG_SCAN_FOR_FRAGMENTS				= 0x02
};

/* The file types
 */
enum LIBPFF_FILE_TYPES
{
	LIBPFF_FILE_TYPE_32BIT						= 32,
	LIBPFF_FILE_TYPE_64BIT						= 64,
	LIBPFF_FILE_TYPE_64BIT_4K_PAGE					= 65
};

/* The file content types
 */
enum LIBPFF_FILE_CONTENT_TYPES
{
	LIBPFF_FILE_CONTENT_TYPE_PAB					= (int) 'a',
	LIBPFF_FILE_CONTENT_TYPE_PST					= (int) 'p',
	LIBPFF_FILE_CONTENT_TYPE_OST					= (int) 'o'
};

/* The encryption types
 */
enum LIBPFF_ENCRYPTION_TYPES
{
	LIBPFF_ENCRYPTION_TYPE_NONE					= 0,
	LIBPFF_ENCRYPTION_TYPE_COMPRESSIBLE				= 1,
	LIBPFF_ENCRYPTION_TYPE_HIGH					= 2
};

/* The item types
 * These item types partially map to the message classes
 * LIBPFF_ITEM_TYPE_UNDEFINED		(initialization value)
 * LIBPFF_ITEM_TYPE_ACTIVITY		IPM.Activity
 * LIBPFF_ITEM_TYPE_APPOINTMENT		IPM.Appointment
 * LIBPFF_ITEM_TYPE_ATTACHMENT		(attachment)
 * LIBPFF_ITEM_TYPE_ATTACHMENTS		(attachments)
 * LIBPFF_ITEM_TYPE_COMMON		IPM
 * LIBPFF_ITEM_TYPE_CONFIGURATION	IPM.Configuration.*
 * LIBPFF_ITEM_TYPE_CONFLICT_MESSAGE    IPM.Conflict.Message
 * LIBPFF_ITEM_TYPE_CONTACT		IPM.Contact
 * LIBPFF_ITEM_TYPE_DISTRIBUTION_LIST	IPM.DistList
 * LIBPFF_ITEM_TYPE_DOCUMENT		IPM.Document.*
 * LIBPFF_ITEM_TYPE_EMAIL		IPM.Note, REPORT.IPM.Note.*
 * LIBPFF_ITEM_TYPE_EMAIL_SMIME		IPM.Note.SMIME.*
 * LIBPFF_ITEM_TYPE_FAX			IPM.FAX, IPM.Note.Fax
 * LIBPFF_ITEM_TYPE_FOLDER		(folder/container)
 * LIBPFF_ITEM_TYPE_MEETING		IPM.Schedule.Meeting
 * LIBPFF_ITEM_TYPE_MMS			IPM.Note.Mobile.MMS
 * LIBPFF_ITEM_TYPE_NOTE		IPM.StickyNote
 * LIBPFF_ITEM_TYPE_POSTING_NOTE	IPM.Post
 * LIBPFF_ITEM_TYPE_RECIPIENTS          (recipients)
 * LIBPFF_ITEM_TYPE_RSS_FEED		IPM.Post.RSS
 * LIBPFF_ITEM_TYPE_SHARING		IPM.Sharing.*
 * LIBPFF_ITEM_TYPE_SMS			IPM.Note.Mobile.SMS
 * LIBPFF_ITEM_TYPE_TASK		IPM.Task
 * LIBPFF_ITEM_TYPE_TASK_REQUEST	IPM.TaskRequest.*
 * LIBPFF_ITEM_TYPE_VOICEMAIL		IPM.Note.Voicemail
 * LIBPFF_ITEM_TYPE_UNKNOWN		(unknown item type, used in folder content type)
 *
 * Unsupported:
 * IPM.Post
 */
enum LIBPFF_ITEM_TYPES
{
	LIBPFF_ITEM_TYPE_UNDEFINED,
	LIBPFF_ITEM_TYPE_ACTIVITY,
	LIBPFF_ITEM_TYPE_APPOINTMENT,
	LIBPFF_ITEM_TYPE_ATTACHMENT,
	LIBPFF_ITEM_TYPE_ATTACHMENTS,
	LIBPFF_ITEM_TYPE_COMMON,
	LIBPFF_ITEM_TYPE_CONFIGURATION,
	LIBPFF_ITEM_TYPE_CONFLICT_MESSAGE,
	LIBPFF_ITEM_TYPE_CONTACT,
	LIBPFF_ITEM_TYPE_DISTRIBUTION_LIST,
	LIBPFF_ITEM_TYPE_DOCUMENT,
	LIBPFF_ITEM_TYPE_EMAIL,
	LIBPFF_ITEM_TYPE_EMAIL_SMIME,
	LIBPFF_ITEM_TYPE_FAX,
	LIBPFF_ITEM_TYPE_FOLDER,
	LIBPFF_ITEM_TYPE_MEETING,
	LIBPFF_ITEM_TYPE_MMS,
	LIBPFF_ITEM_TYPE_NOTE,
	LIBPFF_ITEM_TYPE_POSTING_NOTE,
	LIBPFF_ITEM_TYPE_RECIPIENTS,
	LIBPFF_ITEM_TYPE_RSS_FEED,
	LIBPFF_ITEM_TYPE_SHARING,
	LIBPFF_ITEM_TYPE_SMS,
	LIBPFF_ITEM_TYPE_SUB_ASSOCIATED_CONTENTS,
	LIBPFF_ITEM_TYPE_SUB_FOLDERS,
	LIBPFF_ITEM_TYPE_SUB_MESSAGES,
	LIBPFF_ITEM_TYPE_TASK,
	LIBPFF_ITEM_TYPE_TASK_REQUEST,
	LIBPFF_ITEM_TYPE_VOICEMAIL,
	LIBPFF_ITEM_TYPE_UNKNOWN
};

/* The attachment types
 */
enum LIBPFF_ATTACHMENT_TYPES
{
	LIBPFF_ATTACHMENT_TYPE_UNDEFINED				= 0,
	LIBPFF_ATTACHMENT_TYPE_DATA					= (int) 'd',
	LIBPFF_ATTACHMENT_TYPE_ITEM					= (int) 'i',
	LIBPFF_ATTACHMENT_TYPE_REFERENCE				= (int) 'r'
};

/* The unallocated block type
 */
enum LIBPFF_UNALLOCATED_BLOCK_TYPES
{
	LIBPFF_UNALLOCATED_BLOCK_TYPE_DATA				= (int) 'd',
	LIBPFF_UNALLOCATED_BLOCK_TYPE_PAGE				= (int) 'p'
};

/* The name to id map entry types
 */
enum LIBPFF_NAME_TO_ID_MAP_ENTRY_TYPES
{
	LIBPFF_NAME_TO_ID_MAP_ENTRY_TYPE_NUMERIC			= (int) 'n',
	LIBPFF_NAME_TO_ID_MAP_ENTRY_TYPE_STRING				= (int) 's'
};

/* The entry value flags
 */
enum LIBPFF_ENTRY_VALUE_FLAGS
{
	LIBPFF_ENTRY_VALUE_FLAG_MATCH_ANY_VALUE_TYPE			= 0x01,
	LIBPFF_ENTRY_VALUE_FLAG_IGNORE_NAME_TO_ID_MAP			= 0x02
};

#endif /* !defined( HAVE_LOCAL_LIBPFF ) */

/* The allocation table types
 */
enum LIBPFF_ALLOCATION_TABLE_TYPES
{
	LIBPFF_ALLOCATION_TABLE_TYPE_PAGE				= 0x83,
	LIBPFF_ALLOCATION_TABLE_TYPE_DATA				= 0x84
};

/* The free map types
 */
enum LIBPFF_FREE_MAP_TYPES
{
	LIBPFF_FREE_MAP_TYPE_PAGE					= 0x82,
	LIBPFF_FREE_MAP_TYPE_DATA					= 0x85
};

/* The index types
 */
enum LIBPFF_INDEX_TYPES
{
	LIBPFF_INDEX_TYPE_OFFSET					= 0x80,
	LIBPFF_INDEX_TYPE_DESCRIPTOR					= 0x81
};

#define LIBPFF_INDEX_NODE_LEVEL_LEAF					0x00

#define LIBPFF_LOCAL_DESCRIPTOR_NODE_LEVEL_LEAF				0x00

/* The node identifier type
 * Stored in the 5 LSB of the descriptor identifier
 */
enum LIBPFF_NODE_IDENTIFIER_TYPES
{
	LIBPFF_NODE_IDENTIFIER_TYPE_TABLE_VALUE				= 0x00,
	LIBPFF_NODE_IDENTIFIER_TYPE_INTERNAL				= 0x01,
	LIBPFF_NODE_IDENTIFIER_TYPE_FOLDER				= 0x02,
	LIBPFF_NODE_IDENTIFIER_TYPE_SEARCH_FOLDER			= 0x03,
	LIBPFF_NODE_IDENTIFIER_TYPE_MESSAGE				= 0x04,
	LIBPFF_NODE_IDENTIFIER_TYPE_ATTACHMENT				= 0x05,
	LIBPFF_NODE_IDENTIFIER_TYPE_SEARCH_UPDATE_QUEUE			= 0x06,
	LIBPFF_NODE_IDENTIFIER_TYPE_SEARCH_CRITERIA_OBJECT		= 0x07,
	LIBPFF_NODE_IDENTIFIER_TYPE_ASSOCIATED_CONTENT			= 0x08,

	LIBPFF_NODE_IDENTIFIER_TYPE_CONTENTS_TABLE_INDEX		= 0x0a,
	LIBPFF_NODE_IDENTIFIER_TYPE_INBOX				= 0x0b,
	LIBPFF_NODE_IDENTIFIER_TYPE_OUTBOX				= 0x0c,
	LIBPFF_NODE_IDENTIFIER_TYPE_SUB_FOLDERS				= 0x0d,
	LIBPFF_NODE_IDENTIFIER_TYPE_SUB_MESSAGES			= 0x0e,
	LIBPFF_NODE_IDENTIFIER_TYPE_SUB_ASSOCIATED_CONTENTS		= 0x0f,
	LIBPFF_NODE_IDENTIFIER_TYPE_SEARCH_CONTENTS_TABLE		= 0x10,
	LIBPFF_NODE_IDENTIFIER_TYPE_ATTACHMENTS				= 0x11,
	LIBPFF_NODE_IDENTIFIER_TYPE_RECIPIENTS				= 0x12,
	LIBPFF_NODE_IDENTIFIER_TYPE_SEARCH_TABLE			= 0x13,

	LIBPFF_NODE_IDENTIFIER_TYPE_UNKNOWN_1718			= 0x16,
	LIBPFF_NODE_IDENTIFIER_TYPE_UNKNOWN_1751			= 0x17,
	LIBPFF_NODE_IDENTIFIER_TYPE_UNKNOWN_1784			= 0x18,

	LIBPFF_NODE_IDENTIFIER_TYPE_LOCAL_DESCRIPTOR_VALUE		= 0x1f
};

/* Predefined descriptor identifiers
 */
enum LIBPFF_DESCRIPTOR_IDENTIFIERS
{
	LIBPFF_DESCRIPTOR_IDENTIFIER_MESSAGE_STORE			= 0x0021,
	LIBPFF_DESCRIPTOR_IDENTIFIER_NAME_TO_ID_MAP			= 0x0061,
	LIBPFF_DESCRIPTOR_IDENTIFIER_FOLDER_TEMPLATE			= 0x00a1,
	LIBPFF_DESCRIPTOR_IDENTIFIER_SEARCH_FOLDER_TEMPLATE		= 0x00c1,
	LIBPFF_DESCRIPTOR_IDENTIFIER_ROOT_FOLDER			= 0x0122,
	LIBPFF_DESCRIPTOR_IDENTIFIER_SEARCH_MANAGEMENT_QUEUE		= 0x01e1,
	LIBPFF_DESCRIPTOR_IDENTIFIER_SEARCH_ACTIVITY_LIST		= 0x0201,
	LIBPFF_DESCRIPTOR_IDENTIFIER_UNKNOWN_RESERVED1			= 0x0241,
	LIBPFF_DESCRIPTOR_IDENTIFIER_SEARCH_GATHERER_QUEUE		= 0x0281,
	LIBPFF_DESCRIPTOR_IDENTIFIER_SEARCH_GATHERER_DESCRIPTOR		= 0x02a1,
	LIBPFF_DESCRIPTOR_IDENTIFIER_UNKNOWN_RESERVED2			= 0x02e1,
	LIBPFF_DESCRIPTOR_IDENTIFIER_UNKNOWN_RESERVED3			= 0x0301,
	LIBPFF_DESCRIPTOR_IDENTIFIER_SEARCH_GATHERER_FOLDER_QUEUE	= 0x0321,
	LIBPFF_DESCRIPTOR_IDENTIFIER_UNKNOWN_2049			= 0x0801,
	LIBPFF_DESCRIPTOR_IDENTIFIER_UNKNOWN_2081			= 0x0821,
	LIBPFF_DESCRIPTOR_IDENTIFIER_UNKNOWN_2113			= 0x0841,
	LIBPFF_DESCRIPTOR_IDENTIFIER_UNKNOWN_3073			= 0x0c01,
};

/* Predefined local descriptor identifiers
 */
enum LIBPFF_LOCAL_DESCRIPTOR_IDENTIFIERS
{
	LIBPFF_LOCAL_DESCRIPTOR_IDENTIFIER_ATTACHMENTS			= 0x0671,
	LIBPFF_LOCAL_DESCRIPTOR_IDENTIFIER_RECIPIENTS			= 0x0692,
	LIBPFF_LOCAL_DESCRIPTOR_IDENTIFIER_UNKNOWN_1718			= 0x06b6,
	LIBPFF_LOCAL_DESCRIPTOR_IDENTIFIER_UNKNOWN_1753			= 0x06d9,
	LIBPFF_LOCAL_DESCRIPTOR_IDENTIFIER_UNKNOWN_1781			= 0x06f5,
};

/* The compression methods definitions
 */
enum LIBPFF_COMPRESSION_METHODS
{
	LIBPFF_COMPRESSION_METHOD_NONE					= 0,
	LIBPFF_COMPRESSION_METHOD_DEFLATE				= 1,
};

/* The block data flags definitions
 */
enum LIBPFF_DATA_BLOCK_FLAGS
{
	LIBPFF_DATA_BLOCK_FLAG_COMPRESSED				= 0x01,
	LIBPFF_DATA_BLOCK_FLAG_VALIDATED				= 0x02,
	LIBPFF_DATA_BLOCK_FLAG_DECRYPTION_FORCED			= 0x04,

	LIBPFF_DATA_BLOCK_FLAG_CRC_MISMATCH				= 0x10,
	LIBPFF_DATA_BLOCK_FLAG_SIZE_MISMATCH				= 0x20,
	LIBPFF_DATA_BLOCK_FLAG_IDENTIFIER_MISMATCH			= 0x40,
};

/* The data array flags
 */
enum LIBPFF_DATA_ARRAY_FLAGS
{
	LIBPFF_DATA_ARRAY_FLAG_DECRYPTION_FORCED			= 0x02
};

/* Flags for the data_array_read_segment function
 */
enum LIBPFF_READ_FLAGS
{
	LIBPFF_READ_FLAG_IGNORE_FORCE_DECRYPTION			= 0x02
};

/* The mask for the (file) offset index identifier
 * The lower order bit of the (file) offset index identifier is used for other purposes
 * and needs to be excluded when the identifier is searched in the index
 */
#define LIBPFF_OFFSET_INDEX_IDENTIFIER_MASK				0xfffffffffffffffeULL

/* The 2nd LSB of the (file) offset index identifier is used to flag
 * if the block is intended for internal use (contains a data array or local descriptors)
 * or external use (contains raw data or a table)
 */
#define LIBPFF_OFFSET_INDEX_IDENTIFIER_FLAG_INTERNAL			0x0000000000000002ULL

/* The item flags
 */
enum LIBPFF_ITEM_FLAGS
{
	LIBPFF_ITEM_FLAG_MANAGED_ITEM_TREE_NODE				= 0x02,
};

#define LIBPFF_ITEM_FLAGS_DEFAULT					0

enum LIBPFF_RECORD_ENTRY_IDENTIFIER_FORMATS
{
	/* The entry identifier consists of a MAPI property type
	 * (entry type, value type)
	 */
	LIBPFF_RECORD_ENTRY_IDENTIFIER_FORMAT_MAPI_PROPERTY		= 1,

	/* The entry identifier consists of a GUID
	 */
	LIBPFF_RECORD_ENTRY_IDENTIFIER_FORMAT_GUID			= 2,

	/* The entry identifier consists of a PRQ_ID_SECURE4 value
	 * the PRQ_ID_SECURE4 value is a yet unknown 10-byte value
	 */
	LIBPFF_RECORD_ENTRY_IDENTIFIER_FORMAT_SECURE4			= 3
};

enum LIBPFF_RECORD_ENTRY_FLAGS
{
	/* The data descriptor could not be read
	 */
	LIBPFF_RECORD_ENTRY_FLAG_MISSING_DATA_DESCRIPTOR		= 0x01
};

enum LIBPFF_TABLE_FLAGS
{
	/* The data of one or more recrord entries could not be read
	 */
	LIBPFF_TABLE_FLAG_MISSING_RECORD_ENTRY_DATA			= 0x01
};

/* The IO handle flags
 */
enum LIBPFF_IO_HANDLE_FLAGS
{
	/* The file is corrupted
	 */
	LIBPFF_IO_HANDLE_FLAG_IS_CORRUPTED				= 0x01
};

#define LIBPFF_ENTRY_TYPE_NAME_TO_ID_MAP_CLASS_IDENTIFIERS		0x0002
#define LIBPFF_ENTRY_TYPE_NAME_TO_ID_MAP_ENTRIES			0x0003
#define LIBPFF_ENTRY_TYPE_NAME_TO_ID_MAP_STRINGS			0x0004

/* The name to ID map entry flags
 */
enum LIBPFF_NAME_TO_ID_MAP_ENTRY_FLAGS
{
	/* The key item is corrupted
	 */
	LIBPFF_NAME_TO_ID_MAP_ENTRY_FLAG_IS_CORRUPTED			= 0x01
};

/* The virtual index tree root offset definitions
 */
#define LIBPFF_DESCRIPTOR_INDEX_TREE_ROOT_OFFSET			1
#define LIBPFF_OFFSETS_INDEX_TREE_ROOT_OFFSET				2
#define LIBPFF_RECOVERED_DESCRIPTOR_INDEX_TREE_ROOT_OFFSET		3
#define LIBPFF_RECOVERED_OFFSETS_INDEX_TREE_ROOT_OFFSET			4

/* The maximum number of cache entries defintions
 */
#define LIBPFF_MAXIMUM_CACHE_ENTRIES_INDEX_NODES			16384
#define LIBPFF_MAXIMUM_CACHE_ENTRIES_DESCRIPTOR_INDEX_VALUES		8192 - 3
#define LIBPFF_MAXIMUM_CACHE_ENTRIES_OFFSET_INDEX_VALUES		32768 - 3
#define LIBPFF_MAXIMUM_CACHE_ENTRIES_LOCAL_DESCRIPTORS_NODES		256
#define LIBPFF_MAXIMUM_CACHE_ENTRIES_LOCAL_DESCRIPTORS_VALUES		128 - 3
#define LIBPFF_MAXIMUM_CACHE_ENTRIES_DATA_ARRAY				8
#define LIBPFF_MAXIMUM_CACHE_ENTRIES_DATA_BLOCK				1
#define LIBPFF_MAXIMUM_CACHE_ENTRIES_ITEM				8

/* The descriptor data stream data handle flags
 */
enum LIBPFF_DESCRIPTOR_DATA_STREAM_DATA_HANDLE_FLAGS
{
	LIBPFF_DESCRIPTOR_DATA_STREAM_DATA_HANDLE_FLAG_NON_MANAGED	= 0,
	LIBPFF_DESCRIPTOR_DATA_STREAM_DATA_HANDLE_FLAG_MANAGED		= 1
};

#endif /* !defined( _LIBPFF_INTERNAL_DEFINITIONS_H ) */

