Главная > документация, форматы файлов > Microsoft Outlook: Формат почтовой базы (.pst, или PFF — Personal Folder Files).

Microsoft Outlook: Формат почтовой базы (.pst, или PFF — Personal Folder Files).

Данный пост является частичным переводом найденной на просторах интернета спецификации формата PFF. Исходный текст был залицензирован под GPL.

Имя
Outlook.pst - формат файла MS Outlook .pst.

Сводка
outlook.pst

Обзор
Каждый элемент в .pst файле определяется двумя значениями идентификаторов ID1 и ID2. Существуют два отдельных Б-дерева с индексами ID1 и ID2. Начиная с Outlook 2003, изменён формат файла с 32-битной версии на 64-битную. Рассмотрен будет 64-битный формат.
Б-деревья далее будем обозначать "Индекс 1" и "Индекс 2".

64-битный заголовок файла
Заголовок располагается по смещению 0 в .pst файле.

смещение поле размер значение описание
0000 signature 4 байта 0x4e444221 сигнатура файла, константа
000a indexType 1 байт 0x17 тип файла .pst (0x17 - 64-битный)
0201 encryptionType 1 байт 0x00
0x01
0x02
Тип шифрования
0 — нет
1 — со сжатием
2 — стойкое
00b8 fileSize 8 байт общий размер файла
00e8 backPointer1 8 байт Обратный указатель 1
00f0 offsetIndex1 8 байт Смещение индекса 1
00d8 backPointer2 8 байт Обратный указатель 2
00e0 offsetIndex2 8 байт Смещение индекса 2

64-битный узел Индекса 1
Узлы индекса 1 являются блоками по 512 байт, формат описан ниже.

смещение поле размер значение описание
01e8 itemCount 1 байт количество элементов
01e9 maxItemCount 1 байт 0x14 максимальное количество элементов, константа
01ea itemSize 1 байт 0x18 размер элемента, константа
01eb nodeLevel 1 байт уровень элемента в дереве
01f8 backPointer 8 байт Обратный указатель

itemCount – определяет количество 24-байтовых 24 записей, которые являются активными.
nodeLevel – ненулевое для этого типа узлов. Узлы-листья имеют другой формат.
backPointer – должен совпадать с обратным указателем тройки, которая указывает на этот узел.
Каждый элемент в этом узел – это тройки (ID1, backPointer, offset), где offset (смещение) указывает на дочерний узел, значение backPointer должно совпадать с backPointer в дочернем узле, ID1 – наименьшее значение ID1 в поддереве.

64-битный лист Индекса 1
Листья имеют размер 512 байт.

смещение поле размер значение описание
01e8 itemCount 1 байт количество элементов
01e9 maxItemCount 1 байт 0x14 максимальное количество элементов, константа
01ea itemSize 1 байт 0x18 размер элемента, константа
01eb nodeLevel 1 байт 0x00 Уровень узла в дереве, для листьев 0x00, константа
01f8 backPointer 8 байт обратный указатель

itemCount – определяет количество 24-байтовых записей, которые активны. nodeLevel – равно нулю для листьев.
backPointer – должен совпадать с backPointer тройки, которая указывает на этот узел.
Каждый элемент в этом узле является тройкой (ID1, offset, size, unknown). Два младших бита ID1 – флаги. Случаев, когда бит установлен в 0 не было (но не факт, что этого не может быть). Первый бит указывает, что элемент не зашифрован. Заметьте, что ссылки на ID1 могут иметь установленный в 1 младший бит (что это означает – неизвестно), поэтому при поиске в этом дереве младший бит сбрасывается.

64-битный узел Индекса 2
Узлы этого Б-дерева имеют размер в 512 байт.

смещение поле размер значение описание
01e8 itemCount 1 байт количество элементов
01e9 maxItemCount 1 байт 0x14 максимальное количество элементов, константа
01ea itemSize 1 байт 0x18 размер элемента, константа
01eb nodeLevel 1 байт уровень узла
01f8 backPointer 8 байт обратный указатель

itemCount – определяет количество 24-байтовых записей, которые являются активными.
nodeLevel – имеет ненулевое значение для этого типа узлов. Листья имеют другой формат.
backPointer – должно совпадать c backPointer тройки, которая указывает на этот узел.
Каждый элемент в этом узле – тройка (ID2, backPointer, offset), где смещение указывает на дочерний узел в дереве. Значение backPointer должно совпадать с backPointer в дочернем узле. ID2 – наименьшее значение ID2 в поддереве.

64-битный лист Индекса 2
Лист имеет размер 512 байт.

смещение поле размер значение описание
01e8 itemCount 1 байт количество элементов
01e9 maxItemCount 1 байт 0x0f максимальное количество элементов, константа
01ea itemSize 1 байт 0x20 размер элемента, константа
01eb nodeLevel 1 байт 0x00 уровень узла, для листьев константа
01f8 backPointer 8 байт обратный указатель

itemCount – определяет количество 32-байтовых записей, которые являются активными.
nodeLevel – равно нулю для листьев.
backPointer – должен совпадать с backPointer тройки, которая указывает на этот узел.
Каждый элемент в этом узле является кортежем (ID2, DESC-ID1, LIST-ID1, PARENT-ID2).

64-битный Список Ассоциаций Элементов (тип 0x0002)
Содержит ассоциации между ID1 и ID2 для элементов, контролируемых записью.

смещение поле размер значение описание
0000 signature 2 байта 0x0002 сигнатура, константа
0002 count 2 байта количество
0004 unknown 4 байта 0 неизвестно, возможно константа
0008 id2 4 байта
000c unknown1 2 байта 0 возможно количество или размер
000e unknown2 2 байта 0 возможно количество или размер
0010 id 8 байт
0018 table2 8 байт

Связанный дескриптор (тип 0xbcec)
Содержит информацию об элементе, который может быть письмом, контактом или другим типом Outlook'а. In the above leaf node, we have a tuple of (0x21, 0x00e638, 0, 0) 0x00e638 is the ID1 of the associated descriptor, and we can lookup that ID1 value in the index1 b-tree to find the (offset,size) of the data in the .pst file. Например, в листе мы имеем кортеж (0x21, 0x00e638, 0, 0). 0x00e638 – ID1 связанного с ним дескриптора, и мы можем посмотреть значение ID1 в Б-дереве index1 чтобы найти смещение и размер этих данных в файл .pst файле.

смещение поле размер значение описание
0000 indexOffset 2 байта смещение индекса
0002 signature 2 байта 0xbcec сигнатура
0004 b5offset 4 байта ссылка на индекс

Стоит отметить, что существуют и другие форматы блока дескриптора с другими сигнатурами. indexOffset указывает позицию в блоке дескриптора, у нас есть массив из двухбайтовых целых чисел. Первое целое (0x000b) является (количество - 1) числом перекрывающихся пар. Перекрывающиеся означает, что второй элемент пары равен первому элементу следующий пары. Значения элементов пар - это смещение элементов в данном блоке в виде (начальное смещение, конечное смещение + 1).
b5offset имеет тип "ссылка на индекс". Такие ссылки имеют как минимум две разные формы и могут указывать на данные в этом же блоге или в каком-то другом. Внешние ссылки имеют установленные в единицу 4 младших бита и являются значениями ID2, которые могут быть использованы для извлечения данных. Если значение ссылки, например, равно 0x0020, то это внтрунняя ссылка, которую надо сдвинуть вправо на 4 бита чтобы чтобы получить значение 0x0002, которое является смещением, которое надо прибавить к indexOffset+2 (+2 – чтобы пропустить count).
До сих пор мы описывали внутренние ссылки на индекс, где старшие 16 бит нулевые. Это достаточно для одиночных блоков десприторов. Но в случае типа блока дескриптора 0x0101 мы получим массив подблоков. В таких ситуациях старшие 16 бит внутренней ссылки на индекс используются для выбора подблока. Каждый подблок начинается с 16 бит indexOffset'а, который указывает на count и массив из 16-битных пар целых чисел, которые являются смещением в текущем подблоке.
Наконец, мы получили смещение и размер блока "b5". Блок имеет следующий формат:

смещение поле размер значение описание
0000 signature 2 байта 0x02b5 сигнатура, константа
0002 datasize 2 байта 0x0006 размер данных, может быть 6 или 2 для 8-байтовых записей
0004 descoffset 4 байта ссылка на индекс

Каждая запись дескриптора имеет следующий формат:

смещение поле размер описание
0000 itemType 2 байта тип элемента
0002 referenceType 2 байта тип ссылки
0004 value 4 байта значение

Для некоторых типов ссылок (типы 2, 3, 0xb) значение используется напрямую, в других случаях это поле является ссылкой на индекс, который также является значением ID2 или смещением, которое надо сдвинуть вправо на 4 бита и использовать для извлечения пар из таблицы индекса чтобы найти смещение и размер жлемента в данном блоке дескриптора.

Известные типы ссылок

Известные типы ссылок:
0x0002 - Signed 16bit value (знаковое 16-битное значение)
0x0003 - Signed 32bit value (знаковое 32-битное значение)
0x0004 - 4-byte floating point (4-байтовое значение с плавающей точкой)
0x0005 - Floating point double (с плавающей точкой двойной точности)
0x0006 - Signed 64-bit int (знаковое 64-битное целое)
0x0007 - Application Time ("время приложения")
0x000A - 32-bit error value (32-битный код ошибки)
0x000B - Boolean (non-zero = true)
0x000D - Embedded Object (вложенный объект)
0x0014 - 8-byte signed integer (8-байтовое знаковое целое)
0x001E - Null terminated String (строка, заканчивающаяся \0)
0x001F - Unicode string (строка юникода)
0x0040 - Systime - Filetime structure (структура времени)
0x0048 - OLE Guid
0x0102 - Binary data (двоичные данные)
0x1003 - Array of 32bit values (массив 32-битных значений)
0x1014 - Array of 64bit values (массив 64-битных значений)
0x101E - Array of Strings (массив строк)
0x1102 - Array of Binary data (массив двоичных данных)

Следующие типы известны, но не используются в libpst:
0002 Alternate recipient allowed
0003 Extended Attributes Table
0017 Importance Level
001a IPM Context, message class
0023 Global delivery report requested
0026 Priority
0029 Read Receipt
002b Reassignment Prohibited
002e Original Sensitivity
0036 Sensitivity
0037 Email Subject
0039 Client submit time / date sent
003b Outlook Address of Sender
003f Outlook structure describing the recipient
0040 Name of the Outlook recipient structure
0041 Outlook structure describing the sender
0042 Name of the Outlook sender structure
0043 Another structure describing the recipient
0044 Name of the second recipient structure
004f Reply-To Outlook Structure
0050 Name of the Reply-To structure
0051 Outlook Name of recipient
0052 Second Outlook name of recipient
0057 My address in TO field
0058 My address in CC field
0059 Message addressed to me
0063 Response requested
0064 Sender's Address access method (SMTP, EX)
0065 Sender's Address
0070 Conversation topic, processed subject (with Fwd:, Re, ... removed)
0071 Conversation index
0072 Original display BCC
0073 Original display CC
0074 Original display TO
0075 Recipient Address Access Method (SMTP, EX)
0076 Recipient's Address
0077 Second Recipient Access Method (SMTP, EX)
0078 Second Recipient Address
007d Email Header. This is the header that was attached to the email
0c17 Reply Requested
0c19 Second sender structure
0c1a Name of second sender structure
0c1d Second outlook name of sender
0c1e Second sender access method (SMTP, EX)
0c1f Second Sender Address
0e01 Delete after submit
0e02 BCC Addresses
0e03 CC Addresses
0e04 SentTo Address
0e06 Date.
0e07 Flag bits
0x01 - Read
0x02 - Unmodified
0x04 - Submit
0x08 - Unsent
0x10 - Has Attachments
0x20 - From Me
0x40 - Associated
0x80 - Resend
0x100 - RN Pending
0x200 - NRN Pending
0e08 Message Size
0e0a Sentmail EntryID
0e1f Compressed RTF in Sync
0e20 Attachment Size
0ff9 binary record header
1000 Plain Text Email Body. Does not exist if the email doesn't have a plain text version
1006 RTF Sync Body CRC
1007 RTF Sync Body character count
1008 RTF Sync body tag
1009 RTF Compressed body
1010 RTF whitespace prefix count
1011 RTF whitespace tailing count
1013 HTML Email Body. Does not exist if the email doesn't have an HTML version
1035 Message ID
1042 In-Reply-To or Parent's Message ID
1046 Return Path
3001 Folder Name? I have seen this value used for the contacts record aswell
3002 Address Type
3003 Contact Address
3004 Comment
3007 Date item creation
3008 Date item modification
300b binary record header
35df Valid Folder Mask
35e0 binary record contains a reference to "Top of Personal Folder" item
35e2 binary record contains a reference to default outbox item
35e3 binary record contains a reference to "Deleted Items" item
35e4 binary record contains a reference to sent items folder item
35e5 binary record contains a reference to user views folder item
35e6 binary record contains a reference to common views folder item
35e7 binary record contains a reference to "Search Root" item
3602 the number of emails stored in a folder
3603 the number of unread emails in a folder
360a Has Subfolders
3613 the folder content description
3617 Associate Content count
3701 Binary Data attachment
3704 Attachment Filename
3705 Attachement method
3707 Attachment Filename long
370b Attachment Position
370e Attachment mime encoding
3710 Attachment mime Sequence
3a00 Contact's Account name
3a01 Contact Alternate Recipient
3a02 Callback telephone number
3a03 Message Conversion Prohibited
3a05 Contacts Suffix
3a06 Contacts First Name
3a07 Contacts Government ID Number
3a08 Business Telephone Number
3a09 Home Telephone Number
3a0a Contacts Initials
3a0b Keyword
3a0c Contact's Language
3a0d Contact's Location
3a0e Mail Permission
3a0f MHS Common Name
3a10 Organizational ID #
3a11 Contacts Surname
3a12 original entry id
3a13 original display name
3a14 original search key
3a15 Default Postal Address
3a16 Company Name
3a17 Job Title
3a18 Department Name
3a19 Office Location
3a1a Primary Telephone
3a1b Business Phone Number 2
3a1c Mobile Phone Number
3a1d Radio Phone Number
3a1e Car Phone Number
3a1f Other Phone Number
3a20 Transmittable Display Name
3a21 Pager Phone Number
3a22 user certificate
3a23 Primary Fax Number
3a24 Business Fax Number
3a25 Home Fax Number
3a26 Business Address Country
3a27 Business Address City
3a28 Business Address State
3a29 Business Address Street
3a2a Business Postal Code
3a2b Business PO Box
3a2c Telex Number
3a2d ISDN Number
3a2e Assistant Phone Number
3a2f Home Phone 2
3a30 Assistant's Name
3a40 Can receive Rich Text
3a41 Wedding Anniversary
3a42 Birthday
3a43 Hobbies
3a44 Middle Name
3a45 Display Name Prefix (Title)
3a46 Profession
3a47 Preferred By Name
3a48 Spouse's Name
3a49 Computer Network Name
3a4a Customer ID
3a4b TTY/TDD Phone
3a4c Ftp Site
3a4d Gender
3a4e Manager's Name
3a4f Nickname
3a50 Personal Home Page
3a51 Business Home Page
3a57 Company Main Phone
3a58 childrens names
3a59 Home Address City
3a5a Home Address Country
3a5b Home Address Postal Code
3a5c Home Address State or Province
3a5d Home Address Street
3a5e Home Address Post Office Box
3a5f Other Address City
3a60 Other Address Country
3a61 Other Address Postal Code
3a62 Other Address State
3a63 Other Address Street
3a64 Other Address Post Office box
65e3 Entry ID
67f2 Attachment ID2 value
67ff Password checksum
6f02 Secure HTML Body
6f04 Secure Text Body
7c07 Top of folders RecID
8005 Contact Fullname
801a Home Address
801b Business Address
801c Other Address
8045 Work Address Street
8046 Work Address City
8047 Work Address State
8048 Work Address Postal Code
8049 Work Address Country
804a Work Address Post Office Box
8082 Email Address 1 Transport
8083 Email Address 1 Address
8084 Email Address 1 Description
8085 Email Address 1 Record
8092 Email Address 2 Transport
8093 Email Address 2 Address
8094 Email Address 2 Description
8095 Email Address 2 Record
80a2 Email Address 3 Transport
80a3 Email Address 3 Address
80a4 Email Address 3 Description
80a5 Email Address 3 Record
80d8 Internet Free/Busy
8205 Appointment shows as
8208 Appointment Location
820d Appointment start
820e Appointment end
8214 Label for appointment
8215 All day appointment flag
8231 Recurrence type
8232 Recurrence description
8234 TimeZone of times
8235 Recurrence Start Time
8236 Recurrence End Time
8501 Reminder minutes before appointment start
8503 Reminder alarm
8516 Common Time Start
8517 Common Time End
851f Play reminder sound filename
8530 Followup String
8534 Mileage
8535 Billing Information
8554 Outlook Version
8560 Appointment Reminder Time
8700 Journal Entry Type
8706 Start Timestamp
8708 End Timestamp
8712 Journal Entry Type - duplicate?

Связанный дескриптор (тип 0x7cec)
Блоки дескриптора такого типа похожи блоки типа 0xbcec.

смещение поле размер значение описание
0000 indexOffset 2 байта смещение индекса
0002 signature 2 байта 0x7cec сигнатура, константа
0004 7coffset 4 байта ссылка на индекс

Начиная с позиции в блоке дескриптора на которую указывает indexOffset мы имеем массив двухбайтовых целых чисел. Первое число, например 0x0006, – это количество – 1 числа перекрывающихся пар. Первая пара (все значения взяты случайным образом, это не константы) – (0, 0xc), следующая – (0xc, 0x14), т.е. первое значение следующей пары равно второму предыдущей (это и означает "перекрывающиеся пары"). Значение пары означает началльное и конечное + 1 смещение элементов в данном блоке.

7coffset – ссылка на индекс. Если ссылка внутренняя – то необходимо сдвинуть её значение вправо на 4 бита и прибавить к indexOffset+2, тогда она будет указывать на первую пару (прибавляем два чтобы пропустить количество пар вначале). Теперь у нас есть смещение и размер блока "7c". Блок типа "7c" начинает с заголовка следующего формата:

смещение поле размер значение описание
0000 signature 1 байт 0x7c сигнатура, константа
0001 itemCount 1 байт соличество элементов
0002 unknown 2 байта
0004 unknown 2 байта
0006 unknown 2 байта
0008 recordSize 2 байта размер записи
000a b5Offset 4 байта ссылка на индекс
000e index2Offset 4 байта ссылка на индекс
0012 unknown 2 байта
0014 unknown 2 байта

Так мы получаем смещение и размер блока "b5", формат самого блока ниже.

смещение поле размер значение описание
0000 signature 2 байта 0x04b5 сигнатура, константа
0002 datasize 2 байта размер данных
0004 descoffset 4 байта ссылка на индекс

По ссылке decoffset мы придём к неизвестному блоку в неизученном формате. Иногда эта ссылка и ссылка index2Offset в блоке типа 7c могут быть равны нулю. Это как то связано, скорее всего, со статусом сообщения "прочтёное/новое".
К index2Offset прибавляем indexOffset + 2 и получаем указатель на пару (0xf0, 0x155), которая указывает на массив таблиц 4-байтовых целых. Далее будем называть это таблицы IND2. Размер каждой из этих таблиц указан в поле recordSize заголовка блока 7c. Количество таблиц указано в recordCount в блоке b5.

Теперь оставшиеся данные в блоке 7c после заголовка начинаются со смещения 0x2a. Далее идёт itemCount (в смысле itemCount - количество элементов) 8-байтовых элементов следующего формата:

смещение поле размер
0000 referenceType 2 байта
0002 itemType 2 байта
0004 ind2Offset 2 байта
0006 size 1 байт
0007 unknown 1 байт

ind2Offset - смещение в текущей IND2 таблице. Если оно указывает на 4х байтовое целое значение, тогда мы извлекаем такую же тройку (тип элемента, тип ссылки, значение), как и в блоках дескриптора типа 0xbcec. Иначе, значения используются напрямую. Такие 8-байтовые дескрипторы обрабатываются recorCount раз, какждый раз используя следующую таблицу IND2. Типы элемента и ссылки такие же, как и описанные выше для блока дескриптора типа 0xbcec.

Связаный дескриптор (тип 0x0101)
Такой блок дескриптора содержит список значений ID1.

смещение поле размер значение описание
0000 signature 2 байта 0x0101 сигнатура, константа
0002 count 2 байта количество
0004 totalLenght 4 байта общая длина
0008 id1 8 байта
0010 id1 8 байта

Если у вас возникли какие-либо вопросы, предложения и т.п. - как обычно, в комментарии.

Ссылки к статье:
http://www.five-ten-sg.com/libpst/rn01re06.html - Оригинал, рассматривается обе версии формата.

Пожалуйста, оцените полезность и качество данной статьи. Одна звезда - плохо, 5 - хорошо.
1/5. Мы будем признательны, если вы напишете комментарий с причиной низкой оценки.2/5. Мы будем признательны, если вы напишете комментарий с причиной низкой оценки.3/5. Мы будем признательны, если вы напишете комментарий с причиной низкой оценки.4/5.5/5. (Еще не оценили)
Загрузка...
  1. Пока что нет комментариев.
  1. Пока что нет уведомлений.