<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Реверс-інженерія PPTX on File Format Blog</title>
    <link>https://blog.fileformat.com/uk/tag/%D1%80%D0%B5%D0%B2%D0%B5%D1%80%D1%81-%D1%96%D0%BD%D0%B6%D0%B5%D0%BD%D0%B5%D1%80%D1%96%D1%8F-pptx/</link>
    <description>Recent content in Реверс-інженерія PPTX on File Format Blog</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>uk</language>
    <lastBuildDate>Wed, 16 Sep 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://blog.fileformat.com/uk/tag/%D1%80%D0%B5%D0%B2%D0%B5%D1%80%D1%81-%D1%96%D0%BD%D0%B6%D0%B5%D0%BD%D0%B5%D1%80%D1%96%D1%8F-pptx/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Реверс-інженерія PPTX: розуміння внутрішньої структури файлів PowerPoint</title>
      <link>https://blog.fileformat.com/uk/presentation/pptx-reverse-engineering-understanding-powerpoint-files-internally/</link>
      <pubDate>Wed, 16 Sep 2026 00:00:00 +0000</pubDate>
      
      <guid>https://blog.fileformat.com/uk/presentation/pptx-reverse-engineering-understanding-powerpoint-files-internally/</guid>
      <description>Дізнайтеся, що насправді знаходиться всередині файлу `.pptx`. Дізнайтеся, як працює пакування OpenXML, графи зв’язків, форми та розмітка малюнків під капотом.</description>
      <content:encoded><![CDATA[<p><strong>Останнє оновлення</strong>: 16 вересня 2026</p>
<figure class="align-center ">
    <img loading="lazy" src="images/pptx-reverse-engineering-understanding-powerpoint-files-internally.png#center"
         alt="PPTX Reverse Engineering: Understanding PowerPoint Files Internally"/> 
</figure>

<hr>
<h2 id="реверс-інженерія-файлів-pptx4-посібник-розробника">Реверс-інженерія файлів <a href="https://docs.fileformat.com/presentation/pptx/">PPTX</a>: посібник розробника</h2>
<p>Сучасні презентаційні набори живлять усе — від інвесторських презентацій до внутрішніх квартальних метрик. Але якщо вам доводилося програмно витягувати текст, замінювати шаблони під час виконання, створювати автоматичні генератори слайдів або очищати конфіденційні презентації, ви, ймовірно, швидко зрозуміли: стандартні бібліотеки високого рівня для презентацій можуть виглядати як непередбачувана чорна скринька.</p>
<p>Коли бібліотеки, такі як <a href="https://products.fileformat.com/presentation/python/python-pptx/"><code>python-pptx</code></a>, <a href="https://products.fileformat.com/presentation/java/apache-poi-xslf/">Apache POI</a> або <a href="https://products.fileformat.com/presentation/net/openxmlsdk/">OpenXML SDK</a>, досягають своїх меж — або вводять недокументовані помилки розмітки — єдиний вихід — це глибоке занурення. Вам потрібно зрозуміти, що таке презентація PowerPoint на рівні байтів і схеми.</p>
<p>У цьому глибокому зануренні ми піднімемо завісу над форматом <code>.pptx</code>, розпакуємо його внутрішню структуру, простежимо граф зв’язків, розберемо ієрархії малюнків і розглянемо практичні стратегії зворотного інжинірингу, аналізу та маніпулювання презентаціями за допомогою чистого коду.</p>
<h2 id="1-що-насправді-таке-файл-pptx">1. Що насправді таке файл <code>.pptx</code>?</h2>
<p>По суті, файл <code>.pptx</code> не є пропрієтарним монолітним бінарним файлом, як старий формат <code>.ppt</code> 1990‑х років. З того часу, як Microsoft представила Office Open XML (ECMA-376 і ISO/IEC 29500), сучасні документи Office є <strong>архівами Open Packaging Conventions (OPC)</strong>.</p>
<p>Простими словами: <strong>файл <code>.pptx</code> — це просто zip‑архів, що містить XML‑документи та медіа‑ресурси, організовані у детермінованому дереві каталогів.</strong></p>
<p>Ви можете довести це за секунди, використовуючи стандартні інструменти терміналу:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#75715e"># Rename the extension and unpack it</span>
</span></span><span style="display:flex;"><span>cp presentation.pptx presentation.zip
</span></span><span style="display:flex;"><span>unzip presentation.zip -d presentation_unpacked/
</span></span><span style="display:flex;"><span>cd presentation_unpacked/
</span></span><span style="display:flex;"><span>tree -L <span style="color:#ae81ff">2</span>
</span></span></code></pre></div><p>Отримане дерево каталогів виглядає надзвичайно послідовно:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-text" data-lang="text"><span style="display:flex;"><span>.
</span></span><span style="display:flex;"><span>├── [Content_Types].xml
</span></span><span style="display:flex;"><span>├── _rels/
</span></span><span style="display:flex;"><span>│   └── .rels
</span></span><span style="display:flex;"><span>├── docProps/
</span></span><span style="display:flex;"><span>│   ├── app.xml
</span></span><span style="display:flex;"><span>│   └── core.xml
</span></span><span style="display:flex;"><span>└── ppt/
</span></span><span style="display:flex;"><span>    ├── presentation.xml
</span></span><span style="display:flex;"><span>    ├── _rels/
</span></span><span style="display:flex;"><span>    ├── slides/
</span></span><span style="display:flex;"><span>    ├── slideLayouts/
</span></span><span style="display:flex;"><span>    ├── slideMasters/
</span></span><span style="display:flex;"><span>    ├── theme/
</span></span><span style="display:flex;"><span>    └── media/
</span></span></code></pre></div><p>Кожен окремий візуальний ресурс, перехід, успадкування шаблону слайдів, координати текстового поля та векторна графіка закодовані в цій ієрархії файлів.</p>
<h2 id="2-будова-пакету-ключові-підсистеми">2. Будова пакету: ключові підсистеми</h2>
<p>Щоб ефективно розбирати презентації, ви повинні розуміти функції кожного компоненту верхнього рівня.</p>
<h3 id="content_typesxml"><code>[Content_Types].xml</code></h3>
<p>Це маніфест входу для читача OPC. Він зіставляє розширення файлів та явні внутрішні назви частин зі стандартизованими типами MIME/контенту. Якщо ви створите новий слайд або додасте зображення і не задекларуєте його у <code>[Content_Types].xml</code>, PowerPoint оголосить презентацію пошкодженою і запропонує відновлення.</p>
<p>Приклад фрагмента:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-xml" data-lang="xml"><span style="display:flex;"><span><span style="color:#f92672">&lt;Types</span> <span style="color:#a6e22e">xmlns=</span><span style="color:#e6db74">&#34;http://schemas.openxmlformats.org/package/2006/content-types&#34;</span><span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;Default</span> <span style="color:#a6e22e">Extension=</span><span style="color:#e6db74">&#34;xml&#34;</span> <span style="color:#a6e22e">ContentType=</span><span style="color:#e6db74">&#34;application/xml&#34;</span><span style="color:#f92672">/&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;Default</span> <span style="color:#a6e22e">Extension=</span><span style="color:#e6db74">&#34;rels&#34;</span> <span style="color:#a6e22e">ContentType=</span><span style="color:#e6db74">&#34;application/vnd.openxmlformats-package.relationships+xml&#34;</span><span style="color:#f92672">/&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;Default</span> <span style="color:#a6e22e">Extension=</span><span style="color:#e6db74">&#34;png&#34;</span> <span style="color:#a6e22e">ContentType=</span><span style="color:#e6db74">&#34;image/png&#34;</span><span style="color:#f92672">/&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;Override</span> <span style="color:#a6e22e">PartName=</span><span style="color:#e6db74">&#34;/ppt/presentation.xml&#34;</span> 
</span></span><span style="display:flex;"><span>            <span style="color:#a6e22e">ContentType=</span><span style="color:#e6db74">&#34;application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml&#34;</span><span style="color:#f92672">/&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;/Types&gt;</span>
</span></span></code></pre></div><h3 id="граф-звязків-_rels">Граф зв’язків <code>_rels/</code></h3>
<p>Одним із найважливіших концептів у OpenXML є <strong>непряме посилання через відношення</strong>. Частини рідко вказують безпосередньо на сирі шляхи файлів. Замість цього файл (наприклад, <code>slide1.xml</code>) має пов’язаний файл відношень, розташований у сусідській папці <code>_rels</code> (наприклад, <code>_rels/slide1.xml.rels</code>).</p>
<p>Відношення визначають:</p>
<ul>
<li>Гіперпосилання (<code>r:id=&quot;rId2&quot;</code>, TargetMode=&ldquo;External&rdquo;)</li>
<li>Зображення та аудіодоріжки, збережені в <code>ppt/media/</code></li>
<li>Вказівники успадкування макету (<code>slideLayout1.xml</code>)</li>
<li>Слайди нотаток, коментарі та вбудовані шрифти</li>
</ul>
<h3 id="docprops-метадані"><code>docProps/</code> (Метадані)</h3>
<ul>
<li><strong><code>core.xml</code></strong>: метадані Dublin Core — автор, назва, дата створення, мітка часу модифікації.</li>
<li><strong><code>app.xml</code></strong>: специфічна для застосунку статистика — версія PowerPoint, загальна кількість слайдів, кількість прихованих слайдів, кількість слів, назви шаблонів презентації.</li>
</ul>
<h3 id="ppt-двигун-презентації"><code>ppt/</code> (Двигун презентації)</h3>
<p>Тут розташована фактична презентація:</p>
<ul>
<li><strong><code>presentation.xml</code></strong>: Основний каркас. Він реєструє ідентифікатори слайдів, розміри слайдів, посилання на майстер нотаток та налаштування шрифту за замовчуванням.</li>
<li><strong><code>slides/</code></strong>: Окремі слайди (<code>slide1.xml</code>, <code>slide2.xml</code> тощо).</li>
<li><strong><code>slideLayouts/</code></strong>: Основні структурні шаблони (Титульний слайд, Два стовпці, Заголовок розділу).</li>
<li><strong><code>slideMasters/</code></strong>: Глобальні стилі, палітри за замовчуванням, заповнення фону та успадкування заповнювачів.</li>
<li><strong><code>theme/</code></strong>: Колірні палітри (акцент 1‑6, темні/світлі варіанти) та схеми шрифтів (основні/додаткові шрифти).</li>
<li><strong><code>media/</code></strong>: Оригінальні зображення (PNG, JPEG, SVG), аудіо та відеофайли.</li>
</ul>
<h2 id="3-розбір-слайду-діалекти-presentationml-p-та-drawingml-a">3. Розбір слайду: діалекти PresentationML (<code>p:</code>) та DrawingML (<code>a:</code>)</h2>
<p>Коли ви відкриваєте <code>ppt/slides/slide1.xml</code>, ви стикаєтеся з двома основними XML‑просторами імен:</p>
<ol>
<li><strong>PresentationML (<code>p:</code>)</strong>: Керує структурними елементами презентації (слайди, дерева форм, групи полотна).</li>
<li><strong>DrawingML (<code>a:</code>)</strong>: Керує типографікою, геометрією, 2D‑координатами, градієнтними заповненнями та векторним рендерингом.</li>
</ol>
<p>Ось спрощений приклад того, як виглядає стандартна текстова форма:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-xml" data-lang="xml"><span style="display:flex;"><span><span style="color:#f92672">&lt;p:sp&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#75715e">&lt;!-- 1. Non-visual shape properties (Identifiers, names) --&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;p:nvSpPr&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;p:cNvPr</span> <span style="color:#a6e22e">id=</span><span style="color:#e6db74">&#34;4&#34;</span> <span style="color:#a6e22e">name=</span><span style="color:#e6db74">&#34;Title Box 1&#34;</span><span style="color:#f92672">/&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;p:cNvSpPr&gt;</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&lt;a:spLocks</span> <span style="color:#a6e22e">noGrp=</span><span style="color:#e6db74">&#34;1&#34;</span><span style="color:#f92672">/&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;/p:cNvSpPr&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;p:nvPr&gt;</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&lt;p:ph</span> <span style="color:#a6e22e">type=</span><span style="color:#e6db74">&#34;title&#34;</span><span style="color:#f92672">/&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;/p:nvPr&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;/p:nvSpPr&gt;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#75715e">&lt;!-- 2. Visual shape properties (Position, size, geometry) --&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;p:spPr&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;a:xfrm&gt;</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&lt;a:off</span> <span style="color:#a6e22e">x=</span><span style="color:#e6db74">&#34;1524000&#34;</span> <span style="color:#a6e22e">y=</span><span style="color:#e6db74">&#34;1143000&#34;</span><span style="color:#f92672">/&gt;</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&lt;a:ext</span> <span style="color:#a6e22e">cx=</span><span style="color:#e6db74">&#34;9144000&#34;</span> <span style="color:#a6e22e">cy=</span><span style="color:#e6db74">&#34;1828800&#34;</span><span style="color:#f92672">/&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;/a:xfrm&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;a:prstGeom</span> <span style="color:#a6e22e">prst=</span><span style="color:#e6db74">&#34;rect&#34;</span><span style="color:#f92672">&gt;</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&lt;a:avLst/&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;/a:prstGeom&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;a:solidFill&gt;</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&lt;a:schemeClr</span> <span style="color:#a6e22e">val=</span><span style="color:#e6db74">&#34;accent1&#34;</span><span style="color:#f92672">/&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;/a:solidFill&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;/p:spPr&gt;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#75715e">&lt;!-- 3. Text Body (Paragraphs, runs, styling) --&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;p:txBody&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;a:bodyPr</span> <span style="color:#a6e22e">rtlCol=</span><span style="color:#e6db74">&#34;0&#34;</span> <span style="color:#a6e22e">anchor=</span><span style="color:#e6db74">&#34;ctr&#34;</span><span style="color:#f92672">/&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;a:lstStyle/&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;a:p&gt;</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&lt;a:r&gt;</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">&lt;a:rPr</span> <span style="color:#a6e22e">lang=</span><span style="color:#e6db74">&#34;en-US&#34;</span> <span style="color:#a6e22e">sz=</span><span style="color:#e6db74">&#34;3200&#34;</span> <span style="color:#a6e22e">b=</span><span style="color:#e6db74">&#34;1&#34;</span><span style="color:#f92672">/&gt;</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">&lt;a:t&gt;</span>Mission Critical Architecture<span style="color:#f92672">&lt;/a:t&gt;</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">&lt;/a:r&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;/a:p&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;/p:txBody&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;/p:sp&gt;</span>
</span></span></code></pre></div><h3 id="важливі-одиниці-вимірювання-emu-та-соті-пункту">Важливі одиниці вимірювання: EMU та соті пункту</h3>
<p>Зверніть увагу на числа координат у <code>&lt;a:xfrm&gt;</code>:</p>
<ul>
<li><code>x=\&quot;1524000\&quot;</code></li>
<li><code>cx=\&quot;9144000\&quot;</code></li>
</ul>
<p>Це <strong>англійські метричні одиниці (EMU)</strong>.</p>
<ul>
<li>$1 \text{ inch} = 914,400 \text{ EMUs}$</li>
<li>$1 \text{ cm} = 360,000 \text{ EMUs}$</li>
<li>$1 \text{ pt} = 12,700 \text{ EMUs}$</li>
</ul>
<p>EMUs дозволяють цілим числам представляти точні дроби як дюймів, так і міліметрів без помилок округлення з плаваючою комою на різних апаратних архітектурах.</p>
<p>Зверніть також увагу на розмір шрифту:</p>
<ul>
<li><code>sz=&quot;3200&quot;</code> означає <strong>32.00 pt</strong>. Розміри шрифтів у DrawingML вимірюються в сотих частинах пункту.</li>
</ul>
<h2 id="4-ланцюжок-успадкування-чому-форми-успадковують-невидимі-стилі">4. Ланцюжок успадкування: чому форми успадковують невидимі стилі</h2>
<p>Одним із найпоширеніших підводних каменів при реверс-інженерії файлів PPTX є припущення, що візуальне оформлення форми повністю задекларовано у її власному <code>slideX.xml</code>.</p>
<p>На практиці OpenXML спирається на сувору <strong>4-рівневу каскадну модель успадкування</strong>:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-text" data-lang="text"><span style="display:flex;"><span>[Theme: ppt/theme/theme1.xml]
</span></span><span style="display:flex;"><span>              │
</span></span><span style="display:flex;"><span>              ▼
</span></span><span style="display:flex;"><span>[Slide Master: ppt/slideMasters/slideMaster1.xml]
</span></span><span style="display:flex;"><span>              │
</span></span><span style="display:flex;"><span>              ▼
</span></span><span style="display:flex;"><span>[Slide Layout: ppt/slideLayouts/slideLayout1.xml]
</span></span><span style="display:flex;"><span>              │
</span></span><span style="display:flex;"><span>              ▼
</span></span><span style="display:flex;"><span>[Slide: ppt/slides/slide1.xml]
</span></span></code></pre></div><p>Якщо текстове поле у <code>slide1.xml</code> містить:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-xml" data-lang="xml"><span style="display:flex;"><span><span style="color:#f92672">&lt;a:p&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;a:r&gt;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">&lt;a:t&gt;</span>Revenue Projections<span style="color:#f92672">&lt;/a:t&gt;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&lt;/a:r&gt;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">&lt;/a:p&gt;</span>
</span></span></code></pre></div><p>У цьому фрагменті (<code>&lt;a:r&gt;</code>) не вказано жодного шрифту, жодного явного кольору та жодного розміру. Щоб зрозуміти, як PowerPoint відображає цей текст, ваш парсер повинен:</p>
<ol>
<li>Визначити тип заповнювача (<code>&lt;p:ph type=\&quot;title\&quot;/&gt;</code>).</li>
<li>Прочитати макет, зазначений у <code>slide1.xml.rels</code>.</li>
<li>Перевірити, чи <code>slideLayout1.xml</code> містить перевизначення стилів для цього заповнювача.</li>
<li>Використати <code>slideMaster1.xml</code> як резервний варіант для стилів текстового тіла заголовка за замовчуванням.</li>
<li>Відстежити кольорові токени, такі як <code>accent1</code> або <code>tx1</code>, у <code>theme1.xml</code>, щоб знайти шістнадцятковий код кольору.</li>
</ol>
<p>Якщо пропустити цей граф успадкування, ваш парсер неправильно прочитає стилі, пропустивши шрифти, розміри шрифтів та прив’язки макету.</p>
<h2 id="5-практичний-процес-зворотного-інжинірингу">5. Практичний процес зворотного інжинірингу</h2>
<p>Коли потрібно дослідити, як працює певна функція PowerPoint «під капотом» (наприклад, переходи morph, складні таблиці, векторні контури), дотримуйтесь цього емпіричного підходу:</p>
<h3 id="крок-1-створити-мінімальну-diff-pair">Крок 1: Створити мінімальну &ldquo;Diff Pair&rdquo;</h3>
<ol>
<li>Відкрийте PowerPoint і створіть порожній слайд.</li>
<li>Збережіть його як <code>before.pptx</code>.</li>
<li>Застосуйте саме одну зміну, яку ви хочете розкрити (наприклад, додайте тінь до кола, змініть стиль маркера, вставте вбудоване відео).</li>
<li>Збережіть його як <code>after.pptx</code>.</li>
</ol>
<h3 id="крок-2-розпакувати-обидва-архіви">Крок 2: Розпакувати обидва архіви</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>unzip before.pptx -d before/
</span></span><span style="display:flex;"><span>unzip after.pptx -d after/
</span></span></code></pre></div><h3 id="крок-3-форматувати-xml">Крок 3: Форматувати XML</h3>
<p>Необроблений XML у архівах Office зазвичай позбавлений відступів і символів нового рядка. Перед порівнянням відформатуйте файли:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>find before/ after/ -name <span style="color:#e6db74">&#34;*.xml&#34;</span> -exec xmllint --format <span style="color:#f92672">{}</span> --output <span style="color:#f92672">{}</span> <span style="color:#ae81ff">\;</span>
</span></span></code></pre></div><h3 id="крок-4-запустити-уніфікований-diff">Крок 4: Запустити уніфікований Diff</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>diff -uNr before/ after/ &gt; changes.patch
</span></span></code></pre></div><p>Перегляд <code>changes.patch</code> показує точну назву тегу, атрибут простору ієрархії контейнера, які додав PowerPoint. Це найшвидший спосіб виявити недокументовані або складні властивості схеми без копання в тисячах сторінок документації ECMA-376.</p>
<h2 id="6-створення-власного-мікро-двигуна-розпакування-модифікація-повторне-пакування">6. Створення власного мікро-двигуна: розпакування, модифікація, повторне пакування</h2>
<p>Іноді ви не хочете важку корпоративну залежність, таку як Apache POI або Microsoft OpenXML SDK — особливо в легких безсерверних середовищах (AWS Lambda, Cloudflare Workers, edge‑вузли).</p>
<p>Ось самодостатній шаблон Python, який демонструє, як безпечно розпакувати PPTX у пам&rsquo;яті, вставити власні дані за допомогою інструментів стандартної бібліотеки та знову упакувати його:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#f92672">import</span> zipfile
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> io
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> xml.etree.ElementTree <span style="color:#66d9ef">as</span> ET
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">def</span> <span style="color:#a6e22e">modify_slide_title</span>(input_pptx_bytes: bytes, new_title: str) <span style="color:#f92672">-&gt;</span> bytes:
</span></span><span style="display:flex;"><span>    input_zip <span style="color:#f92672">=</span> zipfile<span style="color:#f92672">.</span>ZipFile(io<span style="color:#f92672">.</span>BytesIO(input_pptx_bytes))
</span></span><span style="display:flex;"><span>    output_buffer <span style="color:#f92672">=</span> io<span style="color:#f92672">.</span>BytesIO()
</span></span><span style="display:flex;"><span>    
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">with</span> zipfile<span style="color:#f92672">.</span>ZipFile(output_buffer, <span style="color:#e6db74">&#34;w&#34;</span>, zipfile<span style="color:#f92672">.</span>ZIP_DEFLATED) <span style="color:#66d9ef">as</span> output_zip:
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">for</span> item <span style="color:#f92672">in</span> input_zip<span style="color:#f92672">.</span>infolist():
</span></span><span style="display:flex;"><span>            content <span style="color:#f92672">=</span> input_zip<span style="color:#f92672">.</span>read(item<span style="color:#f92672">.</span>filename)
</span></span><span style="display:flex;"><span>            
</span></span><span style="display:flex;"><span>            <span style="color:#75715e"># Target slide 1</span>
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">if</span> item<span style="color:#f92672">.</span>filename <span style="color:#f92672">==</span> <span style="color:#e6db74">&#34;ppt/slides/slide1.xml&#34;</span>:
</span></span><span style="display:flex;"><span>                namespaces <span style="color:#f92672">=</span> {
</span></span><span style="display:flex;"><span>                    <span style="color:#e6db74">&#39;p&#39;</span>: <span style="color:#e6db74">&#39;http://schemas.openxmlformats.org/presentationml/2006/main&#39;</span>,
</span></span><span style="display:flex;"><span>                    <span style="color:#e6db74">&#39;a&#39;</span>: <span style="color:#e6db74">&#39;http://schemas.openxmlformats.org/drawingml/2006/main&#39;</span>
</span></span><span style="display:flex;"><span>                }
</span></span><span style="display:flex;"><span>                
</span></span><span style="display:flex;"><span>                <span style="color:#75715e"># Register namespaces to preserve prefixes</span>
</span></span><span style="display:flex;"><span>                <span style="color:#66d9ef">for</span> prefix, uri <span style="color:#f92672">in</span> namespaces<span style="color:#f92672">.</span>items():
</span></span><span style="display:flex;"><span>                    ET<span style="color:#f92672">.</span>register_namespace(prefix, uri)
</span></span><span style="display:flex;"><span>                    
</span></span><span style="display:flex;"><span>                root <span style="color:#f92672">=</span> ET<span style="color:#f92672">.</span>fromstring(content)
</span></span><span style="display:flex;"><span>                
</span></span><span style="display:flex;"><span>                <span style="color:#75715e"># Find title placeholder text run</span>
</span></span><span style="display:flex;"><span>                <span style="color:#66d9ef">for</span> title_run <span style="color:#f92672">in</span> root<span style="color:#f92672">.</span>findall(<span style="color:#e6db74">&#34;.//p:sp[p:nvSpPr/p:nvPr/p:ph[@type=&#39;title&#39;]]//a:t&#34;</span>, namespaces):
</span></span><span style="display:flex;"><span>                    title_run<span style="color:#f92672">.</span>text <span style="color:#f92672">=</span> new_title
</span></span><span style="display:flex;"><span>                    <span style="color:#66d9ef">break</span>
</span></span><span style="display:flex;"><span>                
</span></span><span style="display:flex;"><span>                content <span style="color:#f92672">=</span> ET<span style="color:#f92672">.</span>tostring(root, encoding<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;utf-8&#34;</span>, xml_declaration<span style="color:#f92672">=</span><span style="color:#66d9ef">True</span>)
</span></span><span style="display:flex;"><span>            
</span></span><span style="display:flex;"><span>            output_zip<span style="color:#f92672">.</span>writestr(item, content)
</span></span><span style="display:flex;"><span>            
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> output_buffer<span style="color:#f92672">.</span>getvalue()
</span></span></code></pre></div><h3 id="ключові-підводні-камені-при-модифікації-файлів-на-рівні-сирих-байтів">Ключові підводні камені при модифікації файлів на рівні сирих байтів:</h3>
<ol>
<li><strong>Збереження простору імен</strong>: XML‑парсери часто переписують префікси (<code>xmlns:p</code> може стати <code>xmlns:ns0</code>). Хоча це дійсний XML, сувора внутрішня валідація схеми PowerPoint іноді відхиляє нестандартні псевдоніми префіксів. Реєструйте простори імен явно.</li>
<li><strong>Методи стиснення ZIP</strong>: Переконайтеся, що ви записуєте файли назад, використовуючи стандартне стиснення deflate (<code>zipfile.ZIP_DEFLATED</code>).</li>
<li><strong>Скидання потоку</strong>: Завжди перевіряйте, що ваш буфер zip закривається і повністю скидається перед передачею байтів далі.</li>
<li><strong>Збереження зв&rsquo;язків</strong>: Якщо ви видаляєте слайд, ви також повинні видалити його запис у <code>ppt/presentation.xml</code>, видалити його зв&rsquo;язок у <code>ppt/_rels/presentation.xml.rels</code> і очистити його тип вмісту у <code>[Content_Types].xml</code>.</li>
</ol>
<h2 id="7-розгляд-продуктивності-та-безпеки">7. Розгляд продуктивності та безпеки</h2>
<p>Реверс-інженерія файлів PPTX — це не лише редагування слайдів; це також аудит того, що потрапляє у ваші системи.</p>
<h3 id="безпека-billion-laughs-та-xxe">Безпека: Billion Laughs та XXE</h3>
<p>Оскільки файли PPTX парсять XML, будь‑який серверний конвеєр, що приймає презентації, надіслані користувачами, вразливий до:</p>
<ul>
<li><strong>Впровадження зовнішньої сутності XML (XXE)</strong>: Шкідливий XML, який намагається отримати доступ до <code>/etc/passwd</code> або запитати внутрішні кінцеві точки метаданих хмари (<code>http://169.254.169.254/</code>).</li>
<li><strong>Атаки розширення сутностей (Billion Laughs)</strong>: Експоненційні цикли сутностей, що вичерпують оперативну пам&rsquo;ять системи.</li>
</ul>
<p><strong>Пом&rsquo;якшення</strong>: Завжди вимикайте <code>resolve_entities</code>, <code>load_dtd</code> та зовнішнє мережеве розв&rsquo;язання у вашому XML‑парсері (наприклад, використовуючи <code>defusedxml</code> у Python).</p>
<h3 id="безпека-навантаження-макросів-та-приховані-потоки">Безпека: Навантаження Макросів та Приховані Потоки</h3>
<p>Перевіряйте файли на наявність вмісту <code>.pptm</code>, що маскується під розширенням <code>.pptx</code>. Слідкуйте за <code>ppt/vbaProject.bin</code>, який містить скомпільований код Visual Basic. У стандартних <code>.pptx</code> файлах код VBA заборонений; виявлення посилань на бінарні корисні навантаження у зв’язках має негайно викликати позначки карантину.</p>
<h2 id="висновок">Висновок</h2>
<p>Зворотний інжиніринг <code>.pptx</code> файлів розкриває таємниці програмного забезпечення для презентацій. Коли ви розумієте, що файли PowerPoint — це просто структуровані zip‑пакети, заповнені координатами, посиланнями на схеми та деревами XML‑зв’язків, ви більше не обмежені існуючими сторонніми абстракціями.</p>
<p>Незалежно від того, чи оптимізуєте ви пропускну здатність генерації слайдів, пишете власні автоматизовані санітайзери, чи усуваєте проблеми з рендерингом, прямий погляд на базову архітектуру OpenXML дає вам повний контроль над конвеєром презентації.</p>
<h2 id="поширені-запитання-faq">Поширені запитання (FAQ)</h2>
<p>**Q: Чи можна конвертувати .pptx у звичайну папку та редагувати файли безпосередньо в IDE?</p>
<p><strong>A1:</strong> Так, ви можете розпакувати архів, відредагувати XML у редакторі типу VS Code і знову заархівувати вміст каталогу, щоб відкрити його у PowerPoint.</p>
<p>**Q: Чому PowerPoint повідомляє, що мій вручну змінений файл PPTX потребує ремонту?</p>
<p><strong>A2:</strong> Це зазвичай трапляється, якщо ви внесли некоректний XML, пропустили новий ресурс у файлі <code>[Content_Types].xml</code> або залишили «повішений» посилання у пов’язаному файлі <code>.rels</code>.</p>
<p>**Q: Яку одиницю вимірювання використовує PowerPoint для позицій та відступів форм?</p>
<p><strong>A3:</strong> PowerPoint використовує English Metric Units (EMUs), де 1 дюйм дорівнює 914 400 EMU, а 1 пункт — 12 700 EMU.</p>
<p>**Q: Як я можу <a href="https://products.fileformat.com/presentation/python/python-pptx/">програмно витягнути</a> усі зображення з презентації без зовнішніх бібліотек?</p>
<p><strong>A4:</strong> Просто відкрийте файл <code>.pptx</code> за допомогою будь-якої стандартної zip‑утиліти та витягніть усі бінарні файли, розташовані у каталозі <code>ppt/media/</code>.</p>
<p>**Q: Чи безпечно розбирати (парсити) завантажені користувачами PPTX‑файли за допомогою стандартних XML‑парсерів?</p>
<p><strong>A5:</strong> Ні, вам потрібно посилити ваш парсер або використовувати безпечні обгортки, такі як <code>defusedxml</code>, щоб блокувати атаки XML External Entity (XXE) та zip‑бомби.</p>
<h2 id="дивіться-також">Дивіться також</h2>
<ul>
<li><a href="https://blog.fileformat.com/presentation/powerpoint-file-formats/">Формати файлів презентацій на FileFormat.com?</a></li>
<li><a href="https://blog.fileformat.com/presentation/apache-poi-api-to-access-powerpoint-file-formats/">Java API для доступу до форматів файлів PowerPoint</a></li>
<li><a href="https://blog.fileformat.com/presentation/odp-vs-pptx-opendocument-vs-microsoft-powerpoint-format-comparison/">ODP проти PPTX: OpenDocument проти формату презентацій Microsoft PowerPoint</a></li>
<li><a href="https://blog.fileformat.com/presentation/difference-between-ppt-and-pptx/">Різниця між PPT та PPTX</a></li>
<li><a href="https://blog.fileformat.com/presentation/create-presentation-in-java-with-apache-poi-api/">Створення презентації PowerPoint у Java за допомогою Apache POI API</a></li>
</ul>
<!-- raw HTML omitted -->
]]></content:encoded>
    </item>
    
  </channel>
</rss>
