Формат docx что это такое, формат doc? Чем открыть эти файлы


Документ Microsoft Word представляет собой файл с расширением doc или docx. До 90-х годов XX века расширение doc использовалось для текстовых файлов, которые не содержат разметки. И сейчас можно убедиться, что файл такого типа легко создать с помощью, например, программы «Блокнот». Правда, он не будет иметь богатого форматирования, но легко открывается программой Ворд, в которой набранному в блокноте тексту можно придать более оформленный вид. Когда корпорация Майкрософт выпустила программу Ворд, разработчики решили использовать в ней расширение doc. К настоящему времени этот текстовый редактор является самым популярным в мире, поэтому файл с расширением doc ассоциируют с этим программным продуктом и называют просто «вордовский формат».

Формат docx что это такое? Формат doc — в чем разница, история

Здравствуйте, друзья! Начинающие пользователи программы Ворд иногда задают вопрос, что такое Docx или Doc. Сегодня мы поговорим об этих форматах подробно.

Итак, формат docx что это такое? Это файловый формат документа, предназначенный для хранения, создания и обработки текстов в Ворде. Он входит в линейку форматов Office Open XML (расширяемый язык разметки). Данный документ был создан компанией Майкрософт Офис Ворд в 2008 году, на базе офисного пакета Ворд 2007. Этот формат может сохранять в себе стили разных документов, форматирование, картинки, видео, ссылки, объекты документа и другие данные (скрин 1).

Формат docx что это

Что такое формат Doc? Это расширение, которое обозначает текстовый файл документа Ворд. То есть, формат для хранения текстовых документов, как и docx. Формат был создан в 1985 году, и постоянно обновлялся до 2007 года Данный формат документов так же используется в текстовом редакторе Word.

В чем разница между Docx и Doc форматами? Первое отличие формата docx от doc – это работа с версиями Ворда. То есть, документ в формате docx используются в программе Ворд 2007 и более новыми. Формат doc работает с более старыми версиями программы Ворд.

Второе отличие форматов – сжатие. Файл документа Docx использует сжатие данных. Он позволяет сжимать документы без потери качества в килобайтах. В то время, как формат doc этого сделать не сможет.

Последнее отличие – несовместимость форматов. К примеру, формат doc не совместим со многими программами. А формат docx отлично работает на компьютере и других устройствах.

Если у вас возникла проблема с открытием форматов docx или doc, далее в статье мы разберем, как их можно открыть.

Внутренний формат документов MS WORD

Введение
…Стоило ему прослышать, что где-то результаты многообещающих исследований сданы на консервацию, как он приходил в зоологическое неистовство и рвался разоблачать, обличать и срывать покровы.
А. и Б. Стругацкие. Жук в муравейнике.

Хотя официально фирма Microsoft информацией по этой теме мало с кем делилась, и даже одно время пыталась препятствовать ее распространению, все же нельзя сказать, что эта информация закрыта. Ей на самом деле владеют многие. Без этой информации не существовали бы такие продукты, как антивирусы KAV и DrWEb, переводчик Stylus, пакет 1С:Предприятие и т.п.

Сейчас в Интернете ее вполне достаточное количество, просто она разбросана мелкими порциями по разным малоизвестным источникам, и, что еще более неприятно, озаглавлена совсем не так, как хотелось бы нам. К сожалению, это как раз тот случай, о котором предупреждал незабвенный Козьма Прутков: на клетке слона частенько можно встретить надписи «буйвол», «мышь», «муравей», «динозавр», но только не «слон».

Цель этой статьи — попытаться собрать наиболее важные осколки информации в одно целое и указать места, где они валяются россыпью.

1. Общее описание. Терминология

— Тот, кто хочет стать Чародеем Моря, должен знать Настоящее Имя каждой капли воды.
Урсула Ле Гуин. Волшебник Земноморья.

Файлы документов MS WinWord с расширением .DOC представляют собой сложные объекты, организованные по правилам структурированного хранилища (structured storage). Фактически, структурированное хранилище — это отдельная файловая система от Microsoft, примерно такая же, как FAT или NTFS. Используют ее очень многие Windows-приложения разных производителей, функционирующие в рамках технологий OLE/COM/ActiveX. Вот (очень неполный!) список расширений файлов, устроенных по правилам структурированного хранилища, которые я обнаружил на своем компьютере: .DOC, .DOT, .XLS, .XLA, .WIZ, .CAG, .FLA, .PPT, .MD и пр.

Сам же дисковый файл, хранящий внутри себя структурированное хранилище, называется «файл-документ» (docfile) или «составной файл» (compound file). Первый термин применялся во времена OLE 1, второй появился в середине 90-х годов вместе с OLE 2, сейчас они обычно используются как синонимы.

В OLE существует еще понятие «составной документ» (compound document), но этот термин обозначает абстрактный подкласс хранилищ особого вида… в-общем, это уже ария несколько из другой оперы.

Внутри составной файл состоит из следующих элементов:

  • «хранилища» (storages), а на самом деле это просто внутренние каталоги, описывающие состав и расположение других объектов внутри составного файла;
  • «потоки» (streams), а на самом деле это своего рода файлы, массивы структурированной информации, имеющие собственное имя;
  • «заблокированные данные» (lock-bytes), а на самом деле это довольно редко встречающиеся неструктурированные массивы двоичной информации, своего рода «посторонние» данные, которые разрешается иметь внутри составного файла, но которые не могут служить OLE-объектами.

Еще в литературе про OLE можно встретить термин «корневое хранилище» (root storage). Нетрудно сообразить, что он на самом деле означает всего лишь корневой каталог, т.е. главный каталог в составном файле. Фактически, так оно и есть. Но в литературе этот термин иногда используется в качестве синонима для составного файла и файл-документа, ведь они без корневого каталога не могут существовать, также как и он без них. Ну что ж, будем иметь это в виду.

Наконец, потоки (streams), на которые имеются ссылки в корневом хранилище (root storage), могут называться «наборы свойств» (property sets). На самом деле, так имеют право наименоваться не все потоки (streams), а только те из них, кто организован особым родом: имеют стандартизованный заголовок, разбиты на специфические разделы и т.п. Для нас это не слишком важно.

Разобраться в теринологических хитросплетениях мне помогла книжка: Харрис Л. Освой самостоятельное программирование OLE за 21 день. — М.: Бином, 1995.-462 с.

2. Доступ к STRUCTURED STORAGE через OLE2 API

— Добро пожаловать! Это автобус для ведьм и волшебников, попавших в трудное положение! Взмахните палочкой и входите в салон: мы домчим вас куда угодно!
Дж. К. Ролинг. Гарри Поттер и узник Азбакана

Microsoft предоставляет мощные средства для работы в рамках технологии OLE, они сконцентрированы в библиотеках OLE2.DLL (для 16-разрядных приложений) и OLE32.DLL (для 32-разрядных приложений). В принципе, к ним можно обращаться из любой системы программирования (например, из MS VB и даже из языка ассемблера), использовав традиционный механизм GetModuleHandle/GetProcAddress. Но проще всего это делать из MS VC или Borland C/C++. По крайней мере, все примеры из этой статьи компилировались при помощи Borland C/C++ v5.01.

Итак, в довольно объемной и сложной библиотеке OLE32.DLL для нас с точки зрения темы статьи интересны около дюжины API- функций, позволяющих создавать и открывать составные файлы в различных режимах, обращаться к их каталогам и т.п. Рассмотрим некоторые из них.

  1. Создание нового составного файла с форматом структурированного хранилища: HRESULT StgCreateDocfile (WCHAR *ИмяФайла, DWORD ФлагиДоступа, DWORD НеИспользуется, IStorage **Интерфейс);
    Обычно для параметра ФлагиДоступа используется конкатенация из битов STGM_CREATE (создать новый составной файл), STGM_READ (разрешить чтение), STGM_WRITE (разрешить запись) или STGM_READWRITE (разрешить чтение и запись). Но можно указать STGM_CONVERT, это якобы позволяет преобразовывать «сырые» данные в структурированное хранилище, помещая их в поток с предопределенныи именем CONTENTS.
  2. Открытие существующего составного файла, имеющего формат структурированного хранилища, флаги те же: HRESULT StgOpenStorage (WCHAR *ИмяФайла, IStorage *УжеОткрытыйИнтерфейс, DWORD ФлагиДоступа, SNB МаскаИсключения, DWORD НеИспользуется, IStorage **Интерфейс);
  3. Проверка файла на соответствие формату структурированного хранилища. Возвращает S_OK — это хранилище; S_FALSE — это не хранилище; STG_E_FILENOTFOUND — файла вообще нет: HRESULT StgIsStorageFile(WCHAR* ИмяФайла)
    Функции StgCreateDocfile и StgOpenStorage требуют имя дискового файла (например, L»C:\FILE.DOC»), а возвращают в последнем параметре интерфейс доступа — т.е. указатель на объект класса IStorage, свойства и методы которого позволяют манипулировать с элементами структуры уже открытого или созданного составного документа (физически это — просто массив адресов).

    Дальше кратко описываются некоторые, наиболее интересные методы этого интерфейса.

  4. Создание нового подкаталога в главном каталоге открытого составного файла. HRESULT CreateStorage(wchar_t *ИмяПодкаталога, DWORD ФлагиДоступа, DWORD НеИспользуется1, DWORD НеИспользуется2, IStorage **ОткрытыйОбъект);
  5. Открытие существующего подкаталога в главном каталоге открытого составного файла. HRESULT OpenStorage(wchar_t *ИмяПодкаталога, IStorage *УжеОткрытыйОбъект DWORD ФлагиДоступа, SNB ИменаПотоков, DWORD НеИспользуется, IStorage **ОткрытыйОбъект);
  6. Закрытие открытого каталога или подкаталога после завершения работы с ними (крайне рекомендуется использовать!). ULONG Release(void);
  7. Инициализация перечисления записей в каталоге или подкаталоге. HRESULT EnumElements(DWORD НеИспользуется1, void НеИспользуется2, DWORD НеИспользуется3, IEnumSTATSTG **ИнтерфейсПеречисления);
    Возвращает новый интерфейс к объекту-перечислителю, который обладает методами:
    • HRESULT Next(ULONG Сколько, void *Куда, void *РеальноПолученные) — возвращает очередные элементы;
    • HRESULT Skip(ULONG Сколько) — пропускает элементы списка;

  8. HRESULT Reset(void) — возвращает позицию начала списка;
  9. HRESULT Clone(Позиция) — возвращает копию перечислителя.
  10. Создание нового потока внутри открытого каталога. HRESULT CreateStream(wchar_t * ИмяПотока, DWORD ФлагиДоступа, DWORD НеИспользуется1, DWORD НеИспользуется2, IStream **ОткрытыйПоток);
  11. Открытие потока внутри открытого каталога. HRESULT OpenStream(const wchar_t *ИмяПотока, void *НеИспользуется1, DWORD ФлагиДомтупа, DWORD НеИспользуется2, IStream **ОткрытыйПоток);
  12. Запись данных в поток. HRESULT Write(void *Буфер, ULONG Размер, ULONG *РеальноЗаписано);
  13. Чтение данных из потока. HRESULT Read(void *Буфер, ULONG Размер, ULONG *РеальноПрочитано);
  14. Переименование записи в каталоге. HRESULT RenameElement(wchar_t *СтароеИмя, wchar_t *НовоеИмя);

Фактически, сервисных методов гораздо больше. Например, существует большой набор методов для работы с lock-bytes, но он нам в контексте статьи не слишком актуален.

Теперь рассмотрим примерчик работы с составным файлом через OLE API, а именно — рекурсивный просмотр дерева заключенных внутри объектов:

// Рекурсивный сканер docfile. (с) Климентьев К., Самара 2002 #include «windows.h» #include «ole2.h» #include «iostream.h» #include «stdio.h» int level=0; walk(char *s, LPSTORAGE ls) { OLECHAR FileName[256]; LPENUMSTATSTG lpEnum=NULL; LPSTORAGE pIStorage=NULL; LPSTORAGE pIStorage2=NULL; ULONG uCount; STATSTG stat; int i; if (!ls) { mbstowcs(FileName, s, 256); wprintf(L»[%s]\n», FileName); StgOpenStorage(FileName, NULL, STGM_READ|STGM_SHARE_EXCLUSIVE, NULL,0,&pIStorage); walk(«», pIStorage); } else { ls->EnumElements(0,NULL,0,&lpEnum); if (lpEnum) while (lpEnum->Next(1,&stat,&uCount)==S_OK) { for (i=0;iOpenStorage(stat.pwcsName, NULL, STGM_READ|STGM_SHARE_EXCLUSIVE, NULL, 0, &pIStorage2); level++; walk(«», pIStorage2); level—; } }; ls->Release(); } } int main(int argc, char* argv[]) { if (argc>1) walk(argv[1],NULL); }

Создадим в Word 97/2000/XP пустой DOC-файл без текста и напустим на него нашу программу. Мы увидим примерно следующее:

[word97.doc] 2: 1Table 2: \1CompObj 1: ObjectPool 2: WordDocument 2: \5SummaryInformation 2: \5DocumentSummaryInformation

Для DOC-файла в формате Word 6/7 (его можно создать, например, при помощи Wordpad) картинка будет попроще:

[word6.doc] 2: \1CompObj 2: WordDocument

Примерно так, как описано в этом разделе, устроены популярный FAR-плагин DocFile Browser Игоря Павлова и утилита OLE2View из MS Visual C/С++.

Если хотите подробностей, то рекомендую:

1) хорошую статью Артема Каева «ActiveX по шагам»; 2)фирменный материал от Microsoft «OLE 2 programmers reference» (его можно найти в файлах OLE.HLP или OLE2.HLP).

3. Низкоуровневый доступ к STRUCTURED STORAGE

Вокруг разобранной автомашины моментально собралась толпа коротышек. Каждому было интересно взглянуть на устройство механизма.
Н. Носов. Незнайка в Солнечном городе

Широко известен народный персонаж по имени Чукча, который служил «писателем» и по этой причине не считал для себя нужным учиться читать. Наверное, имеются автомобилисты, которые никогда не заглядывали под капот своего четырехколесного друга. Не исключено, что существуют нежно любящие друг друга супруги, которые ни разу в жизни… гм… надеюсь, мы к их числу не относимся?

Давайте же приоткроем «кошмарную тайну кровавой программисты», которые умеют только кликать по иконкам и таскать мышом картинки между окошкам, могут этот раздел с чистой совестью пропустить.

Составной файл состоит из целого числа «больших блоков» (big blocks), размер каждого из которых соответствует одному дисковому сектору, т.е. 512 байт. Поэтому, в отличие от англоязычной документации, мы будем называть их просто секторами. Все сектора в файле пронумерованы следующим образом: -1, 0, 1, 2… и т.д.

Сектор с номером -1 содержит заголовок составного файла:

struct DOC_FILE_HEADER { DWORD Сигнатура; // +00h — «магическое» число E011CFD0h DWORD КодВерсииOLE; // +04h — «магическое» число E11AB1A2h DWORD НеИспользуется1[9]; DWORD РазмерBBD; // +2Ch — количество секторов в BBD DWORD НачалоКаталога; // +30h — стартовый сектор каталога DWORD НеИспользуется2[2]; DWORD НачалоSBD; // +3Сh — стартовый сектор SBD DWORD РазмерСектора; // +40h — обычно имеет значение 1 DWORD НеИспользуется3[2]; DWORD НачалоBBD; // +4Ch — стартовый сектор BBD };

Примечание

. Есть предположние, что по смещению 40h располагается поле, описывающее размер сектора. В подавляющем большинстве DOC-файлов длиной до 1 Мб в этом поле содержится значение 1 (т.е. размер сектора равен 512), но изредка встречается 2 (т.е. размер сектора равен 1024). Вероятно, возможны 3, 4, и так далее. В этом случае лучше говорить не о «секторах», но о «кластерах». Но идеология организации составного файла от этого не меняется.

Теперь очень легко проверить, организован ли какой-нибудь файл по правилам структурированного хранилища: достаточно проверить его первые 4 байта. Они должны быть: 0D0h, 0CFh, 11h, E0h.

Все остальное, не занятое заголовком, пространство составного файла разбито на четыре (не обязательно непрерывных!) области:

  • область каталогов;
  • FAT данных, организованных в виде 512-байтовых больших блоков (в оригинале это BBD — big blocks depot);
  • FAT даных, организованных в виде 64-байтовых малых блоков (в оригинале это SBD — small blocks depot);
  • область собственно данных.

3.1. FAT «Больших Блоков»

Я не случайно пошел вразрез с англоязычной терминологией. Дело в том, что структура, о которой пойдет речь в этом разделе, является ничем иным, как FAT — File Allocation Table, т.е. таблицей секторов, занимаемых файлом (вернее, занимаемых потоком или каким-либо другим объектом). А оригинальный термин «BBD — big blocks depot» может только ввести в заблуждение.

FAT — она и в Африке FAT. Это последовательный список 4-байтовых «строчек», каждая из которых соответствует одному сектору. Нулевая запись соответствует сектору с номером 0 (т.е. 512-байтовому сектору, начинающемуся в файле по абсолютному смещению 200h), первая — сектору с номером 1 (смещение 400h) и т.д. Еще раз напомним: сектора нумеруются с -1, т.е. самый первый сектор составного файла в этой таблице просто не упоминается!

Содержимое 4-байтовой строчки FAT может быть выбрано из следующих вариантов:

  • -3 = 0FFFFFFFDh — признак специального сектора;
  • -2 = 0FFFFFFFEh — конец цепочки секторов;
  • -1 = 0FFFFFFFFh — неиспользуемый сектор;
  • иное >0 — номер сектора, следующего за текущим.

Если мы знаем номер стартового сектора для какого-либо объекта (например, для потока), мы легко можем вытянуть всю цепочку принадлежащих ему секторов. Вот конкретный пример, фрагмент дампа файла, содержащий начало FAT:

01 00 00 00 — 02 00 00 00 — 05 00 00 00 — 06 00 00 00 07 00 00 00 — 03 00 00 00 — FF FF FF FE — 08 00 00 00 FF FF FF FE — FF FF FF FD — FF FF FF FF — FF FF FF FF

Давайте выпишем значения «строчек» таблицы в более удобной для глаза форме и в скобочках каждой строчке припишем ее номер:

(00) 01 (01) 02 (02) 05 (03) 06 (04) 07 (05) 03 (06) -2 (07) 08 (08) -2 (09) -3 (0A) -1 (0B) -1

Допустим, известно, что стартовый сектор потока имеет значение 0, т.е. этот сектор заведомо уже принадлежит потоку. В нулевой строчке читаем: следующий сектор потока имеет номер 1. Переходим к строчке номер 1, и т.д., окончательно получаем цепочку номеров секторов: {0, 1, 2, 5, 3, 6}. Именно так, именно в таком порядке и разместил MS Word фрагменты какого-то потока внутри составного файла!

Кстати, обратите внимание на вклинившиеся куски какого-то другого объекта, живущего в секторах {4, 7, 8} и на пустые сектора с адресами 0A и 0B. Вероятно, это свидетельство того, что над документом долго и мучительно работали: многократно удаляли и вставляли фрагменты текста, рисунки, формулы и т.п.

Осталось выяснить, как же до этой FAT добраться. Смотрим на заголовок составного файла: по смещению 4Ch живет адрес стартового сектора в составном файле, а количество этих секторов живет по смещению 2Ch. Сектора располагаются непрерывно.

3.2. FAT «Малых Блоков»

Хранить множество малоразмерных объектов в 512-байтных секторах довольно нерационально. Поэтому в структуре составного файла предусмотрена возможность размещать данные в маленьких, 64-байтовых «блочках» (small blocks).

Идеология расположения 64-байтовых «блочков» мало отличается от рассмотренной нами в предыдущем разделе для 512- байтовых «больших блоков». Под них выделяются область составного файла, отдельные «блочки» в которой пронумерованы с 0.

Но область «блочков» носит подчиненный характер. Она описана в «главной» FAT как отдельный объект, под который отведена отдельная цепочка секторов. Для нее же существует отдельная FAT, которая тоже фактически представлена цепочкой 512-байтовых секторов в «главной» FAT.

Числа в строчках «маленькой» FAT соответствуют не абсолютным номерам 512-байтовых секторов, а относительным номерам 64-байтовых «блочков» внутри своей области.

Местоположение стартового сектора FAT «блочков» берется из заголовка составного файла (смещение 3Сh), остальные можно вытянуть по цепочке в «главной» FAT. Не хватает только информации о том, где брать стартовый сектор области, распределенной под «блочки», но речь об этом пойдет в следующем разделе.

Кстати, область «блочков» в файле может просто отсутствовать.

3.3. Структура каталога

Вопреки нашим предварительным предположениям, каталогов внутри составного файла не несколько, он — один единственный! Сей объект также представлен цепочкой секторов внутри «главной» FAT, а номер его стартового сектора можно найти в заголовке составного файла по смещению 30h.

Каталог состоит из 128-байтовых записей следующей структуры:

struct DIR_ENTRY { BYTE ИмяОбъекта[64]; // +00 — имя объекта в UNICODE WORD РазмерИмени; // +40h — фактическая длина имени BYTE ТипОбъекта; // +42h — 1,2,3 или 5 BYTE НеИспользуется1; // +43h DWORD Предыдущий; // +44h — предыдущий объект DWORD Следующий; // +48h — следующий объект DWORD Первый; // +4Сh — первый подчиненный DWORD НеИспользуется2[9]; // +50h DWORD СтартСектор; // +74h — стартовый сектор объекта DWORD РазмерОбъекта; // +78h — размер объекта в байтах DWORD НеИспользуется3; // +7Сh };

Хотя записи в каталогах обычно называются термином «entry» (вхождение), разработчики OLE решили (IMHO, напрасно!) взглянуть на них с точки зрения объектного подхода и назвали их (а также те объекты, которые они описывают) словом «property» (свойство). Остается только сокрушенно покачать головой по этому поводу и продолжать называть вещи пусть и «нелегальными», но более понятными именами.

Имя объекта записывается латинскими буквами и хранится в формате UNICODE, т.е. для того, чтобы перевести его в удобочитаемую форму, потребуется собрать вместе все нечетные байты. Имейте в виду: самый первый символ имени может оказаться «нечитабельным» и иметь значение, например, 05h («трефы») или 01h («рожица»). Не пугайтесь, это так и должно быть. Фактическая длина имени хранится в записи по смещению 40h.

Тип объекта описан байтом, хранящимся по смещению 42h:

  • 1 — это подкаталог нижнего уровня;
  • 2 — поток (т.е. набор каких-то данных);
  • 3 — lock-bytes (?)
  • 5 — корневой каталог.

Местоположение объекта задается номером его стартового сектора (см. смещение 74h), под которым его и нужно искать в FAT. А фактическая длина объекта (например, потока) располагается по смещению 78h. Необходимо иметь в виду: если длина объекта >= 1000h = 4096, то он располагается в больших 512- байтовых блоках (т.е. в секторах). В противном случае значение по адресу 74h указывает на стартовый «блочок» в области 64-байтовых «блочков». Сама эта область представлена в каталоге как «Root Entry», и искать ее следует в FAT больших блоков (даже если ее длина <4096) — вот она, недостававшая нам в предыдущем разделе информация!

Три поля по смещениям 44h, 48h и 4Сh описывают отношения страшинства между объектами. Для каталогов и подкаталогов (но не для потков!) в поле «Первый» хранится номер записи для какого-то своего дочернего объекта, которые, в свою очередь, имеют своих «Следующих» и т. д. Таким образом, все записи в каталоге упорядочиваются в виде дерева.

Вот дамп одной из записей в каталоге:

05 00 44 00-6F 00 63 00-75 00 6D 00-65 00 06 00 ..D.o.c.u.m.e.n 74 00 53 00-75 00 6D 00-6D 00 61 00-72 00 79 00 t.S.u.m.m.a.r.y 49 00 06 00-66 00 6F 00-72 00 6D 00-61 00 74 00 I.n.f.o.r.m.a.t 69 00 6F 00-6E 00 00 00-00 00 00 00-00 00 00 00 .i.o.n……… 38 00 02 01-02 00 00 00-04 00 00 00-FF FF FF FF 8………….. 00 00 00 00-00 00 00 00-00 00 00 00-00 00 00 00 …………… 00 00 00 00-00 00 00 00-00 00 00 00-00 00 00 00 …………… 00 00 00 00-10 00 00 00-00 10 00 00-00 00 00 00 ……………

Легко видеть, что:

  • имя объекта \5DocumentSummaryInformation;
  • длина имени 38h = 56 байтов;
  • тип объекта = 2, т.е. это поток;
  • предыдущий объект имеет номер = 2;
  • следующий объект имеет номер = 4;
  • стартовый сектор = 10h, т.е. файловая позиция = 2200h;
  • размер = 1000h = 4096 байтов, т.е. искать его надо в «больших блоках».

А вот пример полного каталога:

# Имя Тип Пред След Перв Старт Разм 0 Root Entry 5 -1 -1 3 24 1440 1 \1Table 2 -1 -1 -1 8 1000 2 WordDocument 2 5 -1 -1 0 1000 3 \5SummaryInformation 2 2 4 -1 10 1000 4 \5DocumentSummaryInformation 2 -1 -1 -1 18 1000 5 Macros 1 1 C B 0 0 6 VBA 1 -1 -1 7 0 0 7 ThisDocument 2 9 8 -1 0 44D 8 _VBA_PROJECT 2 -1 -1 -1 12 AA5 9 dir 2 -1 -1 -1 3D 2A3 A PROJECTwm 2 -1 -1 -1 48 29 B PROJECT 2 6 A -1 49 151 C \1CompObj 2 -1 D -1 4F 6A D ObjectPool 1 -1 -1 -1 0 0

Попробуем выполнить упорядочивание. Начнем с узла «0» («Root Entry»), его первым «сыном» является узел «3». Собрав воедино все узлы, связанные с узлом «0» и между собой, получим следующее множество: {1, 2, 3, 4, 5, С, D}. Оно образует первый уровень дерева.

На первом уровне присутствуют три объекта со статусом каталогов: «5» и «D». Дочерними объектами каталога «5» являются узел «B» и все связанные с ним объекты: {A, B, 6}. Каталог «D» не имеет дочерних объектов, т.е. он пуст. И так далее…

Можно написать несложный рекурсивный алгоритм, который построит желаемое дерево:

Итак, с составным файлом можно работать не только через OLE API, но и напрямую — например, из DOS-овской программы.

Данный раздел является существенно упорядоченным и несколько дополненным изложением статьи M. Schwartz. LAOLA file system

. Единственный известный мне перевод этой статьи на русский язык можно найти, например, в материалах 4 -го выпуска электронного журнала «Земский Фершал».

4. Структура документа MS WORD

-… Он съедал десять тарелок супу… — А на второе, — пятнадцать отбивных котлет… — И, наконец,… двадцать компотов!… — А потом этот человек подвязывал салфетку на грудь и говорил: «Ну, кажется, я заморил червячка, теперь, пожалуй, можно приступить к настоящему обеду!
Ларри Я.Л. Необыкновенные приключения Карика и Вали

Итак, мы подробно изучили с разных сторон множество действительно интересных вопросов, но… Следует признать, что основную тему статьи мы пока не раскрыли. В ближайшее же время попытаемся исправиться.

В Интернете можно найти немало ссылок на фирменные материалы «Microsoft Word 6.0 Binary File Format» и «Microsoft Word 97 Binary File Format», которые представляют собой огромные файлы, заполненные большим количеством малопонятных терминов, таблиц, списков и пр. Но название не совсем точно отражает действительность: на самом деле эти материалы описывают всего лишь структуру потока под названием «WordDocument». Продемонстрируем, что ничего совсем уж иррационального и трансцендентного в фирменной документации от Micrisoft нет.

Итак, поток «WordDocument» (в документации он называется «главным потоком» — main stream) начинается со своего собственного внутреннего заголовка, в котором мы упомянем всего несколько наиболее интересных для нас полей:

Смещение Длина Назначение Примечание ———————————————— 0h 2 Сигнатура Word6/Word97 2h 2 Код версии Word6/Word97 18h 4 Начало текста Word6/Word97 1Ch 4 Конец текста+1 Word6/Word97 34h 4 Длина текста+1 Word6 4Ch 4 Длина текста+1 Word97

Для документов, созданных в Word v6.0/7.0 или WordPad, сигнатура обычно равна 0A5DCh, а для Word97/2K/XP она равна 0A5ECh (все это верно по крайней мере для русских версий).

Если документ создан в MS WinWord, то текст обычно начинается по «круглым» смещениям (например, 200h или 300h), для прочих продуктов это не всегда выполняется (например, WordPad может разместить его по «треугольному» смещению 312h).

Текст для формата версий 6.0/7.0 представляет собой обычную последовательность однобайтовых символов в той или иной кодировке, а для более старших версий — в двухбайтовой кодировке UNICODE:

Символ Кодировка —————— 0-9 030h-039h A-Z 041h-05Ah a-z 061h-07Ah А-Я 410h-42Fh Ё 401h а-я 430h-44Fh ё 451h

Этой информации вполне достаточно, чтобы, например, извлечь из Word-документа текст. Производить обратную операцию несколько сложнее — для этого придется параллельно формировать таблицы описания свойств символов и абзацев.

Ссылки: 1) Microsoft Word for Windows 6.0 Binary File Format. Updated structures and sprm table for Windows Word 6.0 format; 2) Microsoft Word for Windows 6.0 Binary File Format 09/03/94; 3) Microsoft Word 97 Binary File Format For Windows and Macintosh. Last Revised July, 1997. 1998 Microsoft Corporation; 4) Microsoft Word 97 (aka Version 8) Binary File Format. Revised Aug 1 1998;

Заключение

В этой статье для меня все ясно, за исключением упоминаний о сепульках, трансме и хмепе. Увы, последний вышедший в свет том энциклопедии кончался статьей «Соус грибной», значит, ни о трансме, ни о хмепе ничего нет.
С. Лем. Звездные дневники Ийона Тихого. Путешествие четырандцатое.

Конечно, в статье рассмотрено далеко не все, что хотелось бы. И не всему вышенаписанному стоит беспрекословно доверять: например, весьма вероятно, что в случае огромных DOC-файлов структурированное хранилище может быть образовано из «секторов» с размерами большими, чем 512 байтов. Но теперь любознательный читатель может не только проверить информацию, но и продолжить собственные иследования двоичного формата документов WinWord.

Кому-то может показаться излишним приведенное выше подробное описание формата структурированных хранилищ. Но мне, например, оно сильно пригодилась, когда необходимо было вытаскивать текст из DOC-файлов, записанных на поцарапанную дискету. Функции OLE2 API в этой ситуации просто отказывались работать.

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

Возможны и иные применения для информации, приведенной в этой статье. Желаю успехов!

Дополнение от зимы 2004 года

После обнародования предыдущей версии этой статьи мне пришлось выслушать немало критики за ее неполноту, наличие многочисленых неточностей, и даже за то, что я дерзнул написать ее поперед тех «батьков», кто знает на эту тему гораздо больше, но шибко дорожит своей монополией на информацию. J

К счастью, большинство читателей восприняли ту статью благожелательно. А правильней всех поступил С. Новодворский, который очень удачно углубил рассмотренную тему в своей собственной статье «Доступ к MD-файлам при помощи VBA», попутно исправив самые крупные мои неточности и дописав иллюстрирующий софт. Спасибо, Сергей, и так держать!

Итак, самая крупная неточность в моей статье касалась формата заголовка структурированного хранилища. Часть полей я тогда намеренно не описал (посчитав не важными), одно поле описал ошибочно, а о назначении некоторых полей в то время лишь смутно догадывался. Теперь я имею возможность привести новый, уточненный формат заголовка структурированного хранилища:

struct DOC_FILE_HEADER { DWORD Сигнатура; // +00h — «магическое» число E011CFD0h DWORD КодВерсииOLE; // +04h — «магическое» число E11AB1A2h DWORD НеИспользуется; // +08h WORD НеИспользуется; // +0Ch WORD РазмерСектора; // +0Eh — Log2(512)=9 (new!) DWORD НеИспользуется; // +10h DWORD НеИспользуется; // +14h WORD НомерРевизии; // +18h — ? (new!) WORD НомерВерсии; // +1Ah — ? (new!) DWORD НеИспользуется; // +1Ch DWORD НеИспользуется; // +20h DWORD НеИспользуется; // +24h DWORD НеИспользуется; // +28h DWORD РазмерBBD; // +2Сh — количество секторов в BBD DWORD НачалоКаталога; // +30h — стартовый сектор каталога DWORD НеИспользуется; // +34h DWORD НеИспользуется; // +38h DWORD НачалоSBD; // +3Сh — стартовый сектор SBD DWORD ПродолжениеSBD; // +40h — ? (new!) DWORD ОкончаниеBBD; // +44h — стартовый сектор окончания BBD (new!) DWORD НеИспользуется; // +48h DWORD НачалоBBD; // +4Сh — стартовый сектор BBD DWORD ПродолжениеBBD[108]; // +50h — адреса секторов продолжения BBD (new!) };

Комментарии.

  1. Знаком «?» помечены поля, в назначении которых я не уверен.
  2. С адреса 50h начинается массив DWORD-ов, каждый из которых непосредственно адресует очередной сектор FAT больших блоков. Поля по смещениям 40h и 50h дают возможность иметь длинные FAT.
  3. Говорят, что MS Word, начиная с версии 2000 умеет ЧИТАТЬ
    документы с секторами длиной >512 (например, 4096), но все равно не умеет их
    СОЗДАВАТЬ
    .
  4. Убедитесь, насколько все у Microsoft запущено! J

Не исключено, что и это еще не конец…

* * *

Выражаю благодарность Андрею Каримову, участнику проекта «Антивирус Stop!», в беседах с которым эта статья появилась на свет. Также ряд ценных критических замечаний сделал сотрудник «Лаборатории Касперского» Андрей Крюков.

Благодарю за внимание. С глубочайшим почтением и искреннейшей преданностию есмь, милостивые государи, Ваш покорный слуга

(c) Климентьев К.Е. aka DrMAD: drmad (at) dr.com * https://drmad.chat.ru Самара 2002

Статья написана специально для UInC (https://www.uinc.ru).

Все документы и программы на этом сайте собраны ТОЛЬКО для образовательных целей, мы не отвечаем ни за какие последствия, которые имели место как следствие использования этих материалов\программ. Вы используете все вышеперечисленное на свой страх и риск.

Любые материалы с этого сайта не могут быть скопированы без разрешения автора или администрации.

Формат docx чем открыть (doc) на компьютере

Итак, чтобы открыть формат docx на компьютере, нужны соответствующие программы. В этом вам помогут текстовые редакторы:

  1. Программа онлайн офис – о ней писали статью на блоге.
  2. Майкрософт Офис Ворд 2007 и другие версии программы.
  3. Бесплатный пакет офисных приложений Опен Офис.
  4. Текстовый документ Лайбри Офис.
  5. Другие программы, которые похожи на программу Word.

Рассмотрим открытие документов в формате docx или doc с помощью программы Word 2007. Для начала вам нужно скачать и установить подходящую версию программы Ворд на компьютер, чтобы открыть данные форматы. Затем, нажмите по документу правой кнопкой мыши, далее кнопку «Открыть» (скрин 2).

Чтобы открыть doc формат, также используйте текстовые редакторы.

Кроме того, можете воспользоваться статьей на блоге: «как открыть файлы, если не знаете их расширения». Статья поможет вам узнать расширения файлов и открыть на компьютере файлы.

Что делать, если забыл сохранить документ

Ни для кого не секрет, что человеку свойственно ошибаться, а компьютер просто машина, поэтому возникают ситуации, когда документ закрывается без сохранения.

Завис компьютер, произошел сбой и Word закрылся, скакнуло напряжение и компьютер выключился, закрыл ворд не сохранил текст документа, подобных случаев можно перечислить очень много, но факт остается фактом, документ, над которым работали очень долго, не сохранился.

Или наоборот, заработался, часть документа удалил и случайно нажал «Сохранить» и теперь надо вернуть более раннюю версию.

Избежать подобных ситуаций, поможет встроенная функция автосохранения документа. Эта функция будет сохранять документ через определенное количество минут автоматически.

И все же, бывают случаи, часто от невнимательности или усталости, когда при закрытии документа, машинально нажал «Не сохранять». Конечно же, все последние изменения будут потеряны, но частично, файл удастся спасти..

Давайте рассмотрим, что следует делать, если вышли без сохранения или в результате программного сбоя закрылся текстовый редактор WS Word или отключили свет и компьютер выключился.

Чем открыть формат doc (docx) на айфоне

На айфон нужно установить приложение, которое будет открывать форматы doc и docx. Одно из приложений — это Office reader. Скачать на айфон его можете с магазина АппСторе.

Нужно найти приложение через поиск и нажать «Установить». Когда программа будет установлена, запустите ее на айфоне. Затем, найдите в программе документы с форматами doc или docx (скрин 3).

Кликните по найденным форматам, и документ откроется для просмотра.

Вместе с тем, можно установить другие приложения на айфон:

  • Смарт Офис;
  • Все документы;
  • и другие приложения.

Перечисленные программы работают без проблем, пользоваться ими можно бесплатно.

Создание документа

Для того, чтобы создать новый документ, в программе Word необходимо перейти:

Файл — Создать

При этом вы можете выбрать как пустой документ, так и документ по заранее подготовленному шаблону. Список шаблонов отобразится на экране.

Помимо предложенных шаблонов вы можете выбрать одну из категорий, для того, чтобы увидеть больше шаблонов в этой категории: Наборы макетов, Бизнес, Личное, Календари, Карточки, Событие, Образование.

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

Для того, чтобы вернуться назад, необходимо нажать кнопку Домой около строки поиска.

Строкой поиска можно воспользоваться для того, чтобы быстро найти необходимый шаблон.

Чем открыть файлы doc (docx) в онлайн

В Интернете есть специальные сервисы, которые открывают документы форматов doc или docx. Перечислим популярные ресурсы:

  • Гугл документы онлайн;
  • Яндекс диск открывает для просмотра и скачивания документов;
  • Гугл диск;
  • online-reader.com;
  • groupdocs.app/viewer/docx;
  • com/Welcome/
  • и другие ресурсы.

Разберем, как открыть doc формат в сервисе «onlinedocumentviewer.com/Welcome/». Сначала откройте сервис в браузере. Далее нажмите кнопку «UPLOAD File» (скрин 4).

После чего кликните по кнопке «Обзор», чтобы выбрать и загрузить документ doc с компьютера (скрин 5).

На других сервисах, документы в формате doc и docx, открываются по похожему принципу.

Word не сохраняет изменения

Почему Ворд не сохраняет документ? Возможно, Вы сталкивались с проблемой, когда Word отказывается сохранять отредактированный документ. Этому есть различные объяснения начнем с программного.

Документ защищен командой «Ограничить редактирование»

Сообщение выскакивает, когда на документ установлена защита. Чтобы снять ограничение следует, следует знать пароль и тогда:

Файл снабжен атрибутом «Только для чтения»

Чтобы избавится от проблемы следует:

Word отказывается сохранять файлы

Что делать если ворд не сохранил документ? По какой причине? Да, просто, не хочет сохранять. Может сбой системный, может еще что то.

В этом случае, самый банальный способ, это выделить текст документа и нажать «Ctrl+C», другими словами копировать.

Далее, создаем новый вордовский документ и нажимаем «Ctrl+V», тобишь вставить.

В 90% случаев, данный способ поможет в вашей беде.

Проблемы с расширениями docx и doc, как их решить

Во время работы с документами docx возникают проблемы с отображением документа, например, часть текста, невозможно прочитать. Что в этом случае сделать? Вы можете конвертировать данный документ в другие форматы, используя в Интернете сервисы-конвертеры.

Кроме этого, можно восстановить документ. Откройте Ворд 2010 и выше на компьютере. Нажмите вверху кнопку «Файл» далее «Открыть». Затем загрузите поврежденный документ с компьютера и кликните кнопку «Открыть и восстановить». Если этот способ вам не помог восстановить документ, можно использовать инструкцию от . В ней предложены другие варианты решения этой проблемы.

Автоматическое восстановление

Во время работы над документами Word автоматически сохраняет их во временную папку. Существует возможность восстановить файл, воспользовавшись Автоматическим восстановлением

, в случае если Вы забудете сохранить изменения или произойдет сбой.

Как восстановить документ

По умолчанию Word автоматически сохраняет каждые 10 минут. Если документ редактировался менее 10 минут, Word может не успеть выполнить автосохранение.

Если Вы не видите нужный файл, можете посмотреть все автоматически сохраненные файлы в представлении Backstage. Откройте вкладку Файл

, нажмите Управление версиями

, а затем выберите
Восстановить несохраненные документы
.

Как только напишете заголовок, сразу же сохраните документ

, чтобы в случае непредвиденных обстоятельств, не потерять документ, над которым работали целый день!

Быстрое сохранение документов Ворд

Каждая версия текстового процессора Word имеет виртуальную кнопку для быстрого сохранения документов. Она расположена в верхней части окна в виде дискеты. Во время работы в программе нужно нажать на неё один раз, и документ будет сохранён.

Текстовый файл можно найти на том месте, где он был создан. Статус сохранения на мгновение появляется в нижней части окна документа. Никаких других уведомлений в момент сохранения не появляется. Если кнопки на панели нет, её можно включить в параметрах. Необходимо открыть Панель быстрого доступа и добавить кнопку.

Сейчас читают: Как перевернуть текст.

Как сохранить на USB-носителе

Такой вариант записи нужен тогда, когда нужно передать текст Word — особенно если на другом устройстве нет доступа к интернету. Для этого нужно:

  1. Вставьте USB-устройство в порт;
  2. Нажмите «Файл»;
  3. Выберите «Сохранить как»;
  4. Выберите «Компьютер» или дважды кликните по «USB-накопитель» в «Устройства со съёмными носителями»;
  5. Введите название документа;
  6. Нажмите «Сохранить».

Как найти последний сохраненный документ

Не опытные пользователи текстового редактора, зачастую не обращают внимания в какую папку сохраняют свой документ, а затем не могут его найти. Ситуация распространенная и решается в два клика.

Найти последний сохраненный документ поможет следующий алгоритм:

  1. Открыть меню «Файл».
  2. Выбрать строку с командой «Последние» и кликнуть по ней мышкой.
  3. В открывшемся окне Вы увидите две колонки: в первой колонке будет последний закрытый документ; во второй, папка, где он сохранен.

Сохранение, сохранение и восстановление файла в Microsoft Office

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

Кроме того, можно сохранить файл в другом формате, например RTF, CSV или PDF.

Сохранение файла в OneDrive или SharePoint позволяет получить к нему доступ с любого устройства и включает такие функции, как автосохранения и история версий, которые помогают предотвратить потерю данных при неожиданном закрытии файла.

Чтобы сохранить файл:

Нажмите клавиши CTRL+S или выберите «Сохранить > файл».

Совет: Вы также можете выбрать

«Сохранить панели быстрого доступа».

Если файл сохраняется впервые, обязательно нужно ввести для него имя.

Совет: Сохраните файл в облачном расположении, например в OneDrive или SharePoint, чтобы иметь доступ к нему отовсюду, сотрудничать с другими людьми в режиме реального времени и получать доступ к истории версий.

По умолчанию, если вы уже вписали в свою папку, файлы сохраняются в OneDrive. Если вы хотите сохранить текущий файл в другом месте, щелкните ссылку «Расположение», чтобы увидеть другие расположения, которые использовались недавно. Если нужного расположения нет, вы можете открыть полное окно «Сохранить как», выбрав «Дополнительные параметры сохранения».

Совет: Если вы сохраните файл в OneDrive или SharePoint,автосохранения будут включены по умолчанию, поэтому вам не нужно помнить о том, что сохранять файлы по мере их сохранения.

Если вы хотите изменить стандартное расположение для сохранения этих папок на одну из недавно использованных папок, щелкните правой кнопкой мыши папку, которая будет использоваться по умолчанию, и выберите «Использовать как расположение по умолчанию».

Если вы хотите сохранить папку, которая не была использована последними, выберите пункт «Другие расположения». Если вы еще не получили это обновление, приложения Office по-прежнему будут использовать меню «Файл» для сохранения.

Вы также можете нажать F12 или выбрать > «Сохранить как», чтобы открыть меню «Файл».

Если вы привыкли использовать сочетания клавиш при закрытии документа, например ALT+F4, вы можете быстро выбрать «Не сохранять» с помощью сочетания клавиш для этой кнопки (ALT+N).

Сохранение копии как нового файла («Сохранить как»)

Совет: Если вы собираетесь создать новый файл на основе существующего, но хотите сохранить изменения только в нем, перед внесением каких-либо изменений лучше сохранить копию. Таким образом, исходный файл останется без изменений, а все изменения будут сохранены в новой копии. Вы также можете щелкнуть исходный файл правой кнопкой мыши и выбрать «Открыть копию».

Нажмите клавишу F12 или на вкладке Файл выберите команду Сохранить как.

По умолчанию Office сохраняет копию в том же расположении, что и исходный файл. Если текущее расположение вам подходит, перейдите к шагу 3. Если вы хотите сохранить копию в другом расположении, выберите его на этом этапе.

Сайты — [название вашей компании]

Библиотеки документов SharePoint или групп Office 365

OneDrive — [название вашей компании]

OneDrive для бизнеса

OneDrive для пользователей с учетной записью Майкрософт

Локальное устройство, включая все подключенные жесткие диски и устройства флэш-памяти

Откроется проводник, и вы сможете перейти к любому расположению на компьютере.

Укажите имя новой копии и нажмите Сохранить.

Исходный файл закроется, а вы продолжите работу над его новой копией.

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

Сохранение файла в другом формате

Файл можно сохранить в другом формате, чтобы его можно было открыть в другом приложении или в более ранней версии используемого приложения. Например, может потребоваться сохранить документ Word в файле RTF, а книгу Excel — в виде CSV-файла Comma-Separated.

Откройте вкладку Файл.

Нажмите кнопку Сохранить как.

Выберите расположение файла, например OneDrive или «Этот компьютер», в котором нужно сохранить файл.

В поле Имя файла введите новое имя файла.

В списке Тип файла выберите формат, в котором требуется сохранить файл. Например, выберите формат RTF, Word 97–2003 (DOC), веб-страницу (HTM или HTML) или запятую (CSV-формат).

Дополнительные сведения о том, как сохранять файлы в форматах PDF или XPS, см. в документе «Сохранение» или «Преобразование в формат PDF» или «XPS».

Нажмите кнопку Сохранить.

Архивные файлы и их восстановление

То, как вы будете восстанавливать и восстанавливать файлы, зависит от того, где и когда вы их сохранили. Чтобы узнать больше о функции, в том числе о том, какие версии Office ее поддерживают, выберите ее имя в таблице ниже.

Сохранено в OneDrive

Автосохранения автоматически сохраняет файл при его OneDrive или SharePoint в Microsoft 365.

С помощью истории версий можно просматривать и восстанавливать предыдущие версии файлов, сохраненных в OneDrive или SharePoint в Microsoft 365.

На компьютере с Windows можно архивировать папки «Рабочий стол», «Документы» и «Изображения OneDrive резервное копирование папок компьютера. См. также: сохранение файлов в OneDrive по умолчанию в Windows 10.

Вы можете восстановить все OneDrive до предыдущей версии, если OneDrive, перезаписаны, повреждены или заражены вредоносными программами.

Вы можете восстановить файлы и папки, удаленные из OneDrive.

Как записать в PDF или XPS

Эти форматы — самые доступные и популярные для того, чтобы ограничить редактирование. Получатель документа сможет только просматривать содержимое. Чтобы сделать такую настройку, нужно:

  1. Открыть «Файл»;
  2. Выбрать «Сохранить как»;
  3. Ввести имя текста в соответствующее поле;
  4. В списке выбора типа файла указать PDF или XPS;
  5. Если просмотр будет только в сети, можно уменьшить размеры — кликните «Минимальный размер»;
  6. Если нужно частично записать текст, включить записанные правки, свойства файла или создать гиперссылки, выберите соответствующие пункты в «Параметры»;
  7. Подтвердите изменения.

Как сохранить в виде веб-страницы

Этот вариант подходит для чтения в браузере. Он не переносит макет текста. Записать можно как в виде обычной HTML-страницы, так и в качестве документа, который сочетает в себе все медиафайлы (MHTML). Для этого:

  1. Нажмите «Файл»;
  2. Выберите «Сохранить как»;
  3. При публикации найдите имя сервера и кликните на него один раз;
  4. Введите наименование файла;
  5. В поле «Тип» укажите «Веб-страница» или альтернативу — «в одном файле»;
  6. Подтвердите изменения.

Рейтинг
( 1 оценка, среднее 4 из 5 )
Понравилась статья? Поделиться с друзьями: