Внутри файлов PDF: Полный структурный анализ.
Переносимый формат документов (PDF) стал де-факто стандартом для обмена и архивирования документов. Понимание его внутренней структуры необходимо разработчикам, системным администраторам и всем, кто занимается процессами обработки документов. Это подробное руководство исследует сложную структуру и содержимое файлов PDF, рассматривая их четыре основных раздела и детальный синтаксис объектов, составляющих каждый компонент.
Структура файла PDF: Четыре основных компонента.
Каждый допустимый файл PDF следует строгой архитектурной схеме, состоящей из четырех основных частей, расположенных в определенном последовательном порядке. Эти компоненты работают вместе, создавая формат, который является одновременно структурированным и высокоэффективным для произвольного доступа.
- Заголовок – Определяет номер версии PDF и его двоичную природу.
- Основной текст – Содержит все объекты документа, включая страницы, шрифты, изображения и графический контент.
- Таблица перекрестных ссылок. – Предоставляет точное сопоставление смещений байтов для произвольного доступа к объектам.
- Прицеп. Содержит важные метаданные и указатели навигации.
Разбор полного PDF-файла: пример "Hello, World".
Чтобы понять, как эти компоненты работают вместе, давайте рассмотрим полный, минимальный PDF-файл, который отображает текст "Hello, World!". Этот пример демонстрирует каждый важный элемент структуры PDF.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
%PDF-1.0 % Header starts here %âãÏÓ 1 0 obj % Body starts here << /Kids [2 0 R] /Count 1 /Type /Pages >> endobj 2 0 obj << /Rotate 0 /Parent 1 0 R /Resources 3 0 R /MediaBox [0 0 612 792] /Contents [4 0 R] /Type /Page >> endobj 3 0 obj << /Font << /F0 << /BaseFont /Times-Italic /Subtype /Type1 /Type /Font >> >> >> endobj 4 0 obj << /Length 65 >> stream 1. 0. 0. 1. 50. 700. cm BT /F0 36. Tf (Hello, World!) Tj ET endstream endobj 5 0 obj << /Pages 1 0 R /Type /Catalog >> endobj xref % Cross-reference table starts here 0 6 0000000000 65535 f 0000000015 00000 n 0000000074 00000 n 0000000192 00000 n 0000000291 00000 n 0000000409 00000 n trailer % Trailer starts here << /Root 5 0 R /Size 6 >> startxref 459 %%EOF |
💡 Понимание графов объектов PDF.
Объекты PDF образуют структуру направленного графа, где узлы - это объекты PDF, а ссылки - это непрямые ссылки. Это представление графа позволяет эффективно осуществлять произвольный доступ к содержимому без необходимости последовательной обработки файла. Каталог документа (объект 5) служит корневым узлом, соединяющимся с деревом страниц (объект 1), который ссылается на отдельные страницы и их ресурсы.
Заголовок: контроль версий и идентификация двоичного файла.
Заголовок PDF выполняет две критически важные функции, которые обеспечивают правильную обработку файла в различных системах и приложениях:
|
1 2 |
%PDF-1.0 %âãÏÓ |
Первая строка указывает версию PDF (1.0 в этом примере). PDF обеспечивает отличную обратную совместимость, что означает, что новые программы просмотра могут беспрепятственно обрабатывать более старые версии. Он также обеспечивает некоторую степень прямой совместимости, поскольку большинство приложений PDF пытаются читать файлы независимо от указанного номера версии.
Вторая строка содержит двоичные символы с кодами ASCII, превышающими 127. Это очень важно, потому что файлы PDF почти всегда содержат двоичные данные, которые могут быть повреждены, если символы конца строки изменяются во время передачи файла (например, при передаче через FTP в текстовом режиме). Эти символы с высокими значениями ASCII помогают устаревшим программам передачи файлов определить, что файл является двоичным, предотвращая автоматическую конвертацию символов конца строки, которая может повредить документ.
Знак процента (%) указывает на строку комментария в синтаксисе PDF, а конкретные символы âãÏÓ являются произвольными байтами, превышающими ASCII 127, и служат двоичным маркером для протоколов передачи данных.
Тело: Здесь находится весь контент.
Файл содержит основное содержимое, представляющее собой последовательность объектов. Каждый объект имеет строгую синтаксическую структуру:
|
1 2 3 |
[object_number] [generation_number] obj [object_content] endobj |
Каждый объект начинается с номера объекта, номера поколения и далее... obj keyword на одной строке, за которой следует содержимое объекта, и заканчивается endobj ключевое слово. Номер генерации позволяет повторно использовать объекты при обновлении записей перекрестных ссылок, но для большинства целей он остается равным нулю.
Для примера, рассмотрим объект 1 из нашего образца:
|
1 2 3 4 5 6 7 |
1 0 obj << /Kids [2 0 R] /Count 1 /Type /Pages >> endobj |
Этот объект (номер 1, поколение 0) содержит словарь, определяющий структуру страниц. /Type /Pages Эта запись идентифицирует его как узел дерева страниц. /Count 1 Она указывает на то, что он содержит одну страницу. /Kids [2 0 R] Она ссылается на объект 2 как на дочернюю страницу.
Таблица перекрестных ссылок: Основа навигации.
Таблица перекрестных ссылок представляет собой самую гениальную функцию PDF для оптимизации производительности. Она обеспечивает прямое сопоставление между номерами объектов и их байтовыми позициями в файле, что позволяет осуществлять произвольный доступ без последовательного сканирования.
|
1 2 3 4 5 6 7 8 |
xref 0 6 % Six entries starting at object 0 0000000000 65535 f % Special entry for free objects 0000000015 00000 n % Object 1 at byte offset 15 0000000074 00000 n % Object 2 at byte offset 74 0000000192 00000 n % Object 3 at byte offset 192 0000000291 00000 n % Object 4 at byte offset 291 0000000409 00000 n % Object 5 at byte offset 409 |
Каждый элемент таблицы перекрестных ссылок состоит ровно из 20 байт: 10-значное смещение в байтах (с ведущими нулями), 5-значный номер поколения и один символ (n для обычных объектов, f для свободных объектов), за которым обязательно следует пробел. Этот формат фиксированной длины позволяет осуществлять произвольный доступ к самой таблице перекрестных ссылок.
Первая запись (объект 0) всегда является специальной записью, указывающей на начало списка свободных объектов, с номером поколения 65535. Этот механизм позволяет PDF повторно использовать номера объектов при удалении объектов во время инкрементных обновлений.
Трейлер: Основные метаданные и навигация по файлам.
Раздел "трейлера" содержит важную информацию, необходимую для программ обработки PDF-файлов для навигации по структуре документа:
|
1 2 3 4 5 6 7 8 |
trailer << /Root 5 0 R % Document catalog reference /Size 6 % Number of xref entries >> startxref 459 % Byte offset of xref table %%EOF % End-of-file marker |
Трейлер начинается со следующего. trailer ключевое слово, за которым следует словарь, содержащий важную информацию для навигации. /Size запись указывает на общее количество записей в таблице перекрестных ссылок, в то время как /Root указывает на каталог документов — корневой элемент графа объектов.
The startxref Ключевое слово предшествует единственному номеру, указывающему смещение в байтах, где начинается таблица перекрестных ссылок. В заключение, %%EOF marks the end of the PDF file. Программы для чтения PDF-файлов начинают обработку, находя этот маркер конца файла, затем, двигаясь в обратном направлении, находят трейлер и таблицу перекрестных ссылок, после чего приступают к загрузке объектов по мере необходимости.
Лексические соглашения: Основа синтаксиса PDF.
Файлы PDF представляют собой последовательности 8-битных байтов, которые следуют определенным лексическим правилам для преобразования в токены. Понимание этих соглашений имеет решающее значение для обработки PDF.
Классификация символов.
PDF распознает три категории символов:
- Обычные символы. – Все символы, кроме пробелов и разделителей.
- Символы пробелов. – Используются для разделения токенов.
- Разделители – Специальные символы:
( ) < > [ ] { } / %
Символы пробелов в PDF включают:
| Character Code | Meaning |
|---|---|
| 0 | Null |
| 9 | Tab |
| 10 | Line feed |
| 12 | Form feed |
| 13 | Carriage return |
| 32 | Space |
Файлы PDF могут использовать последовательности <CR>, <LF> или <CR><LF> для завершения строк. Однако, массовое изменение разрывов строк, вероятно, повредит файл, поскольку это влияет на последовательности разрывов строк внутри сжатых двоичных данных.
Типы объектов PDF: Полная таксономия
PDF поддерживает восемь основных типов объектов, которые служат строительными блоками для всего содержимого документа. Они делятся на базовые объекты, составные объекты и механизмы связывания:
Базовые объекты
Целые числа и числа с плавающей точкой
Числа являются основой числовой системы PDF:
|
1 2 3 4 5 |
% Integer examples 0 +1 -1 63 % Real number examples 0.0 0. .0 -0.004 65.4 |
Целые числа состоят из десятичных цифр (0-9), которые могут быть опционально предварены знаками плюс или минус. Вещественные числа следуют аналогичным правилам, но могут включать один десятичный знак, который может находиться в начале, середине или конце числа. Следует отметить, что экспоненциальная запись (например, 4.5e-6) не допускается в PDF.
Диапазон и точность чисел зависят от реализации PDF, а не от спецификации. Некоторые реализации преобразуют целые числа в вещественные числа, если они превышают доступный диапазон целых чисел.
Строки: Два способа представления.
PDF предлагает два различных формата строк для разных целей:
Строковые литералы.
Строковые литералы заключаются в круглые скобки и поддерживают escape-последовательности:
|
1 2 3 4 5 6 7 8 |
% Simple string (Hello, World!) % String with escaped characters (Some \\ escaped \(characters\)) % String with balanced parentheses (no escaping needed) (Red (Rouge)) |
Escape-последовательности в строковых литералах включают:
| Sequence | Meaning |
|---|---|
\n |
Line feed |
\r |
Carriage return |
\t |
Horizontal tab |
\b |
Backspace |
\f |
Form feed |
\ddd |
Character code in three octal digits |
Шестнадцатеричные строки.
Шестнадцатеричные строки предоставляют альтернативное представление, особенно полезное для двоичных данных:
|
1 2 |
<4F6Eff00> % Bytes 0x4F, 0x6E, 0xFF, 0x00 <48656C6C6F> % "Hello" in ASCII hex |
Каждая пара шестнадцатеричных цифр представляет один байт. Если встречается нечетное число цифр, предполагается, что последняя цифра следует за 0. Этот формат делает двоичные данные удобочитаемыми для человека, сохраняя при этом функциональную эквивалентность строковым литералам.
Имена: Система идентификаторов PDF.
Имена служат идентификаторами во всем PDF, выполняя функции ключей словаря и символических констант:
|
1 2 3 4 |
/French % Simple name / % Valid name (just the slash) /Websafe#20Dark#20Green % Name with encoded spaces (#20 = space) /A#42 % Name with encoded character (#42 = 'B') |
Имена начинаются с символа "/" и не могут содержать пробелы или разделительные символы напрямую. Специальные символы используют хеш-кодирование с двумя шестнадцатеричными цифрами. Имена чувствительны к регистру, поэтому /French и /french представляют разные идентификаторы.
Булевы значения и Null.
PDF поддерживает стандартные логические значения и объект null:
|
1 2 3 |
true % Boolean true false % Boolean false null % Null object |
Они служат флагами в записях словаря и значениями-заполнителями в структурах объектов.
Сложные объекты.
Массивы: Упорядоченные коллекции.
Массивы содержат упорядоченные последовательности любых объектов PDF, включая другие массивы:
|
1 2 3 |
[0 0 400 500] % Four integers (typical rectangle) [/Green /Blue [/Red /Yellow]] % Mixed types with nested array [1 0 R 2 0 R 3 0 R] % Array of indirect references |
Массивы не требуют согласованности типов — элементы могут быть числами, строками, именами, другими массивами или любым типом объектов PDF.
Словари: Отображения ключ-значение.
Словари представляют собой неупорядоченные коллекции пар ключ-значение, где ключи всегда являются именами:
|
1 2 3 4 5 6 7 8 |
<</One 1 /Two 2 /Three 3>> % Simple mappings << % Multi-line dictionary /Type /Page /Parent 1 0 R /Resources 3 0 R /MediaBox [0 0 612 792] /Contents [4 0 R] >> |
Словари являются основой структурированных данных PDF, содержащими все, от определений страниц до спецификаций шрифтов. Они могут быть вложены на произвольную глубину, создавая сложные иерархические структуры.
Потоки: Контейнеры для двоичных данных.
Потоки объединяют словарь с двоичными данными, что необходимо для изображений, шрифтов и сжатого контента.
|
1 2 3 4 5 6 7 8 9 10 11 12 |
4 0 obj << /Length 65 % Stream length in bytes /Filter /FlateDecode % Optional compression filter >> stream 1. 0. 0. 1. 50. 700. cm BT % Binary or text data /F0 36. Tf (Hello, World!) Tj ET endstream endobj |
Потоки состоят из словаря (который содержит как минимум запись), ключевое слово, символ новой строки, байты данных, еще один символ новой строки и ключевое слово. Все потоки должны быть непрямыми объектами и обычно используют сжатие для повышения эффективности. /Length запись. stream ключевое слово. endstream ключевое слово.
Непрямые ссылки: Связывание объектов.
Непрямые ссылки создают связи между объектами, обеспечивая структуру графа, которая делает PDF эффективным.
|
1 2 |
6 0 R % Reference to object 6, generation 0 <</Resources 10 0 R /Contents [4 0 R]>> % Dictionary using references |
Формат состоит из номера объекта, номера поколения и ключевого слова. R Этот механизм позволяет объектам ссылаться друг на друга без включения полных определений, что обеспечивает совместное использование и произвольный доступ.
Потоки и фильтры: расширенная обработка данных.
Потоки представляют собой основной механизм хранения двоичных данных в PDF, обеспечивающий эффективность. Большинство содержимого PDF, от графики страниц до встроенных шрифтов, хранится в потоках, обычно сжатых для экономии места.
Комплексные типы фильтров.
PDF поддерживает множество фильтров сжатия и кодирования, каждый из которых оптимизирован для определенных типов данных.
| Filter Name | Description and Use Cases |
|---|---|
/ASCIIHexDecode |
Converts hexadecimal digit pairs to bytes. ‘>’ indicates end of data. Primarily for 7-bit data transmission compatibility. |
/ASCII85Decode |
More efficient 7-bit encoding using printable characters ‘!’ through ‘u’ and ‘z’. Sequence ‘~>’ marks end of data. |
/LZWDecode |
Lempel-Ziv-Welch compression, identical to TIFF implementation. Good general-purpose compression. |
/FlateDecode |
Deflate compression (RFC 1950), used by zlib. Most common PDF compression method. Supports predictors for enhanced compression. |
/RunLengthDecode |
Simple run-length encoding for data with repeated byte sequences. |
/CCITTFaxDecode |
Group 3/4 fax compression. Excellent for monochrome (1-bit) images, poor for general data. |
/JBIG2Decode |
Advanced compression for monochrome, grayscale, and color images. Superior to CCITT methods. |
/DCTDecode |
JPEG lossy compression. Complete JPEG files with headers can be embedded directly. |
/JPXDecode |
JPEG2000 compression supporting both lossy and lossless modes. Limited to JPX baseline feature set. |
Несколько цепочек фильтров.
Фильтры можно объединять для решения сложных задач обработки:
|
1 2 |
/Filter [/ASCII85Decode /DCTDecode] % JPEG data then ASCII85 encoded /Filter [/ASCIIHexDecode /FlateDecode] % Deflate compression then hex encoding |
Фильтры применяются в обратном порядке во время декодирования: последний фильтр в массиве применяется первым при чтении данных.
Продвинутые архитектуры PDF.
Инкрементное обновление: неразрушающее изменение.
Инкрементное обновление позволяет изменять PDF-файлы путем добавления изменений, а не перезаписывая весь файл. Эта важная функция обеспечивает несколько преимуществ:
- Производительность. – Записываются только новые/измененные объекты.
- Электронные подписи – Оригинальное подписанное содержимое остается нетронутым.
- История версий. – Возможно восстановление предыдущих состояний документа.
- Эффективная обработка больших файлов. – Минимальное количество операций записи для работы с большими документами.
Во время инкрементных обновлений новые объекты и новый раздел перекрестных ссылок добавляются в конец файла. Новый трейлер включает в себя... /Prev запись, указывающая на смещение в байтах предыдущей таблицы перекрестных ссылок, создающая связанный список версий документов.
Объектные и перекрестные потоки (PDF 1.5+).
Современные версии PDF используют потоки объектов и потоки перекрестных ссылок для достижения лучших коэффициентов сжатия:
- Объектные потоки. – Несколько объектов, сжатых вместе в один поток.
- Потоки перекрестных ссылок. – Данные перекрестных ссылок, хранящиеся в сжатом формате потока.
- Стратегия группировки. – Объекты группируются по шаблонам использования (например, все объекты страницы 1 вместе).
Этот подход обеспечивает произвольный доступ при значительном уменьшении размера файлов, особенно для документов со многими небольшими объектами.
Линеаризованный PDF: Структура, оптимизированная для веб.
Линеаризованный PDF (введен в версии PDF 1.2) реорганизует структуру файла для оптимального просмотра в веб-браузере:
|
1 2 3 4 5 6 7 8 9 10 11 12 |
%PDF-1.4 %âãÏÓ 4 0 obj % Linearization dictionary << /E 200967 % End of first page /H [ 667 140 ] % Hint stream location and length /L 201431 % File length /Linearized 1 % Linearization flag /N 1 % Number of pages /O 7 % First page object number /T 201230 % Traditional xref table offset >> endobj |
Линеаризованные файлы обеспечивают:
- Быстрая загрузка первой страницы – Объекты страницы 1 отображаются первыми в файле
- Постепенная загрузка – Контент отображается постепенно во время загрузки
- Эффективная навигация. – Таблицы подсказок оптимизируют доступ к страницам
- Обратная совместимость Файлы остаются читаемыми для программ, не поддерживающих линейное чтение.
Обработка PDF-файлов: техническая реализация.
Алгоритм чтения: от байтов к объектам.
Программы для чтения PDF используют сложную стратегию разбора.
- Проверка заголовка. Проверка цифровой подписи PDF и извлечение информации о версии.
- Положение трейлера. Поиск маркера %%EOF, начиная с конца файла.
- Разбор перекрестных ссылок. – Создание карты местоположений объектов из таблицы перекрестных ссылок.
- Обработка словаря трейлера. – Извлечение каталога документов и метаданных.
- Стратегия загрузки объектов. – Загрузка объектов по требованию или предварительная загрузка критически важных объектов.
- Построение дерева содержимого. – Создание логической структуры документа из графа объектов.
Этот процесс обрабатывает различные сложности, включая шифрование, линеаризацию, потоки объектов и инкрементные обновления.
Алгоритм записи: от объектов к байтам.
Генерация PDF-файлов следует более простому процессу:
- Генерация заголовка. – Вывод версии PDF и бинарного маркера.
- Анализ графа объектов. – Удаление неиспользуемых объектов для уменьшения размера файла.
- Перенумерация объектов. – Присваивать последовательные номера от 1 до n.
- Сериализация объектов. – Записывать объекты, фиксируя смещения в байтах.
- Генерация перекрестных ссылок. – Создавать таблицу перекрестных ссылок на основе зафиксированных смещений.
- Создание трейлера. – Генерировать словарь трейлера и маркер конца файла.
Представление структуры данных.
Полный объект PDF можно представить, используя эту рекурсивную структуру данных:
|
1 2 3 4 5 6 7 8 9 10 |
pdfobject ::= Null | Boolean of bool | Integer of int | Real of real | String of string | Name of string | Array of pdfobject array | Dictionary of (string, pdfobject) array | Stream of (pdfobject, bytes) | Indirect of int |
Например, объект словаря << /Kids [2 0 R] /Count 1 /Type /Pages >> будет представлен следующим образом:
|
1 2 3 4 5 |
Dictionary [ ("Kids", Array [Indirect 2]); ("Count", Integer 1); ("Type", Name "Pages") ] |
Практические инструменты и профессиональные рабочие процессы
Несколько инструментов командной строки облегчают анализ и манипулирование PDF:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
% Linearize PDF for web optimization pdfopt input.pdf output.pdf % Decompress streams for manual inspection pdftk input.pdf output decompressed.pdf uncompress % Extract and analyze PDF structure pdf-parser --stats document.pdf % Repair corrupted PDF files pdftk broken.pdf output repaired.pdf % Extract specific pages pdftk document.pdf cat 1-3 output pages1-3.pdf % Get comprehensive PDF information pdfinfo -meta -struct document.pdf % Convert PDF to PostScript for analysis pdftops document.pdf document.ps |
Вопросы безопасности и целостности
Понимание структуры PDF имеет решающее значение для анализа безопасности:
- Обнаружение встроенного контента. – Определение скрытых потоков и объектов.
- Анализ вредоносного кода. – Анализ JavaScript и действий форм.
- Извлечение метаданных. – Восстановление истории документов и информации об авторе.
- Проверка цифровой подписи. – Проверка целостности инкрементных обновлений.
Заключение: Освоение архитектуры PDF.
Понимание структуры файлов PDF является основой для расширенной обработки документов, криминалистического анализа и разработки приложений. Элегантная структура формата, состоящая из четырех основных разделов, работающих в гармонии, создает систему, которая одновременно удобна для чтения человеком (в несжатом виде) и очень эффективна для сложных документов.
От простого примера "Hello, World", демонстрирующего базовую структуру, до корпоративных документов с тысячами страниц и сложными интерактивными функциями, применяются одни и те же фундаментальные принципы. Эта согласованность делает PDF масштабируемым и надежным в самых разных сценариях использования.
Эволюция формата от PDF 1.0 до текущих версий демонстрирует внимательное отношение к обратной совместимости, одновременно вводя мощные функции, такие как потоки объектов, расширенная компрессия и оптимизация для веб. Понимание этих архитектурных решений позволяет более эффективно обрабатывать и устранять неполадки в PDF.
⚠️ Рекомендации по реализации.
Хотя это руководство охватывает основные концепции структуры PDF, полное спецификация содержит сотни страниц, подробно описывающих пограничные случаи, необязательные функции и требования совместимости. Для производственных приложений используйте проверенные библиотеки PDF (например, HotPDF Componentили Delphi PDF Library), а не реализуйте парсеры с нуля. Эти библиотеки обрабатывают многочисленные сложности и необязательные функции, которые не охватываются в этом вводном руководстве.