masterspammer (masterspammer) wrote,
masterspammer
masterspammer

Categories:

MS Word document binary format изнутри или очарование противоестественного

У меня лёгкая простуда и температура 37, то есть ни туда не сюда. Оттого пишу в развлекательном стиле, без подглядывания в спецификации и код, даже в свой.

Вообще-то формат файла у офисных программ пакета одинаков - он просто контейнер, в котором лежат в свою очередь уже специфические данные. Больше всего контейнер похож на образ файловой системы, например, .iso, только со своей спецификой. Например, его размер непостоянен, что неудивительно в нашем случае - документ-то может расти и контейнер рассчитан на дописывание данных без перезаписи всего. Кстати, раньше, кажется до версии 6, контейнера не было, а был просто документ (сейчас лежащий в контейнере вместе с прочими данными, которые я зову файлами, а авторы - потоками).

Дозаписывание происходило как онтогенетически, так и филогенетически; и сам документ по мере ввода растёт и от версии к версии "типовой" размер файла увеличивается. Оба случая ведут к странностям, а главная цель контейнера (и много ещё чего в этом формате) - позволить работать на медленных и ненадёжных носителях, на дискетах. У этой "файловой системы" есть таблица размещения "кластеров" - с первого же дня зову эту таблицу FAT, а не так, как авторы - очень уж она похожа. Таблица в какой-то момент стала мала, её расширили (иначе нельзя создавать большие файлы), указав в неиспользованном поле заголовка ссылку на продолжение - таблицу ссылок на таблицы, последняя ссылка - на другую таблицу таблиц и так этот цепень может тянуться долго. Размер кластера великоват для хранения мелких файлов - для них созданы кластеры поменьше со своей таблицей. Лежат они в корневой директории, у которой есть не только имя, но и такое вот "тело". Само тело лежит как и любой файл в кластерах, как указано в большой FAT. Если файлик меньше 4096 байт, он состоит из коротких кластеров, иначе - из длинных. Директории сделаны красно-чёрным деревом, зачем - я не знаю, обильного файлоношения я не наблюдал - 5-10 файликов максимум.

В контейнере лежат документ, данные для документа, до двух таблиц (не имеющих отношения к таблицам на экране), причём в где-то в заголовке указано, какую именно сейчас использовать, метаинформация и прочее. Характерны ссылки из одного "файлика" на место в другом, например, где искать картинку. Я это на память не воспроизведу и в здоровом виде. А ведь когда-то файлик был один (на дискете), а контейнера не были и документ рекурсивно-онанистически сам на некоторое место себя ссылался. Описывать буду как будто он просто ссылается куда-то, всё равно вспоминать лень, а в спеках есть.

Документ прост и весьма туп в плане форматирования - есть 3 уровня вложенности - раздел, абзац и символ, сделать в строчной цитате выделение не получится, но можно сделать нечто, что будет так выглядеть. Вложенность полей, списков и таблиц делается на основе соглашений, напоминающих соглашение с дьяволом. По крайней мере у абзацев и символов есть стили, то есть заданные сочетания атрибутов - не каскадируемые, но наследуемые один от другого. Хотите чтоб в заголовке и в абзаце сокращение было разного цвета - делайте два стиля.

Структуры описания форматирования раздела, абзаца и символа огромны и в файле в чистом виде никогда не хранятся. Хранятся коды форматирования с параметрами переменной длинны разбитые по страницам (так легче по файлу распихивать). Если для какого-то сильноотформатированного элемента страницы не хватает, то есть специальная команда, ссылающаяся на место где продолжение - не постранично, влезет всё. До версии 6 включительно коды были однобайтные, потом стали двухбайтные не считая параметров, естественно. В спецификации куча ошибок по части типов и размера параметров кодов, как по части соответствия документов реальности, так и по части адекватности этой реальности здравому смыслу, например, логическая переменная может занимать 4 байта или из 16-ти бит под хранение ЗНАКОВОГО числа используется только 12 и 4095 на самом деле - -1. К счастью, в двухбайтовой версии кодов есть два способа узнать длину - по коду (взять несколько бит из самого команды) и по таблице - реально стоит проверять на практике команды, для которых эти два способа дают разный результат. А проверять стоит - ошибся в длине - следующую команду начнёшь читать с другого места - как при дизассемблировании - и ошибкой будет всё до конца страницы.

Команды весёлые, многие дублируются для нас и для восточных? двунаправленных языков, многие команды дублируют друг друга - тот же цвет может быть выбран из 16-ти цветовой или 256-ти цветовой палитр или же задан как RGB. Забавно, что при указании цвета подаются все 3 команды от самой старой до самой новой - чтоб программа не поддерживающая новые возможности получила достаточное приближение посредством старых. Ещё смешная команда - назначить таблицу соответствия стилям - чтоб копипастить из документа где 5-й стиль как 2-й тут было попроще. Или назначить псевдослучайный ID для облегчения слияния документов. Ой!

Чтобы получить форматирование символа нужно взять форматирование раздела, применить команды для абзаца и, наконец, для символа - думаете вы. А вот и не всё! Текст состоит из фрагментов, у которых тоже может быть своё форматирование. Если взять текст, выделить в его середине здоровенный кусок, сделать курсивом и сохранить "быстрым сохранением", то сам текст и его форматирование не изменятся, а вот из одного фрагмента (от начала до конца) сделается равно три и средний будет с командой включить курсив. Удаление делается почти так же - фрагментов станет два, а то что между ними останется подвешенным в нигде, но в файле останется.

(Лирическое отступление - получив вопросы для поступления в аспирантуру, я открыл файл простенькой программой, которая нашла там юникод и перегнала в текст - вопросов было МНОГО и они были всеохватны; оказалось, что научный руководитель открыл документ со всеми вопросами на кучу специальностей, удалил лишнее и сохранил документ).

При вставке текста в середину он вставится в конец, а фрагменты выстроят правильный порядок. Ещё фрагменты бывают юникодные и не очень, за юникодность отвечает какой-то невзрачный бит. Для неюникодных ещё как-то кодировка задаётся. Не все программы понимают фрагментированные файлы что может привести к казусам. Сюда же - юникодность и знаковость/беззнаковость некоторых параметров - как вам вместо маленького отступа влево получить ОГРОМНЫЙ, но вправо?!

Некоторые функции (разделение ячеек таблиц, вставка полей, картинок) делаются спецсимволами; мало того, для этих символов должен быть установлен флаг спецсимвола в форматировании. Как нужно обрабатывать спецсимвол без флага и флаг без символа - непонятно. Некоторые спецсимволы означают разное, по разному отформатированные.

Продолжу чуть погодя.
Tags: .doc, Говнокод, РазборПолётов
Subscribe

  • Групповая динамика

    Вчера вечером встретили трёх собак с хозяйкой (типичная банда, мексиканские голые, это такие средние собачки, обводами напоминающие Анубиса). Каждый…

  • Привился

    (Aka осуществил первую часть корпоративного чипирования). Давно планировал, но не было такой возможности (чтоб не тащиться чёрт-те куда, а чтоб с…

  • (no subject)

    Я отдал бы немало за пару крыльев, Я отдал бы немало за третий глаз, За руку, на которой четырнадцать пальцев, Мне нужен для дыхания другой…

  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your reply will be screened

    Your IP address will be recorded 

  • 2 comments