summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuigi Scarso <luigi.scarso@gmail.com>2023-05-23 17:09:02 +0000
committerLuigi Scarso <luigi.scarso@gmail.com>2023-05-23 17:09:02 +0000
commit528c3b5af1e5c594dd962277fc8d54e6a2303d07 (patch)
tree14be3aebd130dea3cae991d94119705e8a8383fa
parenta2fc32755a1bb6e59bfaaa2e8ec69ada58bd026c (diff)
fixes decryption failure on unreadable perms (Paweł Jackowski)
git-svn-id: svn://tug.org/texlive/trunk@67196 c570f23f-e606-0410-a88d-b1316a301751
-rw-r--r--Build/source/libs/pplib/ChangeLog4
-rw-r--r--Build/source/libs/pplib/pplib-src/doc/_build/doctrees/environment.picklebin32928 -> 32867 bytes
-rw-r--r--Build/source/libs/pplib/pplib-src/doc/_build/doctrees/ppapi-1.x.doctreebin167607 -> 167537 bytes
-rw-r--r--Build/source/libs/pplib/pplib-src/doc/_build/doctrees/ppapi-2.x.doctreebin167117 -> 169734 bytes
-rw-r--r--Build/source/libs/pplib/pplib-src/doc/_build/doctrees/ppcode.doctreebin64496 -> 66451 bytes
-rw-r--r--Build/source/libs/pplib/pplib-src/doc/_build/doctrees/pplib.doctreebin3371 -> 3454 bytes
-rw-r--r--Build/source/libs/pplib/pplib-src/doc/_build/doctrees/ppnew.doctreebin25753 -> 25729 bytes
-rw-r--r--Build/source/libs/pplib/pplib-src/doc/_build/html/_sources/ppapi-2.x.rst.txt33
-rw-r--r--Build/source/libs/pplib/pplib-src/doc/_build/html/_sources/ppcode.rst.txt8
-rw-r--r--Build/source/libs/pplib/pplib-src/doc/_build/html/genindex.html2
-rw-r--r--Build/source/libs/pplib/pplib-src/doc/_build/html/ppapi-1.x.html2
-rw-r--r--Build/source/libs/pplib/pplib-src/doc/_build/html/ppapi-2.x.html34
-rw-r--r--Build/source/libs/pplib/pplib-src/doc/_build/html/ppcode.html309
-rw-r--r--Build/source/libs/pplib/pplib-src/doc/_build/html/pplib.html4
-rw-r--r--Build/source/libs/pplib/pplib-src/doc/_build/html/ppnew.html2
-rw-r--r--Build/source/libs/pplib/pplib-src/doc/_build/html/search.html2
-rw-r--r--Build/source/libs/pplib/pplib-src/doc/_build/html/searchindex.js2
-rw-r--r--Build/source/libs/pplib/pplib-src/doc/make.bat2
-rw-r--r--Build/source/libs/pplib/pplib-src/doc/ppapi-2.x.rst33
-rw-r--r--Build/source/libs/pplib/pplib-src/doc/ppcode.rst8
-rw-r--r--Build/source/libs/pplib/pplib-src/src/Makefile.vc3
-rw-r--r--Build/source/libs/pplib/pplib-src/src/ppapi.h2
-rw-r--r--Build/source/libs/pplib/pplib-src/src/ppcrypt.c430
-rw-r--r--Build/source/libs/pplib/pplib-src/src/ppcrypt.h34
-rw-r--r--Build/source/libs/pplib/pplib-src/src/pptest2.c46
25 files changed, 643 insertions, 317 deletions
diff --git a/Build/source/libs/pplib/ChangeLog b/Build/source/libs/pplib/ChangeLog
index dc14799022f..a9e6d8fa692 100644
--- a/Build/source/libs/pplib/ChangeLog
+++ b/Build/source/libs/pplib/ChangeLog
@@ -1,2 +1,6 @@
+2023-05-23 Luigi Scarso luigi.scarso@gmail.com
+ * sync with the upstrem repo.:
+ fixes decryption failure on unreadable perms (Paweł Jackowski)
+
2020-04-18 Luigi Scarso luigi.scarso@gmail.com
* Moved luatexdir/luapplib under libs/pplib. \ No newline at end of file
diff --git a/Build/source/libs/pplib/pplib-src/doc/_build/doctrees/environment.pickle b/Build/source/libs/pplib/pplib-src/doc/_build/doctrees/environment.pickle
index c4d657a1115..5d5fcb14a40 100644
--- a/Build/source/libs/pplib/pplib-src/doc/_build/doctrees/environment.pickle
+++ b/Build/source/libs/pplib/pplib-src/doc/_build/doctrees/environment.pickle
Binary files differ
diff --git a/Build/source/libs/pplib/pplib-src/doc/_build/doctrees/ppapi-1.x.doctree b/Build/source/libs/pplib/pplib-src/doc/_build/doctrees/ppapi-1.x.doctree
index bd22032c659..54e4f6f3e30 100644
--- a/Build/source/libs/pplib/pplib-src/doc/_build/doctrees/ppapi-1.x.doctree
+++ b/Build/source/libs/pplib/pplib-src/doc/_build/doctrees/ppapi-1.x.doctree
Binary files differ
diff --git a/Build/source/libs/pplib/pplib-src/doc/_build/doctrees/ppapi-2.x.doctree b/Build/source/libs/pplib/pplib-src/doc/_build/doctrees/ppapi-2.x.doctree
index d8c91b48bed..ddf23cd91c0 100644
--- a/Build/source/libs/pplib/pplib-src/doc/_build/doctrees/ppapi-2.x.doctree
+++ b/Build/source/libs/pplib/pplib-src/doc/_build/doctrees/ppapi-2.x.doctree
Binary files differ
diff --git a/Build/source/libs/pplib/pplib-src/doc/_build/doctrees/ppcode.doctree b/Build/source/libs/pplib/pplib-src/doc/_build/doctrees/ppcode.doctree
index a33b506208e..a8e4dba8cb1 100644
--- a/Build/source/libs/pplib/pplib-src/doc/_build/doctrees/ppcode.doctree
+++ b/Build/source/libs/pplib/pplib-src/doc/_build/doctrees/ppcode.doctree
Binary files differ
diff --git a/Build/source/libs/pplib/pplib-src/doc/_build/doctrees/pplib.doctree b/Build/source/libs/pplib/pplib-src/doc/_build/doctrees/pplib.doctree
index 0d5e84fe5a5..36be14515fd 100644
--- a/Build/source/libs/pplib/pplib-src/doc/_build/doctrees/pplib.doctree
+++ b/Build/source/libs/pplib/pplib-src/doc/_build/doctrees/pplib.doctree
Binary files differ
diff --git a/Build/source/libs/pplib/pplib-src/doc/_build/doctrees/ppnew.doctree b/Build/source/libs/pplib/pplib-src/doc/_build/doctrees/ppnew.doctree
index 5c152d321a5..f79b5923a53 100644
--- a/Build/source/libs/pplib/pplib-src/doc/_build/doctrees/ppnew.doctree
+++ b/Build/source/libs/pplib/pplib-src/doc/_build/doctrees/ppnew.doctree
Binary files differ
diff --git a/Build/source/libs/pplib/pplib-src/doc/_build/html/_sources/ppapi-2.x.rst.txt b/Build/source/libs/pplib/pplib-src/doc/_build/html/_sources/ppapi-2.x.rst.txt
index 250cd8fcd35..c6779145a56 100644
--- a/Build/source/libs/pplib/pplib-src/doc/_build/html/_sources/ppapi-2.x.rst.txt
+++ b/Build/source/libs/pplib/pplib-src/doc/_build/html/_sources/ppapi-2.x.rst.txt
@@ -677,15 +677,14 @@ It is a common practise to *protect* documents with an empty password. Such docu
for a password), but some features (eg. printing) may restricted by the application.
When ``pplib`` detects encryption, it follows Acrobat approach and first tries an empty password. If it succeeds, ``pplib`` proceeeds normally, providing
-an access to decrypted strings and streams, as if they weren't ciphered. If the document is protected with non-empty password, ``pplib`` gives
-a way to provide a password and proceed. Until you provide a password, ``ppdoc`` object returned by ``ppdoc_load()`` function has all object wntries
-set to ``null``.
+an access to decrypted strings and streams, as if they weren't ciphered. If the document is protected with non-empty password, you have to call
+``ppdoc_crypt_pass()``. Until you provide a password, ``ppdoc`` object returned by ``ppdoc_load()`` function has all object entries set to ``null``.
-After loading a document you should check encryption status with::
+Once the document is loaded, encryption status can be checked with::
ppcrypt_status ppdoc_crypt_status (ppdoc *pdf);
-``ppcrypt_status`` (integer) may have the following values:
+``ppcrypt_status`` (enum) may have the following values:
``PPCRYPT_NONE`` - no encryption, go ahead
``PPCRYPT_DONE`` - encryption present but password succeeded, go ahead
@@ -697,10 +696,12 @@ If a password is needed, you can provide one with::
ppcrypt_status ppdoc_crypt_pass (ppdoc *pdf, const void *userpass, size_t userpasslength,
const void *ownerpass, size_t ownerpasslength);
-Well, yes, there are actually two passwords in encrypted documents. Relation between them is obscure to me, but enough
-to know that having one of them is enough to decrypt the document. If you know the password, you probably mean
-``userpass``, in which case you should put ``NULL`` as ``ownerpass``. The function returns ``PPCRYPT_DONE`` if the password
-succeeds and the previous status otherwise. Your custom loader function may look like that::
+Providing one of two is enough to decrypt the document.
+It is ok to use the same password for owner and user -- ``pplib`` will try both.
+
+The function returns ``PPCRYPT_DONE`` if the password succeeds and the previous crypt status otherwise.
+
+Your custom loader function may look like that::
ppdoc *pdf;
pdf = ppdoc_load("file.pdf");
@@ -712,8 +713,7 @@ succeeds and the previous status otherwise. Your custom loader function may look
case PPCRYPT_DONE:
return pdf;
case PPCRYPT_PASS:
- if (ppdoc_crypt_pass(pdf, "dummy", 5, NULL, 0) == PPCRYPT_DONE ||
- ppdoc_crypt_pass(pdf, NULL, 0, "dummy", 5) == PPCRYPT_DONE)
+ if (ppdoc_crypt_pass(pdf, "dummy", 5, "dummy", 5) == PPCRYPT_DONE)
return pdf;
printf("sorry, password needed\n");
ppdoc_free(pdf);
@@ -724,7 +724,7 @@ succeeds and the previous status otherwise. Your custom loader function may look
return NULL;
}
-[If you get ``PPCRYPT_FAIL`` it might mean *I failed*, so treat as a bug.]
+See ``pplib`` tests suite for a complete code.
If you'd like to know what permissions are given/restricted to encrypted document::
@@ -751,6 +751,15 @@ In encrypted documents most of streams are encrypted. To check if a given stream
Encryption is independent from compression, don't confuse with ``ppstream_compressed()``
+.. caution::
+ Starting from ``pplib v2.10`` all passwords should be passed as ``UTF-8``.
+ Earlier PDF encryption algorithms (/V 1..4, PDF 1.7) were based on ``PdfDocEncoding``.
+ Newer algorithms (/V 5, PDF 1.8-2.0) expect Unicode encoded as ``UTF-8``.
+ ``pplib`` API now expects ``UTF-8`` and if opening documents with older encryption methods,
+ it tries to make a conversion to 8-bit encoding. In earlier versions ``pplib`` didn't
+ make any password preprocessing, treating them as raw byte arrays.
+ So in case of passwords with fancy characters, it may behave differently.
+
Pages
-----
diff --git a/Build/source/libs/pplib/pplib-src/doc/_build/html/_sources/ppcode.rst.txt b/Build/source/libs/pplib/pplib-src/doc/_build/html/_sources/ppcode.rst.txt
index ebe92465d80..e9f6dc7adbd 100644
--- a/Build/source/libs/pplib/pplib-src/doc/_build/html/_sources/ppcode.rst.txt
+++ b/Build/source/libs/pplib/pplib-src/doc/_build/html/_sources/ppcode.rst.txt
@@ -95,7 +95,7 @@ v2.05
uint8_t instead of ppbyte in internals; ppbyte intent is "the most natural 8-bit integer", so it is 'char',
but internally we almost always need uint8_t (char may be signed or not..)
-TODO
-====
-- external streams (egzotic)
-
+v2.10
+-----
+Rework on encryption; algorithms /V5 /R6.
+Passwords passed to ppdoc_crypt_pass() should be UTF-8 (backward incompatible).
diff --git a/Build/source/libs/pplib/pplib-src/doc/_build/html/genindex.html b/Build/source/libs/pplib/pplib-src/doc/_build/html/genindex.html
index 24eed9d3c25..4e8b3647578 100644
--- a/Build/source/libs/pplib/pplib-src/doc/_build/html/genindex.html
+++ b/Build/source/libs/pplib/pplib-src/doc/_build/html/genindex.html
@@ -79,7 +79,7 @@
</div>
<div class="footer" role="contentinfo">
&#169; Copyright 2019, p.jackowski@gust.org.pl.
- Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.8.5.
+ Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.8.6.
</div>
</body>
</html> \ No newline at end of file
diff --git a/Build/source/libs/pplib/pplib-src/doc/_build/html/ppapi-1.x.html b/Build/source/libs/pplib/pplib-src/doc/_build/html/ppapi-1.x.html
index 838aee52175..186a5c6df2e 100644
--- a/Build/source/libs/pplib/pplib-src/doc/_build/html/ppapi-1.x.html
+++ b/Build/source/libs/pplib/pplib-src/doc/_build/html/ppapi-1.x.html
@@ -1024,7 +1024,7 @@ of some PDF boject fails due to invalid offsets. By default, <code class="docuti
</div>
<div class="footer" role="contentinfo">
&#169; Copyright 2019, p.jackowski@gust.org.pl.
- Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.8.5.
+ Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.8.6.
</div>
</body>
</html> \ No newline at end of file
diff --git a/Build/source/libs/pplib/pplib-src/doc/_build/html/ppapi-2.x.html b/Build/source/libs/pplib/pplib-src/doc/_build/html/ppapi-2.x.html
index cac0fcec997..9222889331d 100644
--- a/Build/source/libs/pplib/pplib-src/doc/_build/html/ppapi-2.x.html
+++ b/Build/source/libs/pplib/pplib-src/doc/_build/html/ppapi-2.x.html
@@ -752,14 +752,13 @@ In that form they are unreadable and rather useless, you can’t even rewrite su
It is a common practise to <em>protect</em> documents with an empty password. Such documents remain readable in Acrobat (just opens them without prompting
for a password), but some features (eg. printing) may restricted by the application.</p>
<p>When <code class="docutils literal notranslate"><span class="pre">pplib</span></code> detects encryption, it follows Acrobat approach and first tries an empty password. If it succeeds, <code class="docutils literal notranslate"><span class="pre">pplib</span></code> proceeeds normally, providing
-an access to decrypted strings and streams, as if they weren’t ciphered. If the document is protected with non-empty password, <code class="docutils literal notranslate"><span class="pre">pplib</span></code> gives
-a way to provide a password and proceed. Until you provide a password, <code class="docutils literal notranslate"><span class="pre">ppdoc</span></code> object returned by <code class="docutils literal notranslate"><span class="pre">ppdoc_load()</span></code> function has all object wntries
-set to <code class="docutils literal notranslate"><span class="pre">null</span></code>.</p>
-<p>After loading a document you should check encryption status with:</p>
+an access to decrypted strings and streams, as if they weren’t ciphered. If the document is protected with non-empty password, you have to call
+<code class="docutils literal notranslate"><span class="pre">ppdoc_crypt_pass()</span></code>. Until you provide a password, <code class="docutils literal notranslate"><span class="pre">ppdoc</span></code> object returned by <code class="docutils literal notranslate"><span class="pre">ppdoc_load()</span></code> function has all object entries set to <code class="docutils literal notranslate"><span class="pre">null</span></code>.</p>
+<p>Once the document is loaded, encryption status can be checked with:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppcrypt_status</span> <span class="n">ppdoc_crypt_status</span> <span class="p">(</span><span class="n">ppdoc</span> <span class="o">*</span><span class="n">pdf</span><span class="p">);</span>
</pre></div>
</div>
-<p><code class="docutils literal notranslate"><span class="pre">ppcrypt_status</span></code> (integer) may have the following values:</p>
+<p><code class="docutils literal notranslate"><span class="pre">ppcrypt_status</span></code> (enum) may have the following values:</p>
<blockquote>
<div><code class="docutils literal notranslate"><span class="pre">PPCRYPT_NONE</span></code> - no encryption, go ahead
<code class="docutils literal notranslate"><span class="pre">PPCRYPT_DONE</span></code> - encryption present but password succeeded, go ahead
@@ -770,10 +769,10 @@ set to <code class="docutils literal notranslate"><span class="pre">null</span><
<span class="n">const</span> <span class="n">void</span> <span class="o">*</span><span class="n">ownerpass</span><span class="p">,</span> <span class="n">size_t</span> <span class="n">ownerpasslength</span><span class="p">);</span>
</pre></div>
</div>
-<p>Well, yes, there are actually two passwords in encrypted documents. Relation between them is obscure to me, but enough
-to know that having one of them is enough to decrypt the document. If you know the password, you probably mean
-<code class="docutils literal notranslate"><span class="pre">userpass</span></code>, in which case you should put <code class="docutils literal notranslate"><span class="pre">NULL</span></code> as <code class="docutils literal notranslate"><span class="pre">ownerpass</span></code>. The function returns <code class="docutils literal notranslate"><span class="pre">PPCRYPT_DONE</span></code> if the password
-succeeds and the previous status otherwise. Your custom loader function may look like that:</p>
+<p>Providing one of two is enough to decrypt the document.
+It is ok to use the same password for owner and user – <code class="docutils literal notranslate"><span class="pre">pplib</span></code> will try both.</p>
+<p>The function returns <code class="docutils literal notranslate"><span class="pre">PPCRYPT_DONE</span></code> if the password succeeds and the previous crypt status otherwise.</p>
+<p>Your custom loader function may look like that:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppdoc</span> <span class="o">*</span><span class="n">pdf</span><span class="p">;</span>
<span class="n">pdf</span> <span class="o">=</span> <span class="n">ppdoc_load</span><span class="p">(</span><span class="s2">&quot;file.pdf&quot;</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="n">pdf</span> <span class="o">==</span> <span class="n">NULL</span><span class="p">)</span>
@@ -784,8 +783,7 @@ succeeds and the previous status otherwise. Your custom loader function may look
<span class="n">case</span> <span class="n">PPCRYPT_DONE</span><span class="p">:</span>
<span class="k">return</span> <span class="n">pdf</span><span class="p">;</span>
<span class="n">case</span> <span class="n">PPCRYPT_PASS</span><span class="p">:</span>
- <span class="k">if</span> <span class="p">(</span><span class="n">ppdoc_crypt_pass</span><span class="p">(</span><span class="n">pdf</span><span class="p">,</span> <span class="s2">&quot;dummy&quot;</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="n">NULL</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span> <span class="o">==</span> <span class="n">PPCRYPT_DONE</span> <span class="o">||</span>
- <span class="n">ppdoc_crypt_pass</span><span class="p">(</span><span class="n">pdf</span><span class="p">,</span> <span class="n">NULL</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="s2">&quot;dummy&quot;</span><span class="p">,</span> <span class="mi">5</span><span class="p">)</span> <span class="o">==</span> <span class="n">PPCRYPT_DONE</span><span class="p">)</span>
+ <span class="k">if</span> <span class="p">(</span><span class="n">ppdoc_crypt_pass</span><span class="p">(</span><span class="n">pdf</span><span class="p">,</span> <span class="s2">&quot;dummy&quot;</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="s2">&quot;dummy&quot;</span><span class="p">,</span> <span class="mi">5</span><span class="p">)</span> <span class="o">==</span> <span class="n">PPCRYPT_DONE</span><span class="p">)</span>
<span class="k">return</span> <span class="n">pdf</span><span class="p">;</span>
<span class="n">printf</span><span class="p">(</span><span class="s2">&quot;sorry, password needed</span><span class="se">\n</span><span class="s2">&quot;</span><span class="p">);</span>
<span class="n">ppdoc_free</span><span class="p">(</span><span class="n">pdf</span><span class="p">);</span>
@@ -797,7 +795,7 @@ succeeds and the previous status otherwise. Your custom loader function may look
<span class="p">}</span>
</pre></div>
</div>
-<p>[If you get <code class="docutils literal notranslate"><span class="pre">PPCRYPT_FAIL</span></code> it might mean <em>I failed</em>, so treat as a bug.]</p>
+<p>See <code class="docutils literal notranslate"><span class="pre">pplib</span></code> tests suite for a complete code.</p>
<p>If you’d like to know what permissions are given/restricted to encrypted document:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">ppint</span> <span class="n">ppdoc_permissions</span> <span class="p">(</span><span class="n">ppdoc</span> <span class="o">*</span><span class="n">pdf</span><span class="p">);</span>
</pre></div>
@@ -821,6 +819,16 @@ So except the check to <code class="docutils literal notranslate"><span class="p
</pre></div>
</div>
<p>Encryption is independent from compression, don’t confuse with <code class="docutils literal notranslate"><span class="pre">ppstream_compressed()</span></code></p>
+<div class="admonition caution">
+<p class="first admonition-title">Caution</p>
+<p class="last">Starting from <code class="docutils literal notranslate"><span class="pre">pplib</span> <span class="pre">v2.10</span></code> all passwords should be passed as <code class="docutils literal notranslate"><span class="pre">UTF-8</span></code>.
+Earlier PDF encryption algorithms (/V 1..4, PDF 1.7) were based on <code class="docutils literal notranslate"><span class="pre">PdfDocEncoding</span></code>.
+Newer algorithms (/V 5, PDF 1.8-2.0) expect Unicode encoded as <code class="docutils literal notranslate"><span class="pre">UTF-8</span></code>.
+<code class="docutils literal notranslate"><span class="pre">pplib</span></code> API now expects <code class="docutils literal notranslate"><span class="pre">UTF-8</span></code> and if opening documents with older encryption methods,
+it tries to make a conversion to 8-bit encoding. In earlier versions <code class="docutils literal notranslate"><span class="pre">pplib</span></code> didn’t
+make any password preprocessing, treating them as raw byte arrays.
+So in case of passwords with fancy characters, it may behave differently.</p>
+</div>
</div>
<div class="section" id="pages">
<h2>Pages<a class="headerlink" href="#pages" title="Permalink to this headline">¶</a></h2>
@@ -1025,7 +1033,7 @@ of some PDF boject fails due to invalid offsets. By default, <code class="docuti
</div>
<div class="footer" role="contentinfo">
&#169; Copyright 2019, p.jackowski@gust.org.pl.
- Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.8.5.
+ Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.8.6.
</div>
</body>
</html> \ No newline at end of file
diff --git a/Build/source/libs/pplib/pplib-src/doc/_build/html/ppcode.html b/Build/source/libs/pplib/pplib-src/doc/_build/html/ppcode.html
index 8645450d8ec..fdd52f528de 100644
--- a/Build/source/libs/pplib/pplib-src/doc/_build/html/ppcode.html
+++ b/Build/source/libs/pplib/pplib-src/doc/_build/html/ppcode.html
@@ -63,9 +63,9 @@
<li><a class="reference internal" href="#v2-03">v2.03</a></li>
<li><a class="reference internal" href="#v2-04">v2.04</a></li>
<li><a class="reference internal" href="#v2-05">v2.05</a></li>
+<li><a class="reference internal" href="#v2-10">v2.10</a></li>
</ul>
</li>
-<li><a class="reference internal" href="#todo">TODO</a></li>
</ul>
<h4>Previous topic</h4>
@@ -212,143 +212,175 @@
<div class="section" id="example-2">
<h2>Example 2<a class="headerlink" href="#example-2" title="Permalink to this headline">¶</a></h2>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span>
-<span class="c1">#include &lt;stdio.h&gt;</span>
-<span class="c1">#include &lt;assert.h&gt;</span>
-<span class="c1">#include &quot;ppapi.h&quot;</span>
+#include &lt;stdio.h&gt;
+#include &lt;assert.h&gt;
+#include &quot;ppapi.h&quot;
-<span class="o">/*</span>
-<span class="n">static</span> <span class="n">const</span> <span class="n">char</span> <span class="o">*</span> <span class="n">get_file_name</span> <span class="p">(</span><span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">path</span><span class="p">)</span>
-<span class="p">{</span>
- <span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">fn</span><span class="p">,</span> <span class="o">*</span><span class="n">p</span><span class="p">;</span>
- <span class="k">for</span> <span class="p">(</span><span class="n">fn</span> <span class="o">=</span> <span class="n">p</span> <span class="o">=</span> <span class="n">path</span><span class="p">;</span> <span class="o">*</span><span class="n">p</span> <span class="o">!=</span> <span class="s1">&#39;</span><span class="se">\0</span><span class="s1">&#39;</span><span class="p">;</span> <span class="o">++</span><span class="n">p</span><span class="p">)</span>
- <span class="k">if</span> <span class="p">(</span><span class="o">*</span><span class="n">p</span> <span class="o">==</span> <span class="s1">&#39;</span><span class="se">\\</span><span class="s1">&#39;</span> <span class="o">||</span> <span class="o">*</span><span class="n">p</span> <span class="o">==</span> <span class="s1">&#39;/&#39;</span><span class="p">)</span>
- <span class="n">fn</span> <span class="o">=</span> <span class="n">p</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
- <span class="k">return</span> <span class="n">fn</span><span class="p">;</span>
-<span class="p">}</span>
-<span class="o">*/</span>
+/*
+static const char * get_file_name (const char *path)
+{
+ const char *fn, *p;
+ for (fn = p = path; *p != &#39;\0&#39;; ++p)
+ if (*p == &#39;\\&#39; || *p == &#39;/&#39;)
+ fn = p + 1;
+ return fn;
+}
+*/
-<span class="n">static</span> <span class="n">void</span> <span class="n">box_info</span> <span class="p">(</span><span class="n">ppdict</span> <span class="o">*</span><span class="n">pagedict</span><span class="p">,</span> <span class="n">FILE</span> <span class="o">*</span><span class="n">fh</span><span class="p">)</span>
-<span class="p">{</span>
- <span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">boxes</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span><span class="s2">&quot;MediaBox&quot;</span><span class="p">,</span> <span class="s2">&quot;CropBox&quot;</span><span class="p">,</span> <span class="s2">&quot;BleedBox&quot;</span><span class="p">,</span> <span class="s2">&quot;TrimBox&quot;</span><span class="p">,</span> <span class="s2">&quot;ArtBox&quot;</span><span class="p">};</span>
- <span class="n">pprect</span> <span class="n">rect</span><span class="p">;</span>
- <span class="n">size_t</span> <span class="n">i</span><span class="p">;</span>
- <span class="k">for</span> <span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">sizeof</span><span class="p">(</span><span class="n">boxes</span><span class="p">)</span> <span class="o">/</span> <span class="n">sizeof</span><span class="p">(</span><span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="p">);</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span>
- <span class="k">if</span> <span class="p">(</span><span class="n">ppdict_get_box</span><span class="p">(</span><span class="n">pagedict</span><span class="p">,</span> <span class="n">boxes</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="o">&amp;</span><span class="n">rect</span><span class="p">))</span>
- <span class="n">fprintf</span><span class="p">(</span><span class="n">fh</span><span class="p">,</span> <span class="s2">&quot;</span><span class="si">%%%%</span><span class="s2"> </span><span class="si">%s</span><span class="s2"> [</span><span class="si">%f</span><span class="s2"> </span><span class="si">%f</span><span class="s2"> </span><span class="si">%f</span><span class="s2"> </span><span class="si">%f</span><span class="s2">]</span><span class="se">\n</span><span class="s2">&quot;</span><span class="p">,</span> <span class="n">boxes</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">rect</span><span class="o">.</span><span class="n">lx</span><span class="p">,</span> <span class="n">rect</span><span class="o">.</span><span class="n">ly</span><span class="p">,</span> <span class="n">rect</span><span class="o">.</span><span class="n">rx</span><span class="p">,</span> <span class="n">rect</span><span class="o">.</span><span class="n">ry</span><span class="p">);</span>
-<span class="p">}</span>
+static void box_info (ppdict *pagedict, FILE *fh)
+{
+ const char *boxes[] = {&quot;MediaBox&quot;, &quot;CropBox&quot;, &quot;BleedBox&quot;, &quot;TrimBox&quot;, &quot;ArtBox&quot;};
+ pprect rect;
+ size_t i;
+ for (i = 0; i &lt; sizeof(boxes) / sizeof(const char *); ++i)
+ if (ppdict_get_box(pagedict, boxes[i], &amp;rect))
+ fprintf(fh, &quot;%%%% %s [%f %f %f %f]\n&quot;, boxes[i], rect.lx, rect.ly, rect.rx, rect.ry);
+}
-<span class="n">static</span> <span class="nb">int</span> <span class="n">usage</span> <span class="p">(</span><span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">argv0</span><span class="p">)</span>
-<span class="p">{</span>
- <span class="n">printf</span><span class="p">(</span><span class="s2">&quot;pplib &quot;</span> <span class="n">pplib_version</span> <span class="s2">&quot;, &quot;</span> <span class="n">pplib_author</span> <span class="s2">&quot;</span><span class="se">\n</span><span class="s2">&quot;</span><span class="p">);</span>
- <span class="n">printf</span><span class="p">(</span><span class="s2">&quot;usage: </span><span class="si">%s</span><span class="s2"> file1.pdf file2.pdf ...</span><span class="se">\n</span><span class="s2">&quot;</span><span class="p">,</span> <span class="n">argv0</span><span class="p">);</span>
- <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
-<span class="p">}</span>
+static int usage (const char *argv0)
+{
+ printf(&quot;pplib &quot; pplib_version &quot;, &quot; pplib_author &quot;\n&quot;);
+ printf(&quot;usage: %s file1.pdf file2.pdf ...\n&quot;, argv0);
+ printf(&quot; %s file.pdf -u userpassword\n&quot;, argv0);
+ printf(&quot; %s file.pdf -o ownerpassword\n&quot;, argv0);
+ printf(&quot; %s file.pdf -p bothpasswords\n&quot;, argv0);
+ return 0;
+}
-<span class="n">static</span> <span class="n">void</span> <span class="n">log_callback</span> <span class="p">(</span><span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">message</span><span class="p">,</span> <span class="n">void</span> <span class="o">*</span><span class="n">alien</span><span class="p">)</span>
-<span class="p">{</span>
- <span class="n">fprintf</span><span class="p">((</span><span class="n">FILE</span> <span class="o">*</span><span class="p">)</span><span class="n">alien</span><span class="p">,</span> <span class="s2">&quot;</span><span class="se">\n</span><span class="s2">ooops: </span><span class="si">%s</span><span class="se">\n</span><span class="s2">&quot;</span><span class="p">,</span> <span class="n">message</span><span class="p">);</span>
-<span class="p">}</span>
+static void log_callback (const char *message, void *alien)
+{
+ fprintf((FILE *)alien, &quot;\nooops: %s\n&quot;, message);
+}
-<span class="nb">int</span> <span class="n">main</span> <span class="p">(</span><span class="nb">int</span> <span class="n">argc</span><span class="p">,</span> <span class="n">const</span> <span class="n">char</span> <span class="o">**</span><span class="n">argv</span><span class="p">)</span>
-<span class="p">{</span>
- <span class="n">const</span> <span class="n">char</span> <span class="o">*</span><span class="n">filepath</span><span class="p">;</span>
- <span class="nb">int</span> <span class="n">a</span><span class="p">;</span>
- <span class="n">ppdoc</span> <span class="o">*</span><span class="n">pdf</span><span class="p">;</span>
- <span class="n">ppref</span> <span class="o">*</span><span class="n">pageref</span><span class="p">;</span>
- <span class="n">ppdict</span> <span class="o">*</span><span class="n">pagedict</span><span class="p">;</span>
- <span class="nb">int</span> <span class="n">pageno</span><span class="p">;</span>
- <span class="n">char</span> <span class="n">outname</span><span class="p">[</span><span class="mi">1024</span><span class="p">];</span>
- <span class="n">FILE</span> <span class="o">*</span><span class="n">fh</span><span class="p">;</span>
- <span class="n">ppstream</span> <span class="o">*</span><span class="n">stream</span><span class="p">;</span>
- <span class="n">uint8_t</span> <span class="o">*</span><span class="n">data</span><span class="p">;</span>
- <span class="n">size_t</span> <span class="n">size</span><span class="p">;</span>
- <span class="n">ppcontext</span> <span class="o">*</span><span class="n">context</span><span class="p">;</span>
- <span class="n">ppobj</span> <span class="o">*</span><span class="n">obj</span><span class="p">;</span>
- <span class="n">ppname</span> <span class="o">*</span><span class="n">op</span><span class="p">;</span>
- <span class="n">size_t</span> <span class="n">operators</span><span class="p">;</span>
+static const char * get_next_argument (const char *opt, int *a, int argc, const char **argv)
+{
+ const char *next;
+ if ((*a) + 2 &lt; argc)
+ {
+ next = argv[*a + 1];
+ if (strcmp(next, opt) == 0)
+ {
+ *a += 2;
+ return argv[*a];
+ }
+ }
+ return NULL;
+}
- <span class="k">if</span> <span class="p">(</span><span class="n">argc</span> <span class="o">&lt;</span> <span class="mi">2</span><span class="p">)</span>
- <span class="k">return</span> <span class="n">usage</span><span class="p">(</span><span class="n">argv</span><span class="p">[</span><span class="mi">0</span><span class="p">]);</span>
- <span class="n">ppstream_init_buffers</span><span class="p">();</span>
- <span class="n">pplog_callback</span><span class="p">(</span><span class="n">log_callback</span><span class="p">,</span> <span class="n">stderr</span><span class="p">);</span>
- <span class="n">context</span> <span class="o">=</span> <span class="n">ppcontext_new</span><span class="p">();</span>
- <span class="k">for</span> <span class="p">(</span><span class="n">a</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="n">a</span> <span class="o">&lt;</span> <span class="n">argc</span><span class="p">;</span> <span class="o">++</span><span class="n">a</span><span class="p">)</span>
- <span class="p">{</span>
- <span class="n">filepath</span> <span class="o">=</span> <span class="n">argv</span><span class="p">[</span><span class="n">a</span><span class="p">];</span>
- <span class="n">printf</span><span class="p">(</span><span class="s2">&quot;loading </span><span class="si">%s</span><span class="s2">... &quot;</span><span class="p">,</span> <span class="n">filepath</span><span class="p">);</span>
- <span class="n">pdf</span> <span class="o">=</span> <span class="n">ppdoc_load</span><span class="p">(</span><span class="n">filepath</span><span class="p">);</span>
- <span class="k">if</span> <span class="p">(</span><span class="n">pdf</span> <span class="o">==</span> <span class="n">NULL</span><span class="p">)</span>
- <span class="p">{</span>
- <span class="n">printf</span><span class="p">(</span><span class="s2">&quot;failed</span><span class="se">\n</span><span class="s2">&quot;</span><span class="p">);</span>
- <span class="k">continue</span><span class="p">;</span>
- <span class="p">}</span>
- <span class="n">printf</span><span class="p">(</span><span class="s2">&quot;done.</span><span class="se">\n</span><span class="s2">&quot;</span><span class="p">);</span>
- <span class="n">switch</span> <span class="p">(</span><span class="n">ppdoc_crypt_status</span><span class="p">(</span><span class="n">pdf</span><span class="p">))</span>
- <span class="p">{</span>
- <span class="n">case</span> <span class="n">PPCRYPT_NONE</span><span class="p">:</span>
- <span class="n">case</span> <span class="n">PPCRYPT_DONE</span><span class="p">:</span>
- <span class="k">break</span><span class="p">;</span>
- <span class="n">case</span> <span class="n">PPCRYPT_PASS</span><span class="p">:</span>
- <span class="k">if</span> <span class="p">(</span><span class="n">ppdoc_crypt_pass</span><span class="p">(</span><span class="n">pdf</span><span class="p">,</span> <span class="s2">&quot;dummy&quot;</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="n">NULL</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span> <span class="o">==</span> <span class="n">PPCRYPT_DONE</span> <span class="o">||</span> <span class="n">ppdoc_crypt_pass</span><span class="p">(</span><span class="n">pdf</span><span class="p">,</span> <span class="n">NULL</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="s2">&quot;dummy&quot;</span><span class="p">,</span> <span class="mi">5</span><span class="p">)</span> <span class="o">==</span> <span class="n">PPCRYPT_DONE</span><span class="p">)</span>
- <span class="k">break</span><span class="p">;</span>
- <span class="n">printf</span><span class="p">(</span><span class="s2">&quot;sorry, password needed</span><span class="se">\n</span><span class="s2">&quot;</span><span class="p">);</span>
- <span class="n">ppdoc_free</span><span class="p">(</span><span class="n">pdf</span><span class="p">);</span>
- <span class="k">continue</span><span class="p">;</span>
- <span class="n">case</span> <span class="n">PPCRYPT_FAIL</span><span class="p">:</span>
- <span class="n">printf</span><span class="p">(</span><span class="s2">&quot;sorry, encryption failed</span><span class="se">\n</span><span class="s2">&quot;</span><span class="p">);</span>
- <span class="n">ppdoc_free</span><span class="p">(</span><span class="n">pdf</span><span class="p">);</span>
- <span class="k">continue</span><span class="p">;</span>
- <span class="p">}</span>
- <span class="n">sprintf</span><span class="p">(</span><span class="n">outname</span><span class="p">,</span> <span class="s2">&quot;</span><span class="si">%s</span><span class="s2">.out&quot;</span><span class="p">,</span> <span class="n">filepath</span><span class="p">);</span>
- <span class="n">fh</span> <span class="o">=</span> <span class="n">fopen</span><span class="p">(</span><span class="n">outname</span><span class="p">,</span> <span class="s2">&quot;wb&quot;</span><span class="p">);</span>
- <span class="k">if</span> <span class="p">(</span><span class="n">fh</span> <span class="o">==</span> <span class="n">NULL</span><span class="p">)</span>
- <span class="p">{</span>
- <span class="n">printf</span><span class="p">(</span><span class="s2">&quot;can&#39;t open </span><span class="si">%s</span><span class="s2"> for writing</span><span class="se">\n</span><span class="s2">&quot;</span><span class="p">,</span> <span class="n">outname</span><span class="p">);</span>
- <span class="k">continue</span><span class="p">;</span>
- <span class="p">}</span>
- <span class="k">for</span> <span class="p">(</span><span class="n">pageref</span> <span class="o">=</span> <span class="n">ppdoc_first_page</span><span class="p">(</span><span class="n">pdf</span><span class="p">),</span> <span class="n">pageno</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
- <span class="n">pageref</span> <span class="o">!=</span> <span class="n">NULL</span><span class="p">;</span>
- <span class="n">pageref</span> <span class="o">=</span> <span class="n">ppdoc_next_page</span><span class="p">(</span><span class="n">pdf</span><span class="p">),</span> <span class="o">++</span><span class="n">pageno</span><span class="p">)</span>
- <span class="p">{</span>
- <span class="n">pagedict</span> <span class="o">=</span> <span class="n">pageref</span><span class="o">-&gt;</span><span class="nb">object</span><span class="o">.</span><span class="n">dict</span><span class="p">;</span>
- <span class="o">/*</span> <span class="n">decompress</span> <span class="n">contents</span> <span class="n">data</span> <span class="o">*/</span>
- <span class="n">fprintf</span><span class="p">(</span><span class="n">fh</span><span class="p">,</span> <span class="s2">&quot;</span><span class="si">%%%%</span><span class="s2"> PAGE </span><span class="si">%d</span><span class="se">\n</span><span class="s2">&quot;</span><span class="p">,</span> <span class="n">pageno</span><span class="p">);</span>
- <span class="n">box_info</span><span class="p">(</span><span class="n">pagedict</span><span class="p">,</span> <span class="n">fh</span><span class="p">);</span>
- <span class="k">for</span> <span class="p">(</span><span class="n">stream</span> <span class="o">=</span> <span class="n">ppcontents_first</span><span class="p">(</span><span class="n">pagedict</span><span class="p">);</span>
- <span class="n">stream</span> <span class="o">!=</span> <span class="n">NULL</span><span class="p">;</span>
- <span class="n">stream</span> <span class="o">=</span> <span class="n">ppcontents_next</span><span class="p">(</span><span class="n">pagedict</span><span class="p">,</span> <span class="n">stream</span><span class="p">))</span>
- <span class="p">{</span>
- <span class="k">for</span> <span class="p">(</span><span class="n">data</span> <span class="o">=</span> <span class="n">ppstream_first</span><span class="p">(</span><span class="n">stream</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">size</span><span class="p">,</span> <span class="mi">1</span><span class="p">);</span>
- <span class="n">data</span> <span class="o">!=</span> <span class="n">NULL</span><span class="p">;</span>
- <span class="n">data</span> <span class="o">=</span> <span class="n">ppstream_next</span><span class="p">(</span><span class="n">stream</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">size</span><span class="p">))</span>
- <span class="n">fwrite</span><span class="p">(</span><span class="n">data</span><span class="p">,</span> <span class="n">size</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="n">fh</span><span class="p">);</span>
- <span class="n">ppstream_done</span><span class="p">(</span><span class="n">stream</span><span class="p">);</span>
- <span class="p">}</span>
- <span class="o">/*</span> <span class="n">now</span> <span class="n">parse</span> <span class="n">contents</span> <span class="o">*/</span>
- <span class="k">for</span> <span class="p">(</span><span class="n">stream</span> <span class="o">=</span> <span class="n">ppcontents_first</span><span class="p">(</span><span class="n">pagedict</span><span class="p">);</span>
- <span class="n">stream</span> <span class="o">!=</span> <span class="n">NULL</span><span class="p">;</span>
- <span class="n">stream</span> <span class="o">=</span> <span class="n">ppcontents_next</span><span class="p">(</span><span class="n">pagedict</span><span class="p">,</span> <span class="n">stream</span><span class="p">))</span>
- <span class="p">{</span>
- <span class="n">operators</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
- <span class="k">for</span> <span class="p">(</span><span class="n">obj</span> <span class="o">=</span> <span class="n">ppcontents_first_op</span><span class="p">(</span><span class="n">context</span><span class="p">,</span> <span class="n">stream</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">size</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">op</span><span class="p">);</span>
- <span class="n">obj</span> <span class="o">!=</span> <span class="n">NULL</span><span class="p">;</span>
- <span class="n">obj</span> <span class="o">=</span> <span class="n">ppcontents_next_op</span><span class="p">(</span><span class="n">context</span><span class="p">,</span> <span class="n">stream</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">size</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">op</span><span class="p">))</span>
- <span class="o">++</span><span class="n">operators</span><span class="p">;</span>
- <span class="n">fprintf</span><span class="p">(</span><span class="n">fh</span><span class="p">,</span> <span class="s2">&quot;</span><span class="si">%%%%</span><span class="s2"> OPERATORS count </span><span class="si">%lu</span><span class="se">\n</span><span class="s2">&quot;</span><span class="p">,</span> <span class="p">(</span><span class="n">unsigned</span> <span class="n">long</span><span class="p">)</span><span class="n">operators</span><span class="p">);</span>
- <span class="n">ppstream_done</span><span class="p">(</span><span class="n">stream</span><span class="p">);</span>
- <span class="o">//</span><span class="n">obj</span> <span class="o">=</span> <span class="n">ppcontents_parse</span><span class="p">(</span><span class="n">context</span><span class="p">,</span> <span class="n">stream</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">size</span><span class="p">);</span>
- <span class="o">//</span><span class="n">fprintf</span><span class="p">(</span><span class="n">fh</span><span class="p">,</span> <span class="s2">&quot;</span><span class="si">%%%%</span><span class="s2"> items count </span><span class="si">%lu</span><span class="se">\n</span><span class="s2">&quot;</span><span class="p">,</span> <span class="p">(</span><span class="n">unsigned</span> <span class="n">long</span><span class="p">)</span><span class="n">size</span><span class="p">);</span>
- <span class="n">fprintf</span><span class="p">(</span><span class="n">fh</span><span class="p">,</span> <span class="s2">&quot;</span><span class="se">\n</span><span class="s2">&quot;</span><span class="p">);</span>
- <span class="p">}</span>
- <span class="n">ppcontext_done</span><span class="p">(</span><span class="n">context</span><span class="p">);</span>
- <span class="p">}</span>
- <span class="n">fclose</span><span class="p">(</span><span class="n">fh</span><span class="p">);</span>
- <span class="n">ppdoc_free</span><span class="p">(</span><span class="n">pdf</span><span class="p">);</span>
- <span class="p">}</span>
- <span class="n">ppcontext_free</span><span class="p">(</span><span class="n">context</span><span class="p">);</span>
- <span class="n">ppstream_free_buffers</span><span class="p">();</span>
- <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
-<span class="p">}</span>
+int main (int argc, const char **argv)
+{
+ const char *filepath, *password;
+ int a;
+ ppdoc *pdf;
+ ppcrypt_status cryptstatus;
+ ppref *pageref;
+ ppdict *pagedict;
+ int pageno;
+ char outname[1024];
+ FILE *fh;
+ ppstream *stream;
+ uint8_t *data;
+ size_t size;
+ ppcontext *context;
+ ppobj *obj;
+ ppname *op;
+ size_t operators;
+
+ if (argc &lt; 2)
+ return usage(argv[0]);
+ ppstream_init_buffers();
+ pplog_callback(log_callback, stderr);
+ context = ppcontext_new();
+ for (a = 1; a &lt; argc; ++a)
+ {
+ /* load */
+ filepath = argv[a];
+ printf(&quot;loading %s... &quot;, filepath);
+ pdf = ppdoc_load(filepath);
+ if (pdf == NULL)
+ {
+ printf(&quot;failed\n&quot;);
+ continue;
+ }
+ printf(&quot;done\n&quot;);
+
+ /* decrypt */
+ if ((password = get_next_argument(&quot;-u&quot;, &amp;a, argc, argv)) != NULL)
+ cryptstatus = ppdoc_crypt_pass(pdf, password, strlen(password), NULL, 0);
+ else if ((password = get_next_argument(&quot;-o&quot;, &amp;a, argc, argv)) != NULL)
+ cryptstatus = ppdoc_crypt_pass(pdf, NULL, 0, password, strlen(password));
+ else if ((password = get_next_argument(&quot;-p&quot;, &amp;a, argc, argv)) != NULL)
+ cryptstatus = ppdoc_crypt_pass(pdf, password, strlen(password), password, strlen(password));
+ else
+ cryptstatus = ppdoc_crypt_status(pdf);
+ switch (cryptstatus)
+ {
+ case PPCRYPT_NONE:
+ break;
+ case PPCRYPT_DONE:
+ printf(&quot;opened with password &#39;%s&#39;\n&quot;, password != NULL ? password : &quot;&quot;);
+ break;
+ case PPCRYPT_PASS:
+ printf(&quot;invalid password\n&quot;);
+ ppdoc_free(pdf);
+ continue;
+ case PPCRYPT_FAIL:
+ printf(&quot;invalid encryption\n&quot;);
+ ppdoc_free(pdf);
+ continue;
+ }
+
+ /* process */
+ sprintf(outname, &quot;%s.out&quot;, filepath);
+ fh = fopen(outname, &quot;wb&quot;);
+ if (fh == NULL)
+ {
+ printf(&quot;can&#39;t open %s for writing\n&quot;, outname);
+ continue;
+ }
+ for (pageref = ppdoc_first_page(pdf), pageno = 1;
+ pageref != NULL;
+ pageref = ppdoc_next_page(pdf), ++pageno)
+ {
+ pagedict = pageref-&gt;object.dict;
+ /* decompress contents data */
+ fprintf(fh, &quot;%%%% PAGE %d\n&quot;, pageno);
+ box_info(pagedict, fh);
+ for (stream = ppcontents_first(pagedict);
+ stream != NULL;
+ stream = ppcontents_next(pagedict, stream))
+ {
+ for (data = ppstream_first(stream, &amp;size, 1);
+ data != NULL;
+ data = ppstream_next(stream, &amp;size))
+ fwrite(data, size, 1, fh);
+ ppstream_done(stream);
+ }
+ /* now parse contents */
+ for (stream = ppcontents_first(pagedict);
+ stream != NULL;
+ stream = ppcontents_next(pagedict, stream))
+ {
+ operators = 0;
+ for (obj = ppcontents_first_op(context, stream, &amp;size, &amp;op);
+ obj != NULL;
+ obj = ppcontents_next_op(context, stream, &amp;size, &amp;op))
+ ++operators;
+ fprintf(fh, &quot;%%%% OPERATORS count %lu\n&quot;, (unsigned long)operators);
+ ppstream_done(stream);
+ //obj = ppcontents_parse(context, stream, &amp;size);
+ //fprintf(fh, &quot;%%%% items count %lu\n&quot;, (unsigned long)size);
+ fprintf(fh, &quot;\n&quot;);
+ }
+ ppcontext_done(context);
+ }
+ fclose(fh);
+ ppdoc_free(pdf);
+ }
+ ppcontext_free(context);
+ ppstream_free_buffers();
+ return 0;
+}
</pre></div>
</div>
</div>
@@ -492,7 +524,7 @@ int main (int argc, const char **argv)
<span class="c1">#include &quot;ppconf.h&quot;</span>
-<span class="c1">#define pplib_version &quot;v2.05 less toxic i hope&quot;</span>
+<span class="c1">#define pplib_version &quot;v2.1&quot;</span>
<span class="c1">#define pplib_author &quot;p.jackowski@gust.org.pl&quot;</span>
<span class="o">/*</span> <span class="n">types</span> <span class="o">*/</span>
@@ -962,12 +994,11 @@ Some rework on md5 and sha2.</p>
<p>uint8_t instead of ppbyte in internals; ppbyte intent is “the most natural 8-bit integer”, so it is ‘char’,
but internally we almost always need uint8_t (char may be signed or not..)</p>
</div>
+<div class="section" id="v2-10">
+<h2>v2.10<a class="headerlink" href="#v2-10" title="Permalink to this headline">¶</a></h2>
+<p>Rework on encryption; algorithms /V5 /R6.
+Passwords passed to ppdoc_crypt_pass() should be UTF-8 (backward incompatible).</p>
</div>
-<div class="section" id="todo">
-<h1>TODO<a class="headerlink" href="#todo" title="Permalink to this headline">¶</a></h1>
-<ul class="simple">
-<li>external streams (egzotic)</li>
-</ul>
</div>
@@ -990,7 +1021,7 @@ but internally we almost always need uint8_t (char may be signed or not..)</p>
</div>
<div class="footer" role="contentinfo">
&#169; Copyright 2019, p.jackowski@gust.org.pl.
- Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.8.5.
+ Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.8.6.
</div>
</body>
</html> \ No newline at end of file
diff --git a/Build/source/libs/pplib/pplib-src/doc/_build/html/pplib.html b/Build/source/libs/pplib/pplib-src/doc/_build/html/pplib.html
index 3066c7ab6c8..89c85e95f30 100644
--- a/Build/source/libs/pplib/pplib-src/doc/_build/html/pplib.html
+++ b/Build/source/libs/pplib/pplib-src/doc/_build/html/pplib.html
@@ -143,9 +143,9 @@
<li class="toctree-l2"><a class="reference internal" href="ppcode.html#v2-03">v2.03</a></li>
<li class="toctree-l2"><a class="reference internal" href="ppcode.html#v2-04">v2.04</a></li>
<li class="toctree-l2"><a class="reference internal" href="ppcode.html#v2-05">v2.05</a></li>
+<li class="toctree-l2"><a class="reference internal" href="ppcode.html#v2-10">v2.10</a></li>
</ul>
</li>
-<li class="toctree-l1"><a class="reference internal" href="ppcode.html#todo">TODO</a></li>
</ul>
</div>
</div>
@@ -170,7 +170,7 @@
</div>
<div class="footer" role="contentinfo">
&#169; Copyright 2019, p.jackowski@gust.org.pl.
- Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.8.5.
+ Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.8.6.
</div>
</body>
</html> \ No newline at end of file
diff --git a/Build/source/libs/pplib/pplib-src/doc/_build/html/ppnew.html b/Build/source/libs/pplib/pplib-src/doc/_build/html/ppnew.html
index 734d81da1f3..e579cecbe9b 100644
--- a/Build/source/libs/pplib/pplib-src/doc/_build/html/ppnew.html
+++ b/Build/source/libs/pplib/pplib-src/doc/_build/html/ppnew.html
@@ -203,7 +203,7 @@ word (<code class="docutils literal notranslate"><span class="pre">unsigned</spa
</div>
<div class="footer" role="contentinfo">
&#169; Copyright 2019, p.jackowski@gust.org.pl.
- Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.8.5.
+ Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.8.6.
</div>
</body>
</html> \ No newline at end of file
diff --git a/Build/source/libs/pplib/pplib-src/doc/_build/html/search.html b/Build/source/libs/pplib/pplib-src/doc/_build/html/search.html
index 1f1c6ce65f5..f7c4aeca846 100644
--- a/Build/source/libs/pplib/pplib-src/doc/_build/html/search.html
+++ b/Build/source/libs/pplib/pplib-src/doc/_build/html/search.html
@@ -91,7 +91,7 @@
</div>
<div class="footer" role="contentinfo">
&#169; Copyright 2019, p.jackowski@gust.org.pl.
- Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.8.5.
+ Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.8.6.
</div>
</body>
</html> \ No newline at end of file
diff --git a/Build/source/libs/pplib/pplib-src/doc/_build/html/searchindex.js b/Build/source/libs/pplib/pplib-src/doc/_build/html/searchindex.js
index b59ee11455a..dfbe86ff431 100644
--- a/Build/source/libs/pplib/pplib-src/doc/_build/html/searchindex.js
+++ b/Build/source/libs/pplib/pplib-src/doc/_build/html/searchindex.js
@@ -1 +1 @@
-Search.setIndex({docnames:["ppapi-1.x","ppapi-2.x","ppcode","pplib","ppnew"],envversion:{"sphinx.domains.c":1,"sphinx.domains.changeset":1,"sphinx.domains.cpp":1,"sphinx.domains.javascript":1,"sphinx.domains.math":2,"sphinx.domains.python":1,"sphinx.domains.rst":1,"sphinx.domains.std":1,sphinx:54},filenames:["ppapi-1.x.rst","ppapi-2.x.rst","ppcode.rst","pplib.rst","ppnew.rst"],objects:{},objnames:{},objtypes:{},terms:{"1mb":[0,1],"2fkb":2,"2fmb":2,"64kb":[0,1],"boolean":[0,1],"break":[0,1,2],"byte":[0,1,2,4],"case":[0,1,2,4],"char":[0,1,2,4],"const":[0,1,2,4],"default":[0,1,2],"enum":[0,1,2],"final":[0,1],"function":[0,1,2,4],"int":[0,1,2,4],"long":[0,1,2,4],"new":[0,1],"null":[0,1,2,4],"return":[0,1,2,4],"short":[0,1],"static":2,"switch":[0,1,2,4],"void":[0,1,2],"while":[0,1,4],And:[0,1,3],But:[0,1],For:[0,1],NOT:2,One:[0,1],Such:[0,1],The:[0,1,4],Then:[0,1],There:[0,1,4],Use:[0,1],Using:4,about:[0,1,2,4],abov:[0,1],absolutelli:[0,1],accept:[0,1,4],access:[0,1,2],accessor:[0,1],accord:[0,1],acrobat:[0,1,2],actual:[0,1,4],added:2,addit:[0,1],address:4,adjust:2,after:[0,1,2],again:[0,1,2],ahead:[0,1],alfterego:4,alia:[0,1,4],alias:[1,4],alien:[0,1,2],align:[2,4],aliv:[0,1],all:[0,1,4],alloc:[0,1,2,3],allow:[0,1],almost:[2,4],alreadi:[0,1],also:[0,1],alter:[0,1],alterego:[1,2,4],alwai:[0,1,2],among:[0,1],ani:[0,1,2],annoi:[0,1],anoth:[0,1,4],anyhow:[0,1],anymor:[0,1],anyth:[0,1],api:[2,3,4],app:0,appear:[0,1],appli:[0,1],applic:[0,1],approach:[0,1],approx:[0,1],arbitrari:[0,1],aren:[0,1],argc:2,argument:[0,1,4],argv0:2,argv:2,arm:2,arm_compli:4,arrai:[2,3,4],artbox:2,ascii85decod:[0,1],ascii:[0,1],asciihexdecod:[0,1],ask:[0,1],assert:2,associ:[0,1],assum:[0,1],assumpt:4,attempt:2,auxilari:[0,1],avail:[0,1],avoid:[0,1,4],awar:[0,1],base16:[0,1],base85:[0,1],basic:[0,1],bbox:[0,1],becaus:[0,1],been:[0,1,4],befor:[0,1,2],beings:[0,1],belong:[0,1],below:[0,1,4],besid:[0,1],best:4,better:[0,1,4],between:[0,1,4],beyond:[0,1],binari:[0,1],bit:[0,1,2,4],bleedbox:2,bodi:[0,1],boject:[0,1],bom:[0,1],both:[0,1,4],bother:[0,1],bound:[0,1],box:[2,3],box_info:2,buffer:[0,1,2],bug:[0,1],build:0,bunch:[0,1],call:[0,1,4],callback:[0,1],can:[0,1,2,4],care:[0,1],cast:[0,1],catalog:[0,1],caus:4,ccitt:[0,1],ccittfaxdecod:[0,1],chang:3,charact:[0,1,2],check:[0,1,4],check_stream_chunk:2,choic:4,chunk:[0,1,2,4],cipher:[0,1],cleanup:3,clear:0,close:[0,1],closefil:[1,2],code:[0,1,4],coercion:[0,1],come:[0,1],common:[0,1,4],compar:[0,1],comparison:[0,1],compil:4,complet:[0,1],completelli:[0,1],compound:[0,1],compress:[0,1,2],conceptu:[0,1],condit:[0,1],confus:[0,1],consequ:4,consid:0,constant:[0,1],construct:[0,1],contain:[0,1],content:[2,3],context:[0,1,2],continu:2,conveni:[0,1],convert:[0,1],copi:[0,1,2],correspond:[0,1],cost:[0,1,4],could:[0,1,4],count:[0,1,2],counterpart:[0,1,4],covert:[0,1],crap:2,creat:[0,1,2],creator:2,cropbox:2,cross:[0,1],crypt:[0,1,2],crypt_info:2,cryptkei:2,cstr:0,cstring:0,current:[0,1],custom:[0,1],data1:[0,1],data2:[0,1],data3:[0,1],data:[0,1,2,4],dct:[0,1],dctdecod:[0,1],deal:[0,1],declar:[0,1],decod:[0,1,2,4],decodeparm:[0,1,2],decompress:[0,1,2],decrypt:[0,1],dedic:[0,1],dedict:[0,1],deep:2,defin:[0,1,2,4],delim:[0,1],demand:[0,1],depend:[0,1,4],derefer:[0,1],dereferenc:2,describ:[0,1],descript:[0,1],design:[0,1],destroi:[0,1],detail:4,detect:[0,1],determin:[0,1],dict:[2,3,4],differ:[0,1,4],digit:[0,1,2],direct:[0,1],directli:[0,1],dirti:4,distinct:4,distinguish:[0,1],distingush:[0,1],doc:[1,2],document:[0,1],doe:[0,1],doesn:[0,1,4],don:[0,1,4],done:[0,1,2,4],doubl:[0,1,2,4],due:[0,1],dummi:[0,1,2],each:[0,1,4],eat:[0,1],effect:[0,1,2],ego:[0,1],egzot:2,element:[0,1],elementari:[0,1],els:2,empti:[0,1,2],encod:[0,1,2,4],encrypt:[2,3],end:[0,1],endif:2,enough:[0,1,4],ensur:[0,1],entir:[0,1],entri:[0,1],equiv:[0,1],error:3,escap:[0,1,2],even:[0,1],everi:[0,1],exactli:[0,1],exampl:[0,1,3],except:[0,1],execut:[0,1],expect:[0,1],explain:[0,1],explicit:[0,1,4],expos:[0,1],extend:[0,2],extens:0,extern:2,extra:[0,1,4],fail:[0,1,2],failur:[0,1],far:[0,1,4],fast:0,fault:0,fclose:[1,2],featur:[0,1,4],fetch:[0,1],field:[0,1,2],file1:2,file2:2,file:[0,1,2,4],filenam:[0,1,2],filepath:2,files:2,filespec:2,fill:[0,1,2],filter:[2,3],filternam:[0,1,2],filtertyp:[0,1,2],find:[0,1],finder:2,first:[0,1,2],fix:2,flag:[0,1,2,4],flate:[0,1],flatedecod:[0,1],fly:[0,1],folk:2,follow:[0,1],fopen:2,forbidden:0,form:[0,1,2,4],found:[0,1],fprintf:[0,1,2],free:[0,1,2],freed:[0,1],from:[0,1,2,4],futur:[0,1],fwrite:2,gener:[2,4],genuin:[0,1],get:[0,1],get_file_nam:2,getter:[0,1],give:[0,1],given:[0,1],gobbl:2,goe:[0,1],going:[0,1],grant:[0,1],grow:[0,1],guess:[0,1,4],gust:2,han:2,handl:[2,3],handler:[0,1],happen:[0,1,2],has:[0,1,4],hash:[0,1],have:[0,1,4],haven:[0,1],header:[0,1],heap:[0,1,2,4],helper:[0,1,4],here:[0,1],hex:[0,1],hidden:4,hide:0,hope:2,hopefulli:4,host:[0,1],how:[0,1],howev:0,hundr:0,idea:4,ident:[0,1,4],identifi:[0,1],iff:[0,1],ifndef:2,imag:[0,1,2],imagedict:[0,1],implement:[0,1,4],includ:[0,1,2],incomplet:[0,1],incorrect:2,increment:[0,1,2],independ:[0,1,4],index:[0,1,2],indic:[0,1],indirect:[0,1],inevit:4,info:[0,1,2],inform:[0,1,4],initi:[0,1],inlin:[0,1,2],input:2,instead:[0,1,2],insuffici:[0,1],int64_t:[0,1,2,4],int8_t:2,integ:[0,1,2,4],integr:2,intend:[0,1],intent:[0,1,2],interfac:[0,1],intern:[0,1,2],introduc:[0,1],invalid:[0,1,2],iof_copy_file_data:2,iof_discard:2,iof_heap:2,issu:4,item:[0,1,2],iter:[0,1,2],its:[0,1,2],itself:[0,1],jackowski:2,jbig2:[0,1],jbig2decod:[0,1],jbig:[0,1],jpeg:[0,1],jpegsiz:[0,1],jpegstream:[0,1],jpx:[0,1],jpxdecod:[0,1],jump:[0,1],just:[0,1,4],keep:[0,1,4],kei:[0,1,2,4],kep:[0,1],kept:[0,1],keyval:[0,1],keyword:2,kid:2,kind:[0,1],know:[0,1],known:[0,1],larg:[0,1],last:[0,1,2],later:[0,1],lead:[0,1],length:[0,1,2],less:[0,1,2,4],letter:[0,1],librari:[0,1,4],like:[0,1,4],limit:4,linear:[0,1],list:[0,1],liter:[0,1,4],load:[0,1,2],loader:[0,1,2],log:[0,1],log_callback:2,logger:[0,1,2],longer:[0,1,2,4],look:[0,1],lookup:[0,2],loop:[0,1],lot:4,luatex:2,luigi:2,lzw:[0,1],lzwdecod:[0,1],machin:[0,1,2,4],macro:[0,1,2,4],made:4,magic:[0,1],mai:[0,1,2],main:[0,1,2],maintain:4,major:[0,1],make:[0,1,4],malloc:[0,1,2],mani:4,map:[0,1],mark:[0,1],match:[0,1],matrix:[0,1,2],matter:[0,1],md5:2,mean:[0,1],mechan:4,mediabox:[0,1,2],mem:2,member:[0,1,4],memcmp:[0,1,2],memori:[0,1,2,4],memus:2,memwast:2,mention:[0,1],messag:[0,1,2],might:[0,1,2],mind:[0,1],minor:[0,1,2],moment:[0,1],more:[0,1,2,4],most:[0,1,2,4],move:4,much:4,must:[0,1],name:[2,3],natur:2,necessari:[0,1],need:[0,1,2,4],never:4,newest:[0,1],next:[0,1,2],node:[0,1],non:[0,1],none:2,nonempti:2,nooop:[0,1,2],normal:[0,1],note:[0,1,2,4],noth:[0,1],now:[0,1,2,4],number:[0,1,2],numer:[0,1],obj:[0,1,2],object:[2,3,4],obligatori:[0,1],obscur:[0,1],octal:2,offset:[0,1,2],often:[0,1],older:[0,1],omit:[0,1],onc:[0,1,4],one:[0,1],onli:[0,1,2,4],open:[0,1,2],openbsd:[],oper:[0,1,2],operand:[0,1],operato:[0,1],oprat:[0,1],option:[0,1],org:2,origin:[0,1],other:[0,1,2,4],otherwis:[0,1],out:[0,1,2,4],outnam:2,output:[0,1],over:[0,1],own:[0,1,2],owner:[0,1],ownerpass:[0,1,2],ownerpasslength:[0,1,2],page:[2,3],pagecount:2,pagedict:[0,1,2],pageno:[0,1,2],pageref:2,paid:1,pair:[0,1],parallel:[0,1],param:[0,1,2],paramet:[0,1],parent:[0,1],pars:[0,1,2],parser:[0,1,2],part:[0,1,4],password:[0,1,2],path:2,pcontext:[0,1],pdf:[2,3,4],perfectli:0,perform:[0,1],permiss:[0,1,2],piec:[0,1],pkei:[0,1,2,4],place:4,plain:[0,1,2,4],platform:4,plu:2,pname:[0,1,2,4],point:[0,1],pointer:[0,1,2,4],pool:[0,1,4],portabl:2,possibl:[0,1],postscript:[0,1,2],pp_api_h:2,ppapi:[0,1,3,4],pparrai:[0,1,2,4],pparray_at:[0,1,2],pparray_first:[0,1,2],pparray_get:[0,1,2],pparray_get_:[0,1],pparray_get_arrai:[0,1,2],pparray_get_bool:[0,1,2],pparray_get_dict:[0,1,2],pparray_get_int:[0,1,2],pparray_get_nam:[0,1,2],pparray_get_num:[0,1,2],pparray_get_obj:[0,1,2],pparray_get_ref:[0,1,2],pparray_get_str:[0,1,2],pparray_get_stream:[0,1,2],pparray_get_uint:[0,1,2],pparray_next:[0,1,2],pparray_rget_:[0,1],pparray_rget_arrai:2,pparray_rget_bool:2,pparray_rget_dict:2,pparray_rget_int:2,pparray_rget_nam:2,pparray_rget_num:2,pparray_rget_obj:2,pparray_rget_ref:2,pparray_rget_str:2,pparray_rget_stream:[0,1,2],pparray_rget_uint:2,pparray_s:[0,1,2],pparray_to_matrix:[0,1,2],pparray_to_rect:[0,1,2],ppbool:[0,1,2],ppbyte:[1,2,4],ppconf:2,ppcontents_first:[0,1,2],ppcontents_first_op:[0,1,2],ppcontents_next:[0,1,2],ppcontents_next_op:[0,1,2],ppcontents_pars:[0,1,2],ppcontext:[0,1,2],ppcontext_don:[0,1,2],ppcontext_fre:[0,1,2],ppcontext_new:[0,1,2],ppcrypt_don:[0,1,2],ppcrypt_fail:[0,1,2],ppcrypt_non:[0,1,2],ppcrypt_pass:[0,1,2],ppcrypt_statu:[0,1,2],ppdef:2,ppdic_rget_dict:[0,1],ppdict:[0,1,2],ppdict_at:[0,1,2],ppdict_first:[0,1,2,4],ppdict_get:4,ppdict_get_:[0,1,4],ppdict_get_arrai:[0,1,2],ppdict_get_bool:[0,1,2],ppdict_get_box:[0,1,2],ppdict_get_dict:[0,1,2],ppdict_get_int:[0,1,2],ppdict_get_matrix:[0,1,2],ppdict_get_nam:[0,1,2],ppdict_get_num:[0,1,2],ppdict_get_obj:[0,1,2],ppdict_get_rect:[0,1,2],ppdict_get_ref:[0,1,2],ppdict_get_someth:4,ppdict_get_str:[0,1,2],ppdict_get_stream:[0,1,2],ppdict_get_uint:[0,1,2],ppdict_kei:[0,1,2],ppdict_next:[0,1,2,4],ppdict_rget_:[0,1],ppdict_rget_arrai:2,ppdict_rget_bool:2,ppdict_rget_dict:[0,1,2],ppdict_rget_int:2,ppdict_rget_nam:2,ppdict_rget_num:2,ppdict_rget_obj:2,ppdict_rget_ref:2,ppdict_rget_str:2,ppdict_rget_stream:[0,1,2],ppdict_rget_uint:2,ppdict_siz:[0,1,2],ppdoc:[0,1,2],ppdoc_allow_annot:[0,1,2],ppdoc_allow_assembl:[0,1,2],ppdoc_allow_copi:[0,1,2],ppdoc_allow_extract:[0,1,2],ppdoc_allow_modifi:[0,1,2],ppdoc_allow_print:[0,1,2],ppdoc_allow_print_hir:[0,1,2],ppdoc_catalog:[0,1,2],ppdoc_crypt_pass:[0,1,2],ppdoc_crypt_statu:[0,1,2],ppdoc_fil:2,ppdoc_file_s:[0,1,2],ppdoc_filehandl:[1,2],ppdoc_first_pag:[0,1,2],ppdoc_fre:[0,1,2],ppdoc_info:[0,1,2],ppdoc_load:[0,1,2],ppdoc_mem:[0,1,2],ppdoc_memori:[0,1,2],ppdoc_next_pag:[0,1,2],ppdoc_object:[0,1,2],ppdoc_pag:[0,1,2],ppdoc_page_count:[0,1,2],ppdoc_permiss:[0,1,2],ppdoc_trail:[0,1,2],ppdoc_version_numb:[0,1,2],ppdoc_version_str:[0,1,2],ppdoc_xref:[0,1,2],ppint:[0,1,2],pplib:[2,4],pplib_author:2,pplib_vers:2,pplog_callback:[0,1,2],pplog_prefix:[0,1,2],pplogger_callback:[0,1,2],ppmatrix:[0,1,2],ppname:[0,1,2,4],ppname_data:[1,2,4],ppname_decod:[0,1,2,4],ppname_decoded_data:[1,2,4],ppname_encod:[0,1,2,4],ppname_encoded_data:[1,2,4],ppname_eq:[0,1,2],ppname_exec:[0,1,2],ppname_i:[0,1,2],ppname_s:[0,1,2,4],ppnone:[0,1,2],ppnull:[0,1,2],ppnum:[0,1,2],ppobj:[0,1,2],ppobj_get_:[0,1],ppobj_get_arrai:[0,1,2],ppobj_get_bool:[0,1,2],ppobj_get_bool_valu:2,ppobj_get_dict:[0,1,2],ppobj_get_int:[0,1,2],ppobj_get_int_valu:2,ppobj_get_nam:[0,1,2],ppobj_get_nul:[0,1,2],ppobj_get_num:[0,1,2],ppobj_get_num_valu:2,ppobj_get_ref:[0,1,2],ppobj_get_str:[0,1,2],ppobj_get_stream:[0,1,2],ppobj_get_uint:[0,1,2],ppobj_kind:2,ppobj_rget_:[0,1],ppobj_rget_arrai:2,ppobj_rget_bool:2,ppobj_rget_dict:[0,1,2],ppobj_rget_int:2,ppobj_rget_nam:2,ppobj_rget_nul:2,ppobj_rget_num:2,ppobj_rget_obj:[0,1,2],ppobj_rget_ref:2,ppobj_rget_str:2,ppobj_rget_stream:2,ppobj_rget_uint:2,ppobjtp:[0,1,2],pprect:[0,1,2],ppref:[0,1,2],ppref_obj:[0,1,2],ppstream:[0,1,2],ppstream_al:[0,1,2],ppstream_base16:[0,1,2],ppstream_base85:[0,1,2],ppstream_ccitt:[0,1,2],ppstream_compress:[0,1,2],ppstream_crypt:[0,1,2],ppstream_dct:[0,1,2],ppstream_dict:[0,1,2],ppstream_don:[0,1,2],ppstream_encrypt:[0,1,2],ppstream_encrypted_a:2,ppstream_encrypted_own:[0,1,2],ppstream_encrypted_rc4:2,ppstream_filt:[0,1,2],ppstream_filter_info:[0,1,2],ppstream_filter_nam:[0,1,2],ppstream_filter_typ:[0,1,2],ppstream_first:[0,1,2],ppstream_flat:[0,1,2],ppstream_free_buff:[0,1,2],ppstream_imag:[0,1,2],ppstream_init_buff:[0,1,2],ppstream_jbig2:[0,1,2],ppstream_jpx:[0,1,2],ppstream_lzw:[0,1,2],ppstream_next:[0,1,2],ppstream_not_support:2,ppstream_runlength:[0,1,2],ppstreamtp:[0,1,2],ppstring:[0,1,2,4],ppstring_base16:[0,1,2],ppstring_base85:[0,1,2],ppstring_data:[1,2,4],ppstring_decod:[0,1,2,4],ppstring_decoded_data:[1,2,4],ppstring_encod:[0,1,2,4],ppstring_encoded_data:[1,2,4],ppstring_exec:2,ppstring_hex:[0,1,2],ppstring_intern:2,ppstring_plain:[0,1,2],ppstring_siz:[0,1,2,4],ppstring_typ:[0,1,2],ppstring_utf16b:[0,1,2],ppstring_utf16l:[0,1,2],ppstring_utf:[0,1,2],pptest3:2,ppuint:[0,1,2],ppxref:[0,1,2],ppxref_catalog:2,ppxref_find:[0,1,2],ppxref_info:2,ppxref_pag:2,ppxref_prev:[0,1,2],ppxref_trail:2,ppxsec:2,practis:[0,1],preceed:[0,1],precis:[0,1],predictor:2,prefer:[0,1,4],prefix:[0,1,2],present:[0,1],preserv:[0,1],pretend:0,pretti:[0,1,4],previou:[0,1],print:[0,1,2],print_info:2,print_result_filt:2,print_stream_info:2,printabl:[0,1],printf:[0,1,2],privat:4,probabl:[0,1],proce:[0,1],procee:[0,1],process:[0,1],produc:[0,1,2],prompt:[0,1],proper:[0,1,2],properli:4,properti:[0,1,2],protect:[0,1,2],provid:[0,1,4],psize:[0,1,2],pune:2,put:[0,1],queri:[0,1],quit:[0,1],rather:[0,1],raw:[0,1,2],read:[0,1],readabl:[0,1],reader:[0,1],readi:[0,1],real:[0,1],realli:[0,1],reason:[0,1],reclaim:[0,1,2],reconstruct:[0,1],rect:[0,1,2],rectangl:[0,1],redirect:[0,1],ref:[2,3],refer:[0,1,2],referenc:[0,1],refnum:2,refnumb:[0,1,2],relat:[0,1,4],releas:[0,1,2],relev:[0,1],reli:1,remain:[0,1],remov:4,replac:[0,1],repres:[0,1,4],request:2,resid:1,resolv:[0,1,2],resourc:[0,1],restor:[0,1],restrict:[0,1],result:[0,1],reus:[0,1],revers:[0,1],revis:[2,4],revolut:4,rework:2,rewrit:[0,1],root:[0,1],roughli:[0,1],runlength:[0,1],runlengthdecod:[0,1],sai:[0,1],same:[0,1],saniti:[0,1,2],scheme:[0,1],search:[0,1],second:[0,1],sect:2,secur:[0,1,2],see:[0,1],seem:4,segfault:[],segment:0,self:4,sens:0,separ:[0,1],serv:4,set:[0,1],sever:[0,1],sha2:2,should:[0,1,2],shouldn:[0,1,2],show:[0,1],sign:[0,1,2],signed:4,simpl:[0,1],simpli:[0,1],sinc:[0,1,4],singl:[0,1,4],size:[0,1,2,4],size_t:[0,1,2,4],sizenum:2,sizeof:[0,1,2],skip:2,small:[0,1],smarter:[0,1],some:[0,1,2,4],some_output:[0,1],someth:[0,1],somewher:[0,1],soon:0,sorri:[0,1,2],sourc:[0,1,2],space:[0,1],spec:[0,1],special:[0,1],specif:[0,1],sprintf:2,stack:[0,1],standalon:[0,1],start:[0,1],state:[0,1],statu:[0,1],stddef:2,stderr:[0,1,2],stdint:2,stdio:2,stdout:[0,1],still:[0,1,4],stock:4,stop:[0,1],storag:4,store:[0,1,4],stream:[2,3],string:[2,3],strip:[0,1],strlen:[0,1],struct:[0,1,2,4],structur:[0,1,4],style:0,suboptim:[0,1],subsequ:[0,1],succe:[0,1],succeed:[0,1],suffer:[0,1],suit:[0,1,4],sum:[0,1,2],support:[0,1],surround:[0,1],sync:4,syntax:[0,1],tab:[0,1,2],tabl:[0,1],take:[0,1,4],taken:2,target:[0,1],tech:2,tell:[0,1],templat:[0,1,2],termin:[0,1],termini:0,test:2,text:[0,1],than:[0,1],thank:2,thei:[0,1,4],them:[0,1],thi:[0,1,2,4],think:[0,1],those:[0,1],though:0,through:[0,1],tiff:2,todo:3,tollbox:4,top:[0,1],toxic:2,trailer:[0,1],transform:[2,3],treat:[0,1],tree:[0,1],tri:[0,1],trick:4,trickeri:[0,1,4],trimbox:2,triplet:[0,1],trivial:4,two:[0,1,4],type:[2,3,4],typedef:[0,1,2],typic:[0,1],uint8_t:[0,1,2,4],unalign:4,uncompress:2,unconst:[0,1],undocu:[0,1],unescap:[0,1],unicod:[0,1],unif:4,union:[0,1,2],unless:[0,1],unnecesari:[0,1],unnecessari:[0,1],unread:[0,1],unsign:[0,1,2,4],unsupport:[0,1],until:[0,1],unus:4,updat:[0,1,2],usabl:4,usag:[0,1,2],use:[0,1,4],use_buffers_pool:2,used:[0,1,4],useless:[0,1],userpass:[0,1,2],userpasslength:[0,1,2],uses:[0,1,4],using:[0,1],usual:[0,1],utf16:[0,1],utf16b:[0,1],utf16l:[0,1],util:[0,1,2,4],utiliof:2,utilmem:4,utilmemallc:4,val:[0,1],valid:[0,1],valu:[0,1],variabl:[0,1],variant:4,verbos:[0,1],verifi:[0,1],version:[0,1,2,4],via:[0,1,4],wai:[0,1],want:[0,1,4],warn:[2,4],wast:[0,1,2],watch:4,well:[0,1,4],were:4,weren:[0,1,2],what:[0,1],whatev:[0,1],when:[0,1,2],whenev:[0,1,4],which:[0,1,4],window:4,without:[0,1],wntri:[0,1],won:[0,1],word:[0,1,2,4],work:4,would:[0,1],write:2,wrong:[0,1,4],xref:[2,3],xsec:2,yes:[0,1],yet:4,you:[0,1],your:[0,1],your_callback:[0,1],yourself:[0,1],zero:[0,1]},titles:["<code class=\"docutils literal notranslate\"><span class=\"pre\">pplib</span></code> 1.x","<code class=\"docutils literal notranslate\"><span class=\"pre\">pplib</span></code> 2.x","Examples","pplib","1.x vs 2.x"],titleterms:{And:4,alloc:4,api:[0,1],arrai:[0,1],box:[0,1],chang:2,cleanup:4,content:[0,1],dict:[0,1],encrypt:[0,1],error:[0,1],exampl:2,filter:[0,1],handl:[0,1],name:[0,1,4],object:[0,1],page:[0,1],pdf:[0,1],ppapi:2,pplib:[0,1,3],ref:[0,1],stream:[0,1],string:[0,1,4],todo:2,transform:[0,1],type:[0,1],xref:[0,1]}}) \ No newline at end of file
+Search.setIndex({docnames:["ppapi-1.x","ppapi-2.x","ppcode","pplib","ppnew"],envversion:{"sphinx.domains.c":1,"sphinx.domains.changeset":1,"sphinx.domains.cpp":1,"sphinx.domains.javascript":1,"sphinx.domains.math":2,"sphinx.domains.python":1,"sphinx.domains.rst":1,"sphinx.domains.std":1,sphinx:54},filenames:["ppapi-1.x.rst","ppapi-2.x.rst","ppcode.rst","pplib.rst","ppnew.rst"],objects:{},objnames:{},objtypes:{},terms:{"1mb":[0,1],"2fkb":2,"2fmb":2,"64kb":[0,1],"boolean":[0,1],"break":[0,1,2],"byte":[0,1,2,4],"case":[0,1,2,4],"char":[0,1,2,4],"const":[0,1,2,4],"default":[0,1,2],"enum":[0,1,2],"final":[0,1],"function":[0,1,2,4],"int":[0,1,2,4],"long":[0,1,2,4],"new":[0,1],"null":[0,1,2,4],"return":[0,1,2,4],"short":[0,1],"static":2,"switch":[0,1,2,4],"try":1,"void":[0,1,2],"while":[0,1,4],And:[0,1,3],But:[0,1],For:[0,1],NOT:2,One:[0,1],Such:[0,1],The:[0,1,4],Then:[0,1],There:[0,1,4],Use:[0,1],Using:4,about:[0,1,2,4],abov:[0,1],absolutelli:[0,1],accept:[0,1,4],access:[0,1,2],accessor:[0,1],accord:[0,1],acrobat:[0,1,2],actual:[0,1,4],added:2,addit:[0,1],address:4,adjust:2,after:[0,1,2],again:[0,1,2],ahead:[0,1],alfterego:4,algorithm:[1,2],alia:[0,1,4],alias:[1,4],alien:[0,1,2],align:[2,4],aliv:[0,1],all:[0,1,4],alloc:[0,1,2,3],allow:[0,1],almost:[2,4],alreadi:[0,1],also:[0,1],alter:[0,1],alterego:[1,2,4],alwai:[0,1,2],among:[0,1],ani:[0,1,2],annoi:[0,1],anoth:[0,1,4],anyhow:[0,1],anymor:[0,1],anyth:[0,1],api:[2,3,4],app:0,appear:[0,1],appli:[0,1],applic:[0,1],approach:[0,1],approx:[0,1],arbitrari:[0,1],aren:[0,1],argc:2,argument:[0,1,4],argv0:2,argv:2,arm:2,arm_compli:4,arrai:[2,3,4],artbox:2,ascii85decod:[0,1],ascii:[0,1],asciihexdecod:[0,1],ask:[0,1],assert:2,associ:[0,1],assum:[0,1],assumpt:4,attempt:2,auxilari:[0,1],avail:[0,1],avoid:[0,1,4],awar:[0,1],backward:2,base16:[0,1],base85:[0,1],base:1,basic:[0,1],bbox:[0,1],becaus:[0,1],been:[0,1,4],befor:[0,1,2],behav:1,beings:[0,1],belong:[0,1],below:[0,1,4],besid:[0,1],best:4,better:[0,1,4],between:[0,1,4],beyond:[0,1],binari:[0,1],bit:[0,1,2,4],bleedbox:2,bodi:[0,1],boject:[0,1],bom:[0,1],both:[0,1,4],bother:[0,1],bothpassword:2,bound:[0,1],box:[2,3],box_info:2,buffer:[0,1,2],bug:0,build:0,bunch:[0,1],call:[0,1,4],callback:[0,1],can:[0,1,2,4],care:[0,1],cast:[0,1],catalog:[0,1],caus:4,ccitt:[0,1],ccittfaxdecod:[0,1],chang:3,charact:[0,1,2],check:[0,1,4],check_stream_chunk:2,choic:4,chunk:[0,1,2,4],cipher:[0,1],cleanup:3,clear:0,close:[0,1],closefil:[1,2],code:[0,1,4],coercion:[0,1],come:[0,1],common:[0,1,4],compar:[0,1],comparison:[0,1],compil:4,complet:[0,1],completelli:[0,1],compound:[0,1],compress:[0,1,2],conceptu:[0,1],condit:[0,1],confus:[0,1],consequ:4,consid:0,constant:[0,1],construct:[0,1],contain:[0,1],content:[2,3],context:[0,1,2],continu:2,conveni:[0,1],convers:1,convert:[0,1],copi:[0,1,2],correspond:[0,1],cost:[0,1,4],could:[0,1,4],count:[0,1,2],counterpart:[0,1,4],covert:[0,1],crap:2,creat:[0,1,2],creator:2,cropbox:2,cross:[0,1],crypt:[0,1,2],crypt_info:2,cryptkei:2,cryptstatu:2,cstr:0,cstring:0,current:[0,1],custom:[0,1],data1:[0,1],data2:[0,1],data3:[0,1],data:[0,1,2,4],dct:[0,1],dctdecod:[0,1],deal:[0,1],declar:[0,1],decod:[0,1,2,4],decodeparm:[0,1,2],decompress:[0,1,2],decrypt:[0,1,2],dedic:[0,1],dedict:[0,1],deep:2,defin:[0,1,2,4],delim:[0,1],demand:[0,1],depend:[0,1,4],derefer:[0,1],dereferenc:2,describ:[0,1],descript:[0,1],design:[0,1],destroi:[0,1],detail:4,detect:[0,1],determin:[0,1],dict:[2,3,4],didn:1,differ:[0,1,4],digit:[0,1,2],direct:[0,1],directli:[0,1],dirti:4,distinct:4,distinguish:[0,1],distingush:[0,1],doc:[1,2],document:[0,1],doe:[0,1],doesn:[0,1,4],don:[0,1,4],done:[0,1,2,4],doubl:[0,1,2,4],due:[0,1],dummi:[0,1],each:[0,1,4],earlier:1,eat:[0,1],effect:[0,1,2],ego:[0,1],egzot:[],element:[0,1],elementari:[0,1],els:2,empti:[0,1,2],encod:[0,1,2,4],encrypt:[2,3],end:[0,1],endif:2,enough:[0,1,4],ensur:[0,1],entir:[0,1],entri:[0,1],equiv:[0,1],error:3,escap:[0,1,2],even:[0,1],everi:[0,1],exactli:[0,1],exampl:[0,1,3],except:[0,1],execut:[0,1],expect:[0,1],explain:[0,1],explicit:[0,1,4],expos:[0,1],extend:[0,2],extens:0,extern:2,extra:[0,1,4],fail:[0,1,2],failur:[0,1],fanci:1,far:[0,1,4],fast:0,fault:0,fclose:[1,2],featur:[0,1,4],fetch:[0,1],field:[0,1,2],file1:2,file2:2,file:[0,1,2,4],filenam:[0,1,2],filepath:2,files:2,filespec:2,fill:[0,1,2],filter:[2,3],filternam:[0,1,2],filtertyp:[0,1,2],find:[0,1],finder:2,first:[0,1,2],fix:2,flag:[0,1,2,4],flate:[0,1],flatedecod:[0,1],fly:[0,1],folk:2,follow:[0,1],fopen:2,forbidden:0,form:[0,1,2,4],found:[0,1],fprintf:[0,1,2],free:[0,1,2],freed:[0,1],from:[0,1,2,4],futur:[0,1],fwrite:2,gener:[2,4],genuin:[0,1],get:[0,1],get_file_nam:2,get_next_argu:2,getter:[0,1],give:[0,1],given:[0,1],gobbl:2,goe:[0,1],going:[0,1],grant:[0,1],grow:[0,1],guess:[0,1,4],gust:2,han:2,handl:[2,3],handler:[0,1],happen:[0,1,2],has:[0,1,4],hash:[0,1],have:[0,1,4],haven:[0,1],header:[0,1],heap:[0,1,2,4],helper:[0,1,4],here:[0,1],hex:[0,1],hidden:4,hide:0,hope:[],hopefulli:4,host:[0,1],how:[0,1],howev:0,hundr:0,idea:4,ident:[0,1,4],identifi:[0,1],iff:[0,1],ifndef:2,imag:[0,1,2],imagedict:[0,1],implement:[0,1,4],includ:[0,1,2],incompat:2,incomplet:[0,1],incorrect:2,increment:[0,1,2],independ:[0,1,4],index:[0,1,2],indic:[0,1],indirect:[0,1],inevit:4,info:[0,1,2],inform:[0,1,4],initi:[0,1],inlin:[0,1,2],input:2,instead:[0,1,2],insuffici:[0,1],int64_t:[0,1,2,4],int8_t:2,integ:[0,1,2,4],integr:2,intend:[0,1],intent:[0,1,2],interfac:[0,1],intern:[0,1,2],introduc:[0,1],invalid:[0,1,2],iof_copy_file_data:2,iof_discard:2,iof_heap:2,issu:4,item:[0,1,2],iter:[0,1,2],its:[0,1,2],itself:[0,1],jackowski:2,jbig2:[0,1],jbig2decod:[0,1],jbig:[0,1],jpeg:[0,1],jpegsiz:[0,1],jpegstream:[0,1],jpx:[0,1],jpxdecod:[0,1],jump:[0,1],just:[0,1,4],keep:[0,1,4],kei:[0,1,2,4],kep:[0,1],kept:[0,1],keyval:[0,1],keyword:2,kid:2,kind:[0,1],know:[0,1],known:[0,1],larg:[0,1],last:[0,1,2],later:[0,1],lead:[0,1],length:[0,1,2],less:[0,1,4],letter:[0,1],librari:[0,1,4],like:[0,1,4],limit:4,linear:[0,1],list:[0,1],liter:[0,1,4],load:[0,1,2],loader:[0,1,2],log:[0,1],log_callback:2,logger:[0,1,2],longer:[0,1,2,4],look:[0,1],lookup:[0,2],loop:[0,1],lot:4,luatex:2,luigi:2,lzw:[0,1],lzwdecod:[0,1],machin:[0,1,2,4],macro:[0,1,2,4],made:4,magic:[0,1],mai:[0,1,2],main:[0,1,2],maintain:4,major:[0,1],make:[0,1,4],malloc:[0,1,2],mani:4,map:[0,1],mark:[0,1],match:[0,1],matrix:[0,1,2],matter:[0,1],md5:2,mean:[0,1],mechan:4,mediabox:[0,1,2],mem:2,member:[0,1,4],memcmp:[0,1,2],memori:[0,1,2,4],memus:2,memwast:2,mention:[0,1],messag:[0,1,2],method:1,might:[0,1,2],mind:[0,1],minor:[0,1,2],moment:[0,1],more:[0,1,2,4],most:[0,1,2,4],move:4,much:4,must:[0,1],name:[2,3],natur:2,necessari:[0,1],need:[0,1,2,4],never:4,newer:1,newest:[0,1],next:[0,1,2],node:[0,1],non:[0,1],none:2,nonempti:2,nooop:[0,1,2],normal:[0,1],note:[0,1,2,4],noth:[0,1],now:[0,1,2,4],number:[0,1,2],numer:[0,1],obj:[0,1,2],object:[2,3,4],obligatori:[0,1],obscur:0,octal:2,offset:[0,1,2],often:[0,1],older:[0,1],omit:[0,1],onc:[0,1,4],one:[0,1],onli:[0,1,2,4],open:[0,1,2],openbsd:[],oper:[0,1,2],operand:[0,1],operato:[0,1],oprat:[0,1],opt:2,option:[0,1],org:2,origin:[0,1],other:[0,1,2,4],otherwis:[0,1],out:[0,1,2,4],outnam:2,output:[0,1],over:[0,1],own:[0,1,2],owner:[0,1],ownerpass:[0,1,2],ownerpasslength:[0,1,2],ownerpassword:2,page:[2,3],pagecount:2,pagedict:[0,1,2],pageno:[0,1,2],pageref:2,paid:1,pair:[0,1],parallel:[0,1],param:[0,1,2],paramet:[0,1],parent:[0,1],pars:[0,1,2],parser:[0,1,2],part:[0,1,4],pass:[1,2],password:[0,1,2],path:2,pcontext:[0,1],pdf:[2,3,4],pdfdocencod:1,perfectli:0,perform:[0,1],permiss:[0,1,2],piec:[0,1],pkei:[0,1,2,4],place:4,plain:[0,1,2,4],platform:4,plu:2,pname:[0,1,2,4],point:[0,1],pointer:[0,1,2,4],pool:[0,1,4],portabl:2,possibl:[0,1],postscript:[0,1,2],pp_api_h:2,ppapi:[0,1,3,4],pparrai:[0,1,2,4],pparray_at:[0,1,2],pparray_first:[0,1,2],pparray_get:[0,1,2],pparray_get_:[0,1],pparray_get_arrai:[0,1,2],pparray_get_bool:[0,1,2],pparray_get_dict:[0,1,2],pparray_get_int:[0,1,2],pparray_get_nam:[0,1,2],pparray_get_num:[0,1,2],pparray_get_obj:[0,1,2],pparray_get_ref:[0,1,2],pparray_get_str:[0,1,2],pparray_get_stream:[0,1,2],pparray_get_uint:[0,1,2],pparray_next:[0,1,2],pparray_rget_:[0,1],pparray_rget_arrai:2,pparray_rget_bool:2,pparray_rget_dict:2,pparray_rget_int:2,pparray_rget_nam:2,pparray_rget_num:2,pparray_rget_obj:2,pparray_rget_ref:2,pparray_rget_str:2,pparray_rget_stream:[0,1,2],pparray_rget_uint:2,pparray_s:[0,1,2],pparray_to_matrix:[0,1,2],pparray_to_rect:[0,1,2],ppbool:[0,1,2],ppbyte:[1,2,4],ppconf:2,ppcontents_first:[0,1,2],ppcontents_first_op:[0,1,2],ppcontents_next:[0,1,2],ppcontents_next_op:[0,1,2],ppcontents_pars:[0,1,2],ppcontext:[0,1,2],ppcontext_don:[0,1,2],ppcontext_fre:[0,1,2],ppcontext_new:[0,1,2],ppcrypt_don:[0,1,2],ppcrypt_fail:[0,1,2],ppcrypt_non:[0,1,2],ppcrypt_pass:[0,1,2],ppcrypt_statu:[0,1,2],ppdef:2,ppdic_rget_dict:[0,1],ppdict:[0,1,2],ppdict_at:[0,1,2],ppdict_first:[0,1,2,4],ppdict_get:4,ppdict_get_:[0,1,4],ppdict_get_arrai:[0,1,2],ppdict_get_bool:[0,1,2],ppdict_get_box:[0,1,2],ppdict_get_dict:[0,1,2],ppdict_get_int:[0,1,2],ppdict_get_matrix:[0,1,2],ppdict_get_nam:[0,1,2],ppdict_get_num:[0,1,2],ppdict_get_obj:[0,1,2],ppdict_get_rect:[0,1,2],ppdict_get_ref:[0,1,2],ppdict_get_someth:4,ppdict_get_str:[0,1,2],ppdict_get_stream:[0,1,2],ppdict_get_uint:[0,1,2],ppdict_kei:[0,1,2],ppdict_next:[0,1,2,4],ppdict_rget_:[0,1],ppdict_rget_arrai:2,ppdict_rget_bool:2,ppdict_rget_dict:[0,1,2],ppdict_rget_int:2,ppdict_rget_nam:2,ppdict_rget_num:2,ppdict_rget_obj:2,ppdict_rget_ref:2,ppdict_rget_str:2,ppdict_rget_stream:[0,1,2],ppdict_rget_uint:2,ppdict_siz:[0,1,2],ppdoc:[0,1,2],ppdoc_allow_annot:[0,1,2],ppdoc_allow_assembl:[0,1,2],ppdoc_allow_copi:[0,1,2],ppdoc_allow_extract:[0,1,2],ppdoc_allow_modifi:[0,1,2],ppdoc_allow_print:[0,1,2],ppdoc_allow_print_hir:[0,1,2],ppdoc_catalog:[0,1,2],ppdoc_crypt_pass:[0,1,2],ppdoc_crypt_statu:[0,1,2],ppdoc_fil:2,ppdoc_file_s:[0,1,2],ppdoc_filehandl:[1,2],ppdoc_first_pag:[0,1,2],ppdoc_fre:[0,1,2],ppdoc_info:[0,1,2],ppdoc_load:[0,1,2],ppdoc_mem:[0,1,2],ppdoc_memori:[0,1,2],ppdoc_next_pag:[0,1,2],ppdoc_object:[0,1,2],ppdoc_pag:[0,1,2],ppdoc_page_count:[0,1,2],ppdoc_permiss:[0,1,2],ppdoc_trail:[0,1,2],ppdoc_version_numb:[0,1,2],ppdoc_version_str:[0,1,2],ppdoc_xref:[0,1,2],ppint:[0,1,2],pplib:[2,4],pplib_author:2,pplib_vers:2,pplog_callback:[0,1,2],pplog_prefix:[0,1,2],pplogger_callback:[0,1,2],ppmatrix:[0,1,2],ppname:[0,1,2,4],ppname_data:[1,2,4],ppname_decod:[0,1,2,4],ppname_decoded_data:[1,2,4],ppname_encod:[0,1,2,4],ppname_encoded_data:[1,2,4],ppname_eq:[0,1,2],ppname_exec:[0,1,2],ppname_i:[0,1,2],ppname_s:[0,1,2,4],ppnone:[0,1,2],ppnull:[0,1,2],ppnum:[0,1,2],ppobj:[0,1,2],ppobj_get_:[0,1],ppobj_get_arrai:[0,1,2],ppobj_get_bool:[0,1,2],ppobj_get_bool_valu:2,ppobj_get_dict:[0,1,2],ppobj_get_int:[0,1,2],ppobj_get_int_valu:2,ppobj_get_nam:[0,1,2],ppobj_get_nul:[0,1,2],ppobj_get_num:[0,1,2],ppobj_get_num_valu:2,ppobj_get_ref:[0,1,2],ppobj_get_str:[0,1,2],ppobj_get_stream:[0,1,2],ppobj_get_uint:[0,1,2],ppobj_kind:2,ppobj_rget_:[0,1],ppobj_rget_arrai:2,ppobj_rget_bool:2,ppobj_rget_dict:[0,1,2],ppobj_rget_int:2,ppobj_rget_nam:2,ppobj_rget_nul:2,ppobj_rget_num:2,ppobj_rget_obj:[0,1,2],ppobj_rget_ref:2,ppobj_rget_str:2,ppobj_rget_stream:2,ppobj_rget_uint:2,ppobjtp:[0,1,2],pprect:[0,1,2],ppref:[0,1,2],ppref_obj:[0,1,2],ppstream:[0,1,2],ppstream_al:[0,1,2],ppstream_base16:[0,1,2],ppstream_base85:[0,1,2],ppstream_ccitt:[0,1,2],ppstream_compress:[0,1,2],ppstream_crypt:[0,1,2],ppstream_dct:[0,1,2],ppstream_dict:[0,1,2],ppstream_don:[0,1,2],ppstream_encrypt:[0,1,2],ppstream_encrypted_a:2,ppstream_encrypted_own:[0,1,2],ppstream_encrypted_rc4:2,ppstream_filt:[0,1,2],ppstream_filter_info:[0,1,2],ppstream_filter_nam:[0,1,2],ppstream_filter_typ:[0,1,2],ppstream_first:[0,1,2],ppstream_flat:[0,1,2],ppstream_free_buff:[0,1,2],ppstream_imag:[0,1,2],ppstream_init_buff:[0,1,2],ppstream_jbig2:[0,1,2],ppstream_jpx:[0,1,2],ppstream_lzw:[0,1,2],ppstream_next:[0,1,2],ppstream_not_support:2,ppstream_runlength:[0,1,2],ppstreamtp:[0,1,2],ppstring:[0,1,2,4],ppstring_base16:[0,1,2],ppstring_base85:[0,1,2],ppstring_data:[1,2,4],ppstring_decod:[0,1,2,4],ppstring_decoded_data:[1,2,4],ppstring_encod:[0,1,2,4],ppstring_encoded_data:[1,2,4],ppstring_exec:2,ppstring_hex:[0,1,2],ppstring_intern:2,ppstring_plain:[0,1,2],ppstring_siz:[0,1,2,4],ppstring_typ:[0,1,2],ppstring_utf16b:[0,1,2],ppstring_utf16l:[0,1,2],ppstring_utf:[0,1,2],pptest3:2,ppuint:[0,1,2],ppxref:[0,1,2],ppxref_catalog:2,ppxref_find:[0,1,2],ppxref_info:2,ppxref_pag:2,ppxref_prev:[0,1,2],ppxref_trail:2,ppxsec:2,practis:[0,1],preceed:[0,1],precis:[0,1],predictor:2,prefer:[0,1,4],prefix:[0,1,2],preprocess:1,present:[0,1],preserv:[0,1],pretend:0,pretti:[0,1,4],previou:[0,1],print:[0,1,2],print_info:2,print_result_filt:2,print_stream_info:2,printabl:[0,1],printf:[0,1,2],privat:4,probabl:[0,1],proce:0,procee:[0,1],process:[0,1,2],produc:[0,1,2],prompt:[0,1],proper:[0,1,2],properli:4,properti:[0,1,2],protect:[0,1,2],provid:[0,1,4],psize:[0,1,2],pune:2,put:0,queri:[0,1],quit:[0,1],rather:[0,1],raw:[0,1,2],read:[0,1],readabl:[0,1],reader:[0,1],readi:[0,1],real:[0,1],realli:[0,1],reason:[0,1],reclaim:[0,1,2],reconstruct:[0,1],rect:[0,1,2],rectangl:[0,1],redirect:[0,1],ref:[2,3],refer:[0,1,2],referenc:[0,1],refnum:2,refnumb:[0,1,2],relat:[0,1,4],releas:[0,1,2],relev:[0,1],reli:1,remain:[0,1],remov:4,replac:[0,1],repres:[0,1,4],request:2,resid:1,resolv:[0,1,2],resourc:[0,1],restor:[0,1],restrict:[0,1],result:[0,1],reus:[0,1],revers:[0,1],revis:[2,4],revolut:4,rework:2,rewrit:[0,1],root:[0,1],roughli:[0,1],runlength:[0,1],runlengthdecod:[0,1],sai:[0,1],same:[0,1],saniti:[0,1,2],scheme:[0,1],search:[0,1],second:[0,1],sect:2,secur:[0,1,2],see:[0,1],seem:4,segfault:[],segment:0,self:4,sens:0,separ:[0,1],serv:4,set:[0,1],sever:[0,1],sha2:2,should:[0,1,2],shouldn:[0,1,2],show:[0,1],sign:[0,1,2],signed:4,simpl:[0,1],simpli:[0,1],sinc:[0,1,4],singl:[0,1,4],size:[0,1,2,4],size_t:[0,1,2,4],sizenum:2,sizeof:[0,1,2],skip:2,small:[0,1],smarter:[0,1],some:[0,1,2,4],some_output:[0,1],someth:[0,1],somewher:[0,1],soon:0,sorri:[0,1],sourc:[0,1,2],space:[0,1],spec:[0,1],special:[0,1],specif:[0,1],sprintf:2,stack:[0,1],standalon:[0,1],start:[0,1],state:[0,1],statu:[0,1],stddef:2,stderr:[0,1,2],stdint:2,stdio:2,stdout:[0,1],still:[0,1,4],stock:4,stop:[0,1],storag:4,store:[0,1,4],strcmp:2,stream:[2,3],string:[2,3],strip:[0,1],strlen:[0,1,2],struct:[0,1,2,4],structur:[0,1,4],style:0,suboptim:[0,1],subsequ:[0,1],succe:[0,1],succeed:[0,1],suffer:[0,1],suit:[0,1,4],sum:[0,1,2],support:[0,1],surround:[0,1],sync:4,syntax:[0,1],tab:[0,1,2],tabl:[0,1],take:[0,1,4],taken:2,target:[0,1],tech:2,tell:[0,1],templat:[0,1,2],termin:[0,1],termini:0,test:[1,2],text:[0,1],than:[0,1],thank:2,thei:[0,1,4],them:[0,1],thi:[0,1,2,4],think:[0,1],those:[0,1],though:0,through:[0,1],tiff:2,todo:[],tollbox:4,top:[0,1],toxic:[],trailer:[0,1],transform:[2,3],treat:[0,1],tree:[0,1],tri:[0,1],trick:4,trickeri:[0,1,4],trimbox:2,triplet:[0,1],trivial:4,two:[0,1,4],type:[2,3,4],typedef:[0,1,2],typic:[0,1],uint8_t:[0,1,2,4],unalign:4,uncompress:2,unconst:[0,1],undocu:[0,1],unescap:[0,1],unicod:[0,1],unif:4,union:[0,1,2],unless:[0,1],unnecesari:[0,1],unnecessari:[0,1],unread:[0,1],unsign:[0,1,2,4],unsupport:[0,1],until:[0,1],unus:4,updat:[0,1,2],usabl:4,usag:[0,1,2],use:[0,1,4],use_buffers_pool:2,used:[0,1,4],useless:[0,1],user:1,userpass:[0,1,2],userpasslength:[0,1,2],userpassword:2,uses:[0,1,4],using:[0,1],usual:[0,1],utf16:[0,1],utf16b:[0,1],utf16l:[0,1],utf:[1,2],util:[0,1,2,4],utiliof:2,utilmem:4,utilmemallc:4,val:[0,1],valid:[0,1],valu:[0,1],variabl:[0,1],variant:4,verbos:[0,1],verifi:[0,1],version:[0,1,2,4],via:[0,1,4],wai:0,want:[0,1,4],warn:[2,4],wast:[0,1,2],watch:4,well:[0,1,4],were:[1,4],weren:[0,1,2],what:[0,1],whatev:[0,1],when:[0,1,2],whenev:[0,1,4],which:[0,1,4],window:4,without:[0,1],wntri:0,won:[0,1],word:[0,1,2,4],work:4,would:[0,1],write:2,wrong:[0,1,4],xref:[2,3],xsec:2,yes:0,yet:4,you:[0,1],your:[0,1],your_callback:[0,1],yourself:[0,1],zero:[0,1]},titles:["<code class=\"docutils literal notranslate\"><span class=\"pre\">pplib</span></code> 1.x","<code class=\"docutils literal notranslate\"><span class=\"pre\">pplib</span></code> 2.x","Examples","pplib","1.x vs 2.x"],titleterms:{And:4,alloc:4,api:[0,1],arrai:[0,1],box:[0,1],chang:2,cleanup:4,content:[0,1],dict:[0,1],encrypt:[0,1],error:[0,1],exampl:2,filter:[0,1],handl:[0,1],name:[0,1,4],object:[0,1],page:[0,1],pdf:[0,1],ppapi:2,pplib:[0,1,3],ref:[0,1],stream:[0,1],string:[0,1,4],todo:[],transform:[0,1],type:[0,1],xref:[0,1]}}) \ No newline at end of file
diff --git a/Build/source/libs/pplib/pplib-src/doc/make.bat b/Build/source/libs/pplib/pplib-src/doc/make.bat
index b1e0e54b1c0..45c4b0ea948 100644
--- a/Build/source/libs/pplib/pplib-src/doc/make.bat
+++ b/Build/source/libs/pplib/pplib-src/doc/make.bat
@@ -1,5 +1,7 @@
@ECHO OFF
+::set PATH=Q:\<wherepythonlives>\Scripts;%PATH%
+
pushd %~dp0
REM Command file for Sphinx documentation
diff --git a/Build/source/libs/pplib/pplib-src/doc/ppapi-2.x.rst b/Build/source/libs/pplib/pplib-src/doc/ppapi-2.x.rst
index 250cd8fcd35..c6779145a56 100644
--- a/Build/source/libs/pplib/pplib-src/doc/ppapi-2.x.rst
+++ b/Build/source/libs/pplib/pplib-src/doc/ppapi-2.x.rst
@@ -677,15 +677,14 @@ It is a common practise to *protect* documents with an empty password. Such docu
for a password), but some features (eg. printing) may restricted by the application.
When ``pplib`` detects encryption, it follows Acrobat approach and first tries an empty password. If it succeeds, ``pplib`` proceeeds normally, providing
-an access to decrypted strings and streams, as if they weren't ciphered. If the document is protected with non-empty password, ``pplib`` gives
-a way to provide a password and proceed. Until you provide a password, ``ppdoc`` object returned by ``ppdoc_load()`` function has all object wntries
-set to ``null``.
+an access to decrypted strings and streams, as if they weren't ciphered. If the document is protected with non-empty password, you have to call
+``ppdoc_crypt_pass()``. Until you provide a password, ``ppdoc`` object returned by ``ppdoc_load()`` function has all object entries set to ``null``.
-After loading a document you should check encryption status with::
+Once the document is loaded, encryption status can be checked with::
ppcrypt_status ppdoc_crypt_status (ppdoc *pdf);
-``ppcrypt_status`` (integer) may have the following values:
+``ppcrypt_status`` (enum) may have the following values:
``PPCRYPT_NONE`` - no encryption, go ahead
``PPCRYPT_DONE`` - encryption present but password succeeded, go ahead
@@ -697,10 +696,12 @@ If a password is needed, you can provide one with::
ppcrypt_status ppdoc_crypt_pass (ppdoc *pdf, const void *userpass, size_t userpasslength,
const void *ownerpass, size_t ownerpasslength);
-Well, yes, there are actually two passwords in encrypted documents. Relation between them is obscure to me, but enough
-to know that having one of them is enough to decrypt the document. If you know the password, you probably mean
-``userpass``, in which case you should put ``NULL`` as ``ownerpass``. The function returns ``PPCRYPT_DONE`` if the password
-succeeds and the previous status otherwise. Your custom loader function may look like that::
+Providing one of two is enough to decrypt the document.
+It is ok to use the same password for owner and user -- ``pplib`` will try both.
+
+The function returns ``PPCRYPT_DONE`` if the password succeeds and the previous crypt status otherwise.
+
+Your custom loader function may look like that::
ppdoc *pdf;
pdf = ppdoc_load("file.pdf");
@@ -712,8 +713,7 @@ succeeds and the previous status otherwise. Your custom loader function may look
case PPCRYPT_DONE:
return pdf;
case PPCRYPT_PASS:
- if (ppdoc_crypt_pass(pdf, "dummy", 5, NULL, 0) == PPCRYPT_DONE ||
- ppdoc_crypt_pass(pdf, NULL, 0, "dummy", 5) == PPCRYPT_DONE)
+ if (ppdoc_crypt_pass(pdf, "dummy", 5, "dummy", 5) == PPCRYPT_DONE)
return pdf;
printf("sorry, password needed\n");
ppdoc_free(pdf);
@@ -724,7 +724,7 @@ succeeds and the previous status otherwise. Your custom loader function may look
return NULL;
}
-[If you get ``PPCRYPT_FAIL`` it might mean *I failed*, so treat as a bug.]
+See ``pplib`` tests suite for a complete code.
If you'd like to know what permissions are given/restricted to encrypted document::
@@ -751,6 +751,15 @@ In encrypted documents most of streams are encrypted. To check if a given stream
Encryption is independent from compression, don't confuse with ``ppstream_compressed()``
+.. caution::
+ Starting from ``pplib v2.10`` all passwords should be passed as ``UTF-8``.
+ Earlier PDF encryption algorithms (/V 1..4, PDF 1.7) were based on ``PdfDocEncoding``.
+ Newer algorithms (/V 5, PDF 1.8-2.0) expect Unicode encoded as ``UTF-8``.
+ ``pplib`` API now expects ``UTF-8`` and if opening documents with older encryption methods,
+ it tries to make a conversion to 8-bit encoding. In earlier versions ``pplib`` didn't
+ make any password preprocessing, treating them as raw byte arrays.
+ So in case of passwords with fancy characters, it may behave differently.
+
Pages
-----
diff --git a/Build/source/libs/pplib/pplib-src/doc/ppcode.rst b/Build/source/libs/pplib/pplib-src/doc/ppcode.rst
index ebe92465d80..e9f6dc7adbd 100644
--- a/Build/source/libs/pplib/pplib-src/doc/ppcode.rst
+++ b/Build/source/libs/pplib/pplib-src/doc/ppcode.rst
@@ -95,7 +95,7 @@ v2.05
uint8_t instead of ppbyte in internals; ppbyte intent is "the most natural 8-bit integer", so it is 'char',
but internally we almost always need uint8_t (char may be signed or not..)
-TODO
-====
-- external streams (egzotic)
-
+v2.10
+-----
+Rework on encryption; algorithms /V5 /R6.
+Passwords passed to ppdoc_crypt_pass() should be UTF-8 (backward incompatible).
diff --git a/Build/source/libs/pplib/pplib-src/src/Makefile.vc b/Build/source/libs/pplib/pplib-src/src/Makefile.vc
index 481d9b20ab7..ac0f9d1c6f5 100644
--- a/Build/source/libs/pplib/pplib-src/src/Makefile.vc
+++ b/Build/source/libs/pplib/pplib-src/src/Makefile.vc
@@ -19,9 +19,10 @@ CFLAGS=/W3 /D_CRT_SECURE_NO_DEPRECATE /O2
# 4710: no inlined
# 4711: inline expansion
# 4706: assignment in conditionals
+# 4061: switch(enum) case label missing, even if default is there
#WFLAGS= /W3 /D_CRT_SECURE_NO_DEPRECATE
-WFLAGS= /Wall /D_CRT_SECURE_NO_DEPRECATE /wd5045 /wd4820 /wd4456 /wd4457 /wd4668 /wd4244 /wd4127 /wd4131 /wd4464 /wd4201 /wd4710 /wd4711
+WFLAGS= /Wall /D_CRT_SECURE_NO_DEPRECATE /wd5045 /wd4820 /wd4456 /wd4457 /wd4668 /wd4244 /wd4127 /wd4131 /wd4464 /wd4201 /wd4710 /wd4711 /wd4061
CFLAGS= $(WFLAGS) /O2
#LFLAGS = /NODEFAULTLIB:LIBCMT # produces binary dependent from redistributable
diff --git a/Build/source/libs/pplib/pplib-src/src/ppapi.h b/Build/source/libs/pplib/pplib-src/src/ppapi.h
index 94956f8cb56..56137f8f21f 100644
--- a/Build/source/libs/pplib/pplib-src/src/ppapi.h
+++ b/Build/source/libs/pplib/pplib-src/src/ppapi.h
@@ -8,7 +8,7 @@
#include "ppconf.h"
-#define pplib_version "v2.05 less toxic i hope"
+#define pplib_version "v2.2"
#define pplib_author "p.jackowski@gust.org.pl"
/* types */
diff --git a/Build/source/libs/pplib/pplib-src/src/ppcrypt.c b/Build/source/libs/pplib/pplib-src/src/ppcrypt.c
index 266bacc29b2..832e8c327cb 100644
--- a/Build/source/libs/pplib/pplib-src/src/ppcrypt.c
+++ b/Build/source/libs/pplib/pplib-src/src/ppcrypt.c
@@ -44,30 +44,156 @@ int ppcrypt_type (ppcrypt *crypt, ppname *cryptname, ppuint *length, int *cryptf
return 1;
}
-static const uint8_t padding_string[] = {
+/* V1..4 algorithms */
+
+/* V1..4 unicode do PdfDocEncoding */
+
+typedef struct {
+ uint32_t unicode;
+ uint32_t code;
+ uint32_t count;
+} map_range_t;
+
+static const map_range_t unicode_to_pdf_doc_encoding_map[] = {
+ { 32, 32, 95 },
+ { 161, 161, 12 },
+ { 174, 174, 82 },
+ { 305, 154, 1 },
+ { 321, 149, 1 },
+ { 322, 155, 1 },
+ { 338, 150, 1 },
+ { 339, 156, 1 },
+ { 352, 151, 1 },
+ { 353, 157, 1 },
+ { 376, 152, 1 },
+ { 381, 153, 1 },
+ { 382, 158, 1 },
+ { 402, 134, 1 },
+ { 710, 26, 1 },
+ { 711, 25, 1 },
+ { 728, 24, 1 },
+ { 729, 27, 1 },
+ { 730, 30, 1 },
+ { 731, 29, 1 },
+ { 732, 31, 1 },
+ { 733, 28, 1 },
+ { 8211, 133, 1 },
+ { 8212, 132, 1 },
+ { 8216, 143, 3 },
+ { 8220, 141, 2 },
+ { 8222, 140, 1 },
+ { 8224, 129, 2 },
+ { 8226, 128, 1 },
+ { 8230, 131, 1 },
+ { 8240, 139, 1 },
+ { 8249, 136, 2 },
+ { 8260, 135, 1 },
+ { 8364, 160, 1 },
+ { 8482, 146, 1 },
+ { 8722, 138, 1 },
+ { 64257, 147, 2 }
+};
+
+#define unicode_to_pdf_doc_encoding_entries (sizeof(unicode_to_pdf_doc_encoding_map) / sizeof(map_range_t))
+
+static int unicode_to_pdf_doc_encoding (uint32_t unicode, uint8_t *pcode)
+{
+ const map_range_t *left, *right, *mid;
+
+ left = &unicode_to_pdf_doc_encoding_map[0];
+ right = &unicode_to_pdf_doc_encoding_map[unicode_to_pdf_doc_encoding_entries - 1];
+ for ( ; left <= right; )
+ {
+ mid = left + ((right - left) / 2);
+ if (unicode > mid->unicode + mid->count - 1)
+ left = mid + 1;
+ else if (unicode < mid->unicode)
+ right = mid - 1;
+ else
+ {
+ *pcode = (uint8_t)(mid->code + (unicode - mid->unicode));
+ return 1;
+ }
+ }
+ return 0;
+}
+
+#define utf8_unicode2(p) (((p[0]&31)<<6)|(p[1]&63))
+#define utf8_unicode3(p) (((p[0]&15)<<12)|((p[1]&63)<<6)|(p[2]&63))
+#define utf8_unicode4(p) (((p[0]&7)<<18)|((p[1]&63)<<12)|((p[2]&63)<<6)|(p[3]&63))
+
+#define utf8_get1(p, e, unicode) ((unicode = p[0]), p + 1)
+#define utf8_get2(p, e, unicode) (p + 1 < e ? ((unicode = utf8_unicode2(p)), p + 2) : NULL)
+#define utf8_get3(p, e, unicode) (p + 2 < e ? ((unicode = utf8_unicode3(p)), p + 3) : NULL)
+#define utf8_get4(p, e, unicode) (p + 4 < e ? ((unicode = utf8_unicode3(p)), p + 4) : NULL)
+
+#define utf8_get(p, e, unicode) \
+ (p[0] < 0x80 ? utf8_get1(p, e, unicode) : \
+ p[0] < 0xC0 ? NULL : \
+ p[0] < 0xE0 ? utf8_get2(p, e, unicode) : \
+ p[0] < 0xF0 ? utf8_get3(p, e, unicode) : utf8_get4(p, e, unicode))
+
+static int ppcrypt_password_encoding (uint8_t *password, size_t *passwordlength)
+{
+ uint8_t *p, newpassword[PPCRYPT_MAX_PASSWORD], *n;
+ const uint8_t *e;
+ uint32_t unicode = 0;
+
+ for (n = &newpassword[0], p = &password[0], e = p + *passwordlength; p < e; ++n)
+ {
+ p = utf8_get(p, e, unicode);
+ if (p == NULL)
+ return 0;
+ if (unicode_to_pdf_doc_encoding(unicode, n) == 0)
+ return 0;
+ }
+ *passwordlength = n - &newpassword[0];
+ memcpy(password, newpassword, *passwordlength);
+ return 1;
+}
+
+/* setup passwords */
+
+static const uint8_t password_padding[] = {
0x28, 0xBF, 0x4E, 0x5E, 0x4E, 0x75, 0x8A, 0x41, 0x64, 0x00, 0x4E, 0x56, 0xFF, 0xFA, 0x01, 0x08,
0x2E, 0x2E, 0x00, 0xB6, 0xD0, 0x68, 0x3E, 0x80, 0x2F, 0x0C, 0xA9, 0xFE, 0x64, 0x53, 0x69, 0x7A
};
-static void ppcrypt_set_userpass (ppcrypt *crypt, const void *userpass, size_t userpasslength)
+static void ppcrypt_set_user_password (ppcrypt *crypt, const void *userpass, size_t userpasslength)
{
- crypt->userpasslength = userpasslength > 32 ? 32 : userpasslength;
+ crypt->userpasslength = userpasslength > PPCRYPT_MAX_PASSWORD ? PPCRYPT_MAX_PASSWORD : userpasslength;
memcpy(crypt->userpass, userpass, crypt->userpasslength);
- memcpy(crypt->userpass + crypt->userpasslength, padding_string, 32 - crypt->userpasslength);
+ if (crypt->algorithm_variant < 5)
+ {
+ if (ppcrypt_password_encoding(crypt->userpass, &crypt->userpasslength) == 0)
+ return;
+ if (crypt->userpasslength > 32)
+ crypt->userpasslength = 32;
+ else if (crypt->userpasslength < 32)
+ memcpy(&crypt->userpass[crypt->userpasslength], password_padding, 32 - crypt->userpasslength);
+ }
crypt->flags |= PPCRYPT_USER_PASSWORD;
}
-static void ppcrypt_set_ownerpass (ppcrypt *crypt, const void *ownerpass, size_t ownerpasslength)
+static void ppcrypt_set_owner_password (ppcrypt *crypt, const void *ownerpass, size_t ownerpasslength)
{
- crypt->ownerpasslength = ownerpasslength > 32 ? 32 : ownerpasslength;
+ crypt->ownerpasslength = ownerpasslength > PPCRYPT_MAX_PASSWORD ? PPCRYPT_MAX_PASSWORD : ownerpasslength;
memcpy(crypt->ownerpass, ownerpass, crypt->ownerpasslength);
- memcpy(crypt->ownerpass + crypt->ownerpasslength, padding_string, 32 - crypt->ownerpasslength);
+ if (crypt->algorithm_variant < 5)
+ {
+ if (ppcrypt_password_encoding(crypt->ownerpass, &crypt->ownerpasslength) == 0)
+ return;
+ if (crypt->ownerpasslength > 32)
+ crypt->ownerpasslength = 32;
+ else if (crypt->ownerpasslength < 32)
+ memcpy(&crypt->ownerpass[crypt->ownerpasslength], password_padding, 32 - crypt->ownerpasslength);
+ }
crypt->flags |= PPCRYPT_OWNER_PASSWORD;
}
-/* retrieving user password from owner password and owner key (variant < 5) */
+/* V1..4 retrieving user password from owner password and owner key (variant < 5) */
-static void ppcrypt_retrieve_userpass (ppcrypt *crypt, const void *ownerkey, size_t ownerkeysize)
+static void ppcrypt_user_password_from_owner_key (ppcrypt *crypt, const void *ownerkey, size_t ownerkeysize)
{
uint8_t temp[16], rc4key[32], rc4key2[32];
uint8_t i;
@@ -97,14 +223,14 @@ static void ppcrypt_retrieve_userpass (ppcrypt *crypt, const void *ownerkey, siz
}
//crypt->userpasslength = 32;
for (crypt->userpasslength = 0; crypt->userpasslength < 32; ++crypt->userpasslength)
- if (memcmp(&crypt->userpass[crypt->userpasslength], padding_string, 32 - crypt->userpasslength) == 0)
+ if (memcmp(&crypt->userpass[crypt->userpasslength], password_padding, 32 - crypt->userpasslength) == 0)
break;
crypt->flags |= PPCRYPT_USER_PASSWORD;
}
-/* generating file key; pdf spec p. 125 */
+/* V1..4 generating file key; pdf spec p. 125 */
-static void ppcrypt_filekey (ppcrypt *crypt, const void *ownerkey, size_t ownerkeysize, const void *id, size_t idsize)
+static void ppcrypt_compute_file_key (ppcrypt *crypt, const void *ownerkey, size_t ownerkeysize, const void *id, size_t idsize)
{
uint32_t p;
uint8_t permissions[4], temp[16];
@@ -134,9 +260,9 @@ static void ppcrypt_filekey (ppcrypt *crypt, const void *ownerkey, size_t ownerk
}
}
-/* generating userkey for comparison with /U; requires a general file key and id; pdf spec page 126-127 */
+/* V1..4 generating userkey for comparison with /U; requires a general file key and id; pdf spec page 126-127 */
-static void ppcrypt_userkey (ppcrypt *crypt, const void *id, size_t idsize, uint8_t *password_hash)
+static void ppcrypt_compute_user_key (ppcrypt *crypt, const void *id, size_t idsize, uint8_t password_hash[32])
{
uint8_t rc4key2[32];
uint8_t i;
@@ -144,13 +270,13 @@ static void ppcrypt_userkey (ppcrypt *crypt, const void *id, size_t idsize, uint
if (crypt->algorithm_revision <= 2)
{
- rc4_encode_data(padding_string, 32, password_hash, crypt->filekey, crypt->filekeylength);
+ rc4_encode_data(password_padding, 32, password_hash, crypt->filekey, crypt->filekeylength);
}
else
{
md5_state md5;
md5_digest_init(&md5);
- md5_digest_add(&md5, padding_string, 32);
+ md5_digest_add(&md5, password_padding, 32);
md5_digest_add(&md5, id, idsize);
md5_digest_get(&md5, password_hash, MD5_BYTES);
rc4_encode_data(password_hash, 16, password_hash, crypt->filekey, crypt->filekeylength);
@@ -165,25 +291,127 @@ static void ppcrypt_userkey (ppcrypt *crypt, const void *id, size_t idsize, uint
}
}
-/* validating /Perms key (pdf 1.7, /V 5 /R 5 crypt) */
+static ppcrypt_status ppcrypt_authenticate_legacy (ppcrypt *crypt, ppstring *userkey, ppstring *ownerkey, ppstring *id)
+{
+ uint8_t password_hash[32];
+
+ if ((crypt->flags & PPCRYPT_USER_PASSWORD) == 0 && (crypt->flags & PPCRYPT_OWNER_PASSWORD) != 0)
+ ppcrypt_user_password_from_owner_key(crypt, ownerkey, ownerkey->size);
+ ppcrypt_compute_file_key(crypt, ownerkey->data, ownerkey->size, id->data, id->size);
+ ppcrypt_compute_user_key(crypt, id->data, id->size, password_hash); /* needs file key */
+ return memcmp(userkey->data, password_hash, (crypt->algorithm_revision >= 3 ? 16 : 32)) == 0 ? PPCRYPT_DONE : PPCRYPT_PASS;
+}
+
+/* V5 */
static const uint8_t nulliv[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; /* AES-256 initialization vector */
-static ppcrypt_status ppcrypt_authenticate_perms (ppcrypt *crypt, ppstring *perms)
-{ /* decode /Perms string overriding crypt setup (should match anyway) */
+/* V5 R5..6 password hash */
+
+#define PPCRYPT_MAX_MANGLED ((127+64+48)*64) // 127 password, 64 hash, 48 /U key
+
+static void ppcrypt_password_hash_indeed (const uint8_t *password, size_t passwordlength, const uint8_t *userkey, uint8_t hash[64])
+{
+ size_t hashlength, datalength;
+ uint8_t data[PPCRYPT_MAX_MANGLED], *pdata;
+ uint8_t *key, *iv;
+ uint8_t round, i;
+ uint32_t div3;
+
+ hashlength = 32; /* initial hash is sha256 */
+ round = 0;
+ do
+ {
+ /* concat password, hash, and /U value 64 times */
+ pdata = &data[0];
+ memcpy(pdata, password, passwordlength);
+ pdata += passwordlength;
+ memcpy(pdata, hash, hashlength);
+ pdata += hashlength;
+ if (userkey != NULL)
+ {
+ memcpy(pdata, userkey, 48);
+ pdata += 48;
+ }
+ datalength = pdata - &data[0];
+ for (i = 1; i < 64; ++i, pdata += datalength)
+ memcpy(pdata, &data[0], datalength);
+ datalength *= 64;
+
+ /* encrypt the data with aes128 using hash bytes 1..16 as key and bytes 17..32 as initialization vector
+ encryption inplace, CBC, no-padding, no change to datalength */
+ key = &hash[0]; iv = &hash[16];
+ aes_encode_data(data, datalength, data, key, 16, iv, AES_NULL_PADDING);
+
+ /* get modulo 3 of first 16 bytes number of encrypted data (sum of digits modulo 3) */
+ for (i = 0, div3 = 0; i < 16; ++i)
+ div3 += data[i];
+
+ /* compute new hash using sha256/384/512 */
+ switch (div3 % 3)
+ {
+ case 0:
+ sha256_digest(data, datalength, hash, SHA_BYTES);
+ hashlength = 32;
+ break;
+ case 1:
+ sha384_digest(data, datalength, hash, SHA_BYTES);
+ hashlength = 48;
+ break;
+ case 2:
+ sha512_digest(data, datalength, hash, SHA_BYTES);
+ hashlength = 64;
+ break;
+ }
+
+ /* do 64 times, then keep going until the last byte of data <= round - 32 */
+ } while (++round < 64 || round < data[datalength - 1] + 32);
+
+}
+
+static void ppcrypt_password_hash (ppcrypt *crypt, const uint8_t *password, size_t passwordlength, const uint8_t *salt, const uint8_t *userkey, uint8_t password_hash[32])
+{
+ sha256_state sha;
+ uint8_t hash[64]; /* result password_hash is 32 bytes, but we need 64 for R6 procedure */
+
+ /* take sha256 of password, salt and /U */
+ sha256_digest_init(&sha);
+ sha256_digest_add(&sha, password, passwordlength);
+ sha256_digest_add(&sha, salt, 8);
+ if (userkey != NULL)
+ sha256_digest_add(&sha, userkey, 48);
+ sha256_digest_get(&sha, hash, SHA_BYTES);
+
+ /* V5 R5 - password_hash is the digest, V5 R6 - password_hash is mangled */
+ if (crypt->algorithm_revision >= 6)
+ ppcrypt_password_hash_indeed(password, passwordlength, userkey, hash);
+
+ memcpy(password_hash, hash, 32);
+}
+
+/* V5 permissions */
+
+static ppcrypt_status ppcrypt_authenticate_permissions (ppcrypt *crypt, ppstring *perms)
+{
uint8_t permsdata[16];
- //int64_t p;
- //int i;
aes_decode_data(perms->data, perms->size, permsdata, crypt->filekey, crypt->filekeylength, nulliv, AES_NULL_PADDING);
if (permsdata[9] != 'a' || permsdata[10] != 'd' || permsdata[11] != 'b')
- return PPCRYPT_FAIL;
+ { /* if we get here, the password hash is correct, we don't need to fail because of unreadable perms (found such docs) */
+ crypt->flags |= PPCRYPT_UNREADABLE_PERMISSIONS;
+ return PPCRYPT_DONE;
+ }
- // do not update permissions flags; they seem to be different inside crypt string
- //for (p = 0, i = 0; i < 8; ++i)
- // p = p + (permsdata[i] << (i << 3)); /* low order bytes first */
- //crypt->permissions = (ppint)(int32_t)(p & 0x00000000FFFFFFFFLL); /* unset bits 33..64, treat as 32-bit signed int */
+ /* do not check/update permissions flags here; they might be different inside crypt string */
+ if (0)
+ {
+ int64_t p;
+ int i;
+ for (p = 0, i = 0; i < 8; ++i)
+ p = p + (permsdata[i] << (i << 3)); /* low order bytes first */
+ crypt->permissions = (ppint)((int32_t)(p & 0x00000000FFFFFFFFLL)); /* unset bits 33..64, treat as 32-bit signed int */
+ }
if (permsdata[8] == 'T')
crypt->flags &= ~PPCRYPT_NO_METADATA;
@@ -193,6 +421,61 @@ static ppcrypt_status ppcrypt_authenticate_perms (ppcrypt *crypt, ppstring *perm
return PPCRYPT_DONE;
}
+/* V5 authentication */
+
+static ppcrypt_status ppcrypt_authenticate_user (ppcrypt *crypt, ppstring *u, ppstring *ue, ppstring *perms)
+{
+ uint8_t password_hash[32], *salt;
+
+ salt = (uint8_t *)&u->data[32]; /* validation salt */
+ ppcrypt_password_hash(crypt, crypt->userpass, crypt->userpasslength, salt, NULL, password_hash);
+ if (memcmp(u->data, password_hash, 32) != 0)
+ return PPCRYPT_PASS;
+
+ salt = (uint8_t *)&u->data[40]; /* key salt */
+ ppcrypt_password_hash(crypt, crypt->userpass, crypt->userpasslength, salt, NULL, password_hash);
+ aes_decode_data(ue->data, 32, crypt->filekey, password_hash, 32, nulliv, AES_NULL_PADDING);
+
+ return ppcrypt_authenticate_permissions(crypt, perms);
+}
+
+static ppcrypt_status ppcrypt_authenticate_owner (ppcrypt *crypt, ppstring *u, ppstring *o, ppstring *oe, ppstring *perms)
+{
+ uint8_t password_hash[32], *salt;
+
+ salt = (uint8_t *)&o->data[32]; /* validation salt */
+ ppcrypt_password_hash(crypt, crypt->ownerpass, crypt->ownerpasslength, salt, (uint8_t *)u->data, password_hash);
+ if (memcmp(o->data, password_hash, 32) != 0)
+ return PPCRYPT_PASS;
+
+ salt = (uint8_t *)&o->data[40]; /* key salt */
+ ppcrypt_password_hash(crypt, crypt->ownerpass, crypt->ownerpasslength, salt, (uint8_t *)u->data, password_hash);
+ aes_decode_data(oe->data, 32, crypt->filekey, password_hash, 32, nulliv, AES_NULL_PADDING);
+
+ return ppcrypt_authenticate_permissions(crypt, perms);
+}
+
+
+/* authentication */
+
+static ppcrypt_status ppcrypt_authenticate (ppcrypt *crypt, ppstring *u, ppstring *ue, ppstring *o, ppstring *oe, ppstring *id, ppstring *perms)
+{
+ /* V1..V4 */
+ if (crypt->algorithm_variant < 5)
+ return ppcrypt_authenticate_legacy(crypt, u, o, id);
+
+ /* V5 */
+ if (crypt->flags & PPCRYPT_USER_PASSWORD)
+ if (ppcrypt_authenticate_user(crypt, u, ue, perms) == PPCRYPT_DONE)
+ return PPCRYPT_DONE;
+ if (crypt->flags & PPCRYPT_OWNER_PASSWORD)
+ return ppcrypt_authenticate_owner(crypt, u, o, oe, perms);
+
+ return PPCRYPT_PASS;
+}
+
+/**/
+
ppcrypt_status ppdoc_crypt_init (ppdoc *pdf, const void *userpass, size_t userpasslength, const void *ownerpass, size_t ownerpasslength)
{
ppcrypt *crypt;
@@ -206,15 +489,11 @@ ppcrypt_status ppdoc_crypt_init (ppdoc *pdf, const void *userpass, size_t userpa
int cryptflags, encryptmd;
size_t strkeylength, stmkeylength;
- uint8_t password_hash[32]; /* /U and /O are 48 bytes strings for AES-256, but here we use only 32 */
- uint8_t *validation_salt, *key_salt;
-
- /* Every xref could theoretically have a separate encryption info. Not clarified in pdf spec but it seems that the top
- level xref encryption info is the one to be applied to all objects in all xrefs, including older. */
trailer = ppxref_trailer(pdf->xref);
if ((obj = ppdict_get_obj(trailer, "Encrypt")) == NULL)
return PPCRYPT_NONE;
- /* Typically this is all done early, before loading body, so if /Encrypt is indirect reference, it points nothing. We have to load it here. */
+
+ /* this happens early, before loading body, so if /Encrypt is indirect reference, it points nothing */
obj = ppobj_preloaded(pdf, obj);
if (obj->type != PPDICT)
return PPCRYPT_FAIL;
@@ -227,20 +506,23 @@ ppcrypt_status ppdoc_crypt_init (ppdoc *pdf, const void *userpass, size_t userpa
if ((crypt = pdf->crypt) == NULL)
crypt = pdf->crypt = ppcrypt_create(&pdf->heap);
+
+ /* get /V /R /P */
if (!ppdict_get_uint(encrypt, "V", &crypt->algorithm_variant))
crypt->algorithm_variant = 0;
if (crypt->algorithm_variant < 1 || crypt->algorithm_variant > 5)
return PPCRYPT_FAIL;
if (!ppdict_get_uint(encrypt, "R", &crypt->algorithm_revision))
return PPCRYPT_FAIL;
- if (crypt->algorithm_revision >= 3)
- crypt->flags |= PPCRYPT_OBSCURITY;
if (!ppdict_get_int(encrypt, "P", &crypt->permissions))
return PPCRYPT_FAIL;
+
+ /* get /O /U /ID /OE /UE */
if ((userkey = ppdict_get_string(encrypt, "U")) == NULL || (ownerkey = ppdict_get_string(encrypt, "O")) == NULL)
return PPCRYPT_FAIL;
userkey = ppstring_decoded(userkey);
ownerkey = ppstring_decoded(ownerkey);
+
/* for some reason acrobat pads /O and /U to 127 bytes with NULL, so we don't check the exact length but ensure the minimal */
hashlength = crypt->algorithm_variant < 5 ? 32 : 48;
if (userkey->size < hashlength || ownerkey->size < hashlength)
@@ -266,6 +548,7 @@ ppcrypt_status ppdoc_crypt_init (ppdoc *pdf, const void *userpass, size_t userpa
return PPCRYPT_FAIL;
}
+ /* collect flags and keylength */
switch (crypt->algorithm_revision)
{
case 1:
@@ -279,7 +562,7 @@ ppcrypt_status ppdoc_crypt_init (ppdoc *pdf, const void *userpass, size_t userpa
crypt->filekeylength = 5; /* 40 bits, 5 bytes */
crypt->flags |= PPCRYPT_RC4;
break;
- case 4: case 5:
+ case 4: case 5: case 6:
if ((crypt->map = ppdict_rget_dict(encrypt, "CF")) == NULL)
return PPCRYPT_FAIL;
for (ppdict_first(crypt->map, pkey, obj); *pkey != NULL; ppdict_next(pkey, obj))
@@ -327,72 +610,15 @@ ppcrypt_status ppdoc_crypt_init (ppdoc *pdf, const void *userpass, size_t userpa
return PPCRYPT_FAIL;
}
- /* password */
-
+ /* setup passwords */
if (userpass != NULL)
- {
- ppcrypt_set_userpass(crypt, userpass, userpasslength);
- }
- else if (ownerpass != NULL)
- {
- if (crypt->algorithm_variant < 5) // fetch user password from owner password
- ppcrypt_retrieve_userpass(crypt, ownerkey, ppstring_size(ownerkey));
- else // open the document using owner password
- ppcrypt_set_ownerpass(crypt, ownerpass, ownerpasslength);
- }
- else
- {
- return PPCRYPT_FAIL;
- }
-
- if (crypt->algorithm_variant < 5)
- { /* authenticate by comparing a generated vs present /U entry; depending on variant 16 or 32 bytes to compare */
- ppcrypt_filekey(crypt, ownerkey->data, ownerkey->size, id->data, id->size);
- ppcrypt_userkey(crypt, id->data, id->size, password_hash); /* needs file key so comes after key generation */
- if (memcmp(userkey->data, password_hash, (crypt->algorithm_revision >= 3 ? 16 : 32)) == 0)
- return PPCRYPT_DONE;
+ ppcrypt_set_user_password(crypt, userpass, userpasslength);
+ if (ownerpass != NULL)
+ ppcrypt_set_owner_password(crypt, ownerpass, ownerpasslength);
+ if ((crypt->flags & (PPCRYPT_USER_PASSWORD|PPCRYPT_OWNER_PASSWORD)) == 0)
return PPCRYPT_PASS;
- }
- if (crypt->flags & PPCRYPT_USER_PASSWORD)
- {
- sha256_state sha;
- validation_salt = (uint8_t *)userkey + 32;
- key_salt = validation_salt + 8;
- sha256_digest_init(&sha);
- sha256_digest_add(&sha, crypt->userpass, crypt->userpasslength);
- sha256_digest_add(&sha, validation_salt, 8);
- sha256_digest_get(&sha, password_hash, SHA_BYTES);
- if (memcmp(userkey->data, password_hash, 32) != 0)
- return PPCRYPT_PASS;
- sha256_digest_init(&sha);
- sha256_digest_add(&sha, crypt->userpass, crypt->userpasslength);
- sha256_digest_add(&sha, key_salt, 8);
- sha256_digest_get(&sha, password_hash, SHA_BYTES);
- aes_decode_data(userkey_e->data, 32, crypt->filekey, password_hash, 32, nulliv, AES_NULL_PADDING);
- return ppcrypt_authenticate_perms(crypt, perms);
- }
- if (crypt->flags & PPCRYPT_OWNER_PASSWORD)
- {
- sha256_state sha;
- validation_salt = (uint8_t *)ownerkey + 32;
- key_salt = validation_salt + 8;
- sha256_digest_init(&sha);
- sha256_digest_add(&sha, crypt->ownerpass, crypt->ownerpasslength);
- sha256_digest_add(&sha, validation_salt, 8);
- sha256_digest_add(&sha, userkey, 48);
- sha256_digest_get(&sha, password_hash, SHA_BYTES);
- if (memcmp(ownerkey->data, password_hash, 32) != 0)
- return PPCRYPT_PASS;
- sha256_digest_init(&sha);
- sha256_digest_add(&sha, crypt->ownerpass, crypt->ownerpasslength);
- sha256_digest_add(&sha, key_salt, 8);
- sha256_digest_add(&sha, userkey, 48);
- sha256_digest_get(&sha, password_hash, SHA_BYTES);
- aes_decode_data(ownerkey_e->data, 32, crypt->filekey, password_hash, 32, nulliv, AES_NULL_PADDING);
- return ppcrypt_authenticate_perms(crypt, perms);
- }
- return PPCRYPT_FAIL; // should never get here
+ return ppcrypt_authenticate(crypt, userkey, userkey_e, ownerkey, ownerkey_e, id, perms);
}
/* decrypting strings */
@@ -429,10 +655,10 @@ static void ppcrypt_strkey (ppcrypt *crypt, ppref *ref, int aes)
if (aes)
{
- crypt->filekey[crypt->filekeylength + 5] = 0x73;
- crypt->filekey[crypt->filekeylength + 6] = 0x41;
- crypt->filekey[crypt->filekeylength + 7] = 0x6C;
- crypt->filekey[crypt->filekeylength + 8] = 0x54;
+ crypt->filekey[crypt->filekeylength + 5] = 0x73; // s
+ crypt->filekey[crypt->filekeylength + 6] = 0x41; // A
+ crypt->filekey[crypt->filekeylength + 7] = 0x6C; // l
+ crypt->filekey[crypt->filekeylength + 8] = 0x54; // T
}
md5_digest(crypt->filekey, crypt->filekeylength + (aes ? 9 : 5), crypt->cryptkey, MD5_BYTES);
diff --git a/Build/source/libs/pplib/pplib-src/src/ppcrypt.h b/Build/source/libs/pplib/pplib-src/src/ppcrypt.h
index 98864f860c7..a7131adbb31 100644
--- a/Build/source/libs/pplib/pplib-src/src/ppcrypt.h
+++ b/Build/source/libs/pplib/pplib-src/src/ppcrypt.h
@@ -6,21 +6,25 @@
#include "utilcrypt.h"
#include "utilcryptdef.h"
+#define PPCRYPT_MAX_PASSWORD 127
+#define PPCRYPT_MAX_KEY 32
+
typedef struct {
- ppuint algorithm_variant; /* /V entry of encrypt dict */
- ppuint algorithm_revision; /* /R entry of encrypt dict */
- ppint permissions; /* /P entry of encrypt dict */
- ppdict *map; /* /CF filters map of encrypt dict */
- uint8_t userpass[32]; /* padded user password */
- size_t userpasslength; /* the length of unpadded user password */
- uint8_t ownerpass[32]; /* padded owner password */
- size_t ownerpasslength; /* the length of unpadded owner password */
- uint8_t filekey[32+5+4]; /* generated file key with extra space of 5..9 bytes for salt */
- size_t filekeylength; /* key length; usually 5, 16 or 32 bytes */
- uint8_t cryptkey[32]; /* final crypt key for a given reference */
- size_t cryptkeylength; /* final crypt key length; usually keylength + 5 */
- ppref *ref; /* currently loaded ref (each ref may have a different key) */
- union { /* cached crypt states for strings encrypted/decrypted with the same key */
+ ppuint algorithm_variant; /* /V entry of encrypt dict */
+ ppuint algorithm_revision; /* /R entry of encrypt dict */
+ ppint permissions; /* /P entry of encrypt dict */
+ ppdict *map; /* /CF filters map of encrypt dict */
+ uint8_t userpass[PPCRYPT_MAX_PASSWORD]; /* user password */
+ size_t userpasslength; /* user password length */
+ uint8_t ownerpass[PPCRYPT_MAX_PASSWORD]; /* owner password */
+ size_t ownerpasslength; /* owner password length */
+ uint8_t filekey[PPCRYPT_MAX_KEY+5+4]; /* file key with an extra space for salt */
+ size_t filekeylength; /* key length; usually 5, 16 or 32 bytes */
+ uint8_t cryptkey[PPCRYPT_MAX_KEY]; /* crypt key for a recent reference */
+ size_t cryptkeylength; /* crypt key length; usually keylength + 5 */
+ //ppstring *cryptkeystring; /* todo: cached cryptkey string for V5, where all refs has the same */
+ ppref *ref; /* recent reference */
+ union { /* cached crypt states for strings encrypted/decrypted with the same key */
struct {
rc4_state rc4state;
rc4_map rc4map;
@@ -42,7 +46,7 @@ typedef struct {
#define PPCRYPT_STRING_RC4 (1<<4)
#define PPCRYPT_STREAM_AES (1<<5)
#define PPCRYPT_STRING_AES (1<<6)
-#define PPCRYPT_OBSCURITY (1<<7)
+#define PPCRYPT_UNREADABLE_PERMISSIONS (1<<7)
#define PPCRYPT_STREAM (PPCRYPT_STREAM_AES|PPCRYPT_STREAM_RC4)
#define PPCRYPT_STRING (PPCRYPT_STRING_AES|PPCRYPT_STRING_RC4)
diff --git a/Build/source/libs/pplib/pplib-src/src/pptest2.c b/Build/source/libs/pplib/pplib-src/src/pptest2.c
index 766110da4cd..5dff63afda1 100644
--- a/Build/source/libs/pplib/pplib-src/src/pptest2.c
+++ b/Build/source/libs/pplib/pplib-src/src/pptest2.c
@@ -28,6 +28,9 @@ static int usage (const char *argv0)
{
printf("pplib " pplib_version ", " pplib_author "\n");
printf("usage: %s file1.pdf file2.pdf ...\n", argv0);
+ printf(" %s file.pdf -u userpassword\n", argv0);
+ printf(" %s file.pdf -o ownerpassword\n", argv0);
+ printf(" %s file.pdf -p bothpasswords\n", argv0);
return 0;
}
@@ -36,11 +39,27 @@ static void log_callback (const char *message, void *alien)
fprintf((FILE *)alien, "\nooops: %s\n", message);
}
+static const char * get_next_argument (const char *opt, int *a, int argc, const char **argv)
+{
+ const char *next;
+ if ((*a) + 2 < argc)
+ {
+ next = argv[*a + 1];
+ if (strcmp(next, opt) == 0)
+ {
+ *a += 2;
+ return argv[*a];
+ }
+ }
+ return NULL;
+}
+
int main (int argc, const char **argv)
{
- const char *filepath;
+ const char *filepath, *password;
int a;
ppdoc *pdf;
+ ppcrypt_status cryptstatus;
ppref *pageref;
ppdict *pagedict;
int pageno;
@@ -61,6 +80,7 @@ int main (int argc, const char **argv)
context = ppcontext_new();
for (a = 1; a < argc; ++a)
{
+ /* load */
filepath = argv[a];
printf("loading %s... ", filepath);
pdf = ppdoc_load(filepath);
@@ -69,23 +89,35 @@ int main (int argc, const char **argv)
printf("failed\n");
continue;
}
- printf("done.\n");
- switch (ppdoc_crypt_status(pdf))
+ printf("done\n");
+
+ /* decrypt */
+ if ((password = get_next_argument("-u", &a, argc, argv)) != NULL)
+ cryptstatus = ppdoc_crypt_pass(pdf, password, strlen(password), NULL, 0);
+ else if ((password = get_next_argument("-o", &a, argc, argv)) != NULL)
+ cryptstatus = ppdoc_crypt_pass(pdf, NULL, 0, password, strlen(password));
+ else if ((password = get_next_argument("-p", &a, argc, argv)) != NULL)
+ cryptstatus = ppdoc_crypt_pass(pdf, password, strlen(password), password, strlen(password));
+ else
+ cryptstatus = ppdoc_crypt_status(pdf);
+ switch (cryptstatus)
{
case PPCRYPT_NONE:
+ break;
case PPCRYPT_DONE:
+ printf("opened with password '%s'\n", password != NULL ? password : "");
break;
case PPCRYPT_PASS:
- if (ppdoc_crypt_pass(pdf, "dummy", 5, NULL, 0) == PPCRYPT_DONE || ppdoc_crypt_pass(pdf, NULL, 0, "dummy", 5) == PPCRYPT_DONE)
- break;
- printf("sorry, password needed\n");
+ printf("invalid password\n");
ppdoc_free(pdf);
continue;
case PPCRYPT_FAIL:
- printf("sorry, encryption failed\n");
+ printf("invalid encryption\n");
ppdoc_free(pdf);
continue;
}
+
+ /* process */
sprintf(outname, "%s.out", filepath);
fh = fopen(outname, "wb");
if (fh == NULL)