diff --git a/libs/pplib/ChangeLog b/libs/pplib/ChangeLog index dc14799022..a9e6d8fa69 100644 --- a/libs/pplib/ChangeLog +++ b/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/libs/pplib/pplib-src/doc/_build/doctrees/environment.pickle b/libs/pplib/pplib-src/doc/_build/doctrees/environment.pickle index c4d657a111..5d5fcb14a4 100644 Binary files a/libs/pplib/pplib-src/doc/_build/doctrees/environment.pickle and b/libs/pplib/pplib-src/doc/_build/doctrees/environment.pickle differ diff --git a/libs/pplib/pplib-src/doc/_build/doctrees/ppapi-1.x.doctree b/libs/pplib/pplib-src/doc/_build/doctrees/ppapi-1.x.doctree index bd22032c65..54e4f6f3e3 100644 Binary files a/libs/pplib/pplib-src/doc/_build/doctrees/ppapi-1.x.doctree and b/libs/pplib/pplib-src/doc/_build/doctrees/ppapi-1.x.doctree differ diff --git a/libs/pplib/pplib-src/doc/_build/doctrees/ppapi-2.x.doctree b/libs/pplib/pplib-src/doc/_build/doctrees/ppapi-2.x.doctree index d8c91b48be..ddf23cd91c 100644 Binary files a/libs/pplib/pplib-src/doc/_build/doctrees/ppapi-2.x.doctree and b/libs/pplib/pplib-src/doc/_build/doctrees/ppapi-2.x.doctree differ diff --git a/libs/pplib/pplib-src/doc/_build/doctrees/ppcode.doctree b/libs/pplib/pplib-src/doc/_build/doctrees/ppcode.doctree index a33b506208..a8e4dba8cb 100644 Binary files a/libs/pplib/pplib-src/doc/_build/doctrees/ppcode.doctree and b/libs/pplib/pplib-src/doc/_build/doctrees/ppcode.doctree differ diff --git a/libs/pplib/pplib-src/doc/_build/doctrees/pplib.doctree b/libs/pplib/pplib-src/doc/_build/doctrees/pplib.doctree index 0d5e84fe5a..36be14515f 100644 Binary files a/libs/pplib/pplib-src/doc/_build/doctrees/pplib.doctree and b/libs/pplib/pplib-src/doc/_build/doctrees/pplib.doctree differ diff --git a/libs/pplib/pplib-src/doc/_build/doctrees/ppnew.doctree b/libs/pplib/pplib-src/doc/_build/doctrees/ppnew.doctree index 5c152d321a..f79b5923a5 100644 Binary files a/libs/pplib/pplib-src/doc/_build/doctrees/ppnew.doctree and b/libs/pplib/pplib-src/doc/_build/doctrees/ppnew.doctree differ diff --git a/libs/pplib/pplib-src/doc/_build/html/_sources/ppapi-2.x.rst.txt b/libs/pplib/pplib-src/doc/_build/html/_sources/ppapi-2.x.rst.txt index 250cd8fcd3..c6779145a5 100644 --- a/libs/pplib/pplib-src/doc/_build/html/_sources/ppapi-2.x.rst.txt +++ b/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/libs/pplib/pplib-src/doc/_build/html/_sources/ppcode.rst.txt b/libs/pplib/pplib-src/doc/_build/html/_sources/ppcode.rst.txt index ebe92465d8..e9f6dc7adb 100644 --- a/libs/pplib/pplib-src/doc/_build/html/_sources/ppcode.rst.txt +++ b/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/libs/pplib/pplib-src/doc/_build/html/genindex.html b/libs/pplib/pplib-src/doc/_build/html/genindex.html index 24eed9d3c2..4e8b364757 100644 --- a/libs/pplib/pplib-src/doc/_build/html/genindex.html +++ b/libs/pplib/pplib-src/doc/_build/html/genindex.html @@ -79,7 +79,7 @@

Navigation

\ No newline at end of file diff --git a/libs/pplib/pplib-src/doc/_build/html/ppapi-1.x.html b/libs/pplib/pplib-src/doc/_build/html/ppapi-1.x.html index 838aee5217..186a5c6df2 100644 --- a/libs/pplib/pplib-src/doc/_build/html/ppapi-1.x.html +++ b/libs/pplib/pplib-src/doc/_build/html/ppapi-1.x.html @@ -1024,7 +1024,7 @@

Navigation

\ No newline at end of file diff --git a/libs/pplib/pplib-src/doc/_build/html/ppapi-2.x.html b/libs/pplib/pplib-src/doc/_build/html/ppapi-2.x.html index cac0fcec99..9222889331 100644 --- a/libs/pplib/pplib-src/doc/_build/html/ppapi-2.x.html +++ b/libs/pplib/pplib-src/doc/_build/html/ppapi-2.x.html @@ -752,14 +752,13 @@

Encryptionpplib 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.

-

After loading a document you should check encryption status with:

+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.

+

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 @@ -770,10 +769,10 @@

Encryptionconst 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:

-

[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:

Pages

@@ -1025,7 +1033,7 @@

Navigation

\ No newline at end of file diff --git a/libs/pplib/pplib-src/doc/_build/html/ppcode.html b/libs/pplib/pplib-src/doc/_build/html/ppcode.html index 8645450d8e..fdd52f528d 100644 --- a/libs/pplib/pplib-src/doc/_build/html/ppcode.html +++ b/libs/pplib/pplib-src/doc/_build/html/ppcode.html @@ -63,9 +63,9 @@

Table of Contents

  • v2.03
  • v2.04
  • v2.05
  • +
  • v2.10
  • -
  • TODO
  • Previous topic

    @@ -212,143 +212,175 @@

    Example 1

    Example 2

    
    -#include <stdio.h>
    -#include <assert.h>
    -#include "ppapi.h"
    +#include <stdio.h>
    +#include <assert.h>
    +#include "ppapi.h"
     
    -/*
    -static const char * get_file_name (const char *path)
    -{
    -  const char *fn, *p;
    -  for (fn = p = path; *p != '\0'; ++p)
    -    if (*p == '\\' || *p == '/')
    -      fn = p + 1;
    -  return fn;
    -}
    -*/
    +/*
    +static const char * get_file_name (const char *path)
    +{
    +  const char *fn, *p;
    +  for (fn = p = path; *p != '\0'; ++p)
    +    if (*p == '\\' || *p == '/')
    +      fn = p + 1;
    +  return fn;
    +}
    +*/
     
    -static void box_info (ppdict *pagedict, FILE *fh)
    -{
    -  const char *boxes[] = {"MediaBox", "CropBox", "BleedBox", "TrimBox", "ArtBox"};
    -  pprect rect;
    -  size_t i;
    -  for (i = 0; i < sizeof(boxes) / sizeof(const char *); ++i)
    -    if (ppdict_get_box(pagedict, boxes[i], &rect))
    -      fprintf(fh, "%%%% %s [%f %f %f %f]\n", boxes[i], rect.lx, rect.ly, rect.rx, rect.ry);
    -}
    +static void box_info (ppdict *pagedict, FILE *fh)
    +{
    +  const char *boxes[] = {"MediaBox", "CropBox", "BleedBox", "TrimBox", "ArtBox"};
    +  pprect rect;
    +  size_t i;
    +  for (i = 0; i < sizeof(boxes) / sizeof(const char *); ++i)
    +    if (ppdict_get_box(pagedict, boxes[i], &rect))
    +      fprintf(fh, "%%%% %s [%f %f %f %f]\n", boxes[i], rect.lx, rect.ly, rect.rx, rect.ry);
    +}
     
    -static int usage (const char *argv0)
    -{
    -  printf("pplib " pplib_version ", " pplib_author "\n");
    -  printf("usage: %s file1.pdf file2.pdf ...\n", argv0);
    -  return 0;
    -}
    +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;
    +}
     
    -static void log_callback (const char *message, void *alien)
    -{
    -  fprintf((FILE *)alien, "\nooops: %s\n", message);
    -}
    +static void log_callback (const char *message, void *alien)
    +{
    +  fprintf((FILE *)alien, "\nooops: %s\n", message);
    +}
     
    -int main (int argc, const char **argv)
    -{
    -  const char *filepath;
    -  int a;
    -  ppdoc *pdf;
    -  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;
    +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;
    +}
     
    -  if (argc < 2)
    -    return usage(argv[0]);
    -  ppstream_init_buffers();
    -  pplog_callback(log_callback, stderr);
    -  context = ppcontext_new();
    -  for (a = 1; a < argc; ++a)
    -  {
    -    filepath = argv[a];
    -    printf("loading %s... ", filepath);
    -    pdf = ppdoc_load(filepath);
    -    if (pdf == NULL)
    -    {
    -      printf("failed\n");
    -      continue;
    -    }
    -    printf("done.\n");
    -    switch (ppdoc_crypt_status(pdf))
    -    {
    -      case PPCRYPT_NONE:
    -      case PPCRYPT_DONE:
    -        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");
    -        ppdoc_free(pdf);
    -        continue;
    -      case PPCRYPT_FAIL:
    -        printf("sorry, encryption failed\n");
    -        ppdoc_free(pdf);
    -        continue;
    -    }
    -    sprintf(outname, "%s.out", filepath);
    -    fh = fopen(outname, "wb");
    -    if (fh == NULL)
    -    {
    -      printf("can't open %s for writing\n", outname);
    -      continue;
    -    }
    -    for (pageref = ppdoc_first_page(pdf), pageno = 1;
    -         pageref != NULL;
    -         pageref = ppdoc_next_page(pdf), ++pageno)
    -    {
    -      pagedict = pageref->object.dict;
    -      /* decompress contents data */
    -      fprintf(fh, "%%%% PAGE %d\n", pageno);
    -      box_info(pagedict, fh);
    -      for (stream = ppcontents_first(pagedict);
    -           stream != NULL;
    -           stream = ppcontents_next(pagedict, stream))
    -      {
    -        for (data = ppstream_first(stream, &size, 1);
    -             data != NULL;
    -             data = ppstream_next(stream, &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, &size, &op);
    -             obj != NULL;
    -             obj = ppcontents_next_op(context, stream, &size, &op))
    -          ++operators;
    -        fprintf(fh, "%%%% OPERATORS count %lu\n", (unsigned long)operators);
    -        ppstream_done(stream);
    -        //obj = ppcontents_parse(context, stream, &size);
    -        //fprintf(fh, "%%%% items count %lu\n", (unsigned long)size);
    -        fprintf(fh, "\n");
    -      }
    -      ppcontext_done(context);
    -    }
    -    fclose(fh);
    -    ppdoc_free(pdf);
    -  }
    -  ppcontext_free(context);
    -  ppstream_free_buffers();
    -  return 0;
    -}
    +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 < 2)
    +    return usage(argv[0]);
    +  ppstream_init_buffers();
    +  pplog_callback(log_callback, stderr);
    +  context = ppcontext_new();
    +  for (a = 1; a < argc; ++a)
    +  {
    +    /* load */
    +    filepath = argv[a];
    +    printf("loading %s... ", filepath);
    +    pdf = ppdoc_load(filepath);
    +    if (pdf == NULL)
    +    {
    +      printf("failed\n");
    +      continue;
    +    }
    +    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:
    +        printf("invalid password\n");
    +        ppdoc_free(pdf);
    +        continue;
    +      case PPCRYPT_FAIL:
    +        printf("invalid encryption\n");
    +        ppdoc_free(pdf);
    +        continue;
    +    }
    +
    +    /* process */
    +    sprintf(outname, "%s.out", filepath);
    +    fh = fopen(outname, "wb");
    +    if (fh == NULL)
    +    {
    +      printf("can't open %s for writing\n", outname);
    +      continue;
    +    }
    +    for (pageref = ppdoc_first_page(pdf), pageno = 1;
    +         pageref != NULL;
    +         pageref = ppdoc_next_page(pdf), ++pageno)
    +    {
    +      pagedict = pageref->object.dict;
    +      /* decompress contents data */
    +      fprintf(fh, "%%%% PAGE %d\n", pageno);
    +      box_info(pagedict, fh);
    +      for (stream = ppcontents_first(pagedict);
    +           stream != NULL;
    +           stream = ppcontents_next(pagedict, stream))
    +      {
    +        for (data = ppstream_first(stream, &size, 1);
    +             data != NULL;
    +             data = ppstream_next(stream, &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, &size, &op);
    +             obj != NULL;
    +             obj = ppcontents_next_op(context, stream, &size, &op))
    +          ++operators;
    +        fprintf(fh, "%%%% OPERATORS count %lu\n", (unsigned long)operators);
    +        ppstream_done(stream);
    +        //obj = ppcontents_parse(context, stream, &size);
    +        //fprintf(fh, "%%%% items count %lu\n", (unsigned long)size);
    +        fprintf(fh, "\n");
    +      }
    +      ppcontext_done(context);
    +    }
    +    fclose(fh);
    +    ppdoc_free(pdf);
    +  }
    +  ppcontext_free(context);
    +  ppstream_free_buffers();
    +  return 0;
    +}
     
    @@ -492,7 +524,7 @@

    ppapi.h#include "ppconf.h" -#define pplib_version "v2.05 less toxic i hope" +#define pplib_version "v2.1" #define pplib_author "p.jackowski@gust.org.pl" /* types */ @@ -962,12 +994,11 @@

    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..)

    +
    +

    v2.10

    +

    Rework on encryption; algorithms /V5 /R6. +Passwords passed to ppdoc_crypt_pass() should be UTF-8 (backward incompatible).

    -
    -

    TODO

    -
      -
    • external streams (egzotic)
    • -
    @@ -990,7 +1021,7 @@

    Navigation

    \ No newline at end of file diff --git a/libs/pplib/pplib-src/doc/_build/html/pplib.html b/libs/pplib/pplib-src/doc/_build/html/pplib.html index 3066c7ab6c..89c85e95f3 100644 --- a/libs/pplib/pplib-src/doc/_build/html/pplib.html +++ b/libs/pplib/pplib-src/doc/_build/html/pplib.html @@ -143,9 +143,9 @@

    pplib
  • v2.03
  • v2.04
  • v2.05
  • +
  • v2.10
  • -
  • TODO
  • @@ -170,7 +170,7 @@

    Navigation

    \ No newline at end of file diff --git a/libs/pplib/pplib-src/doc/_build/html/ppnew.html b/libs/pplib/pplib-src/doc/_build/html/ppnew.html index 734d81da1f..e579cecbe9 100644 --- a/libs/pplib/pplib-src/doc/_build/html/ppnew.html +++ b/libs/pplib/pplib-src/doc/_build/html/ppnew.html @@ -203,7 +203,7 @@

    Navigation

    \ No newline at end of file diff --git a/libs/pplib/pplib-src/doc/_build/html/search.html b/libs/pplib/pplib-src/doc/_build/html/search.html index 1f1c6ce65f..f7c4aeca84 100644 --- a/libs/pplib/pplib-src/doc/_build/html/search.html +++ b/libs/pplib/pplib-src/doc/_build/html/search.html @@ -91,7 +91,7 @@

    Navigation

    \ No newline at end of file diff --git a/libs/pplib/pplib-src/doc/_build/html/searchindex.js b/libs/pplib/pplib-src/doc/_build/html/searchindex.js index b59ee11455..dfbe86ff43 100644 --- a/libs/pplib/pplib-src/doc/_build/html/searchindex.js +++ b/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:["pplib 1.x","pplib 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:["pplib 1.x","pplib 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/libs/pplib/pplib-src/doc/make.bat b/libs/pplib/pplib-src/doc/make.bat index b1e0e54b1c..45c4b0ea94 100644 --- a/libs/pplib/pplib-src/doc/make.bat +++ b/libs/pplib/pplib-src/doc/make.bat @@ -1,5 +1,7 @@ @ECHO OFF +::set PATH=Q:\\Scripts;%PATH% + pushd %~dp0 REM Command file for Sphinx documentation diff --git a/libs/pplib/pplib-src/doc/ppapi-2.x.rst b/libs/pplib/pplib-src/doc/ppapi-2.x.rst index 250cd8fcd3..c6779145a5 100644 --- a/libs/pplib/pplib-src/doc/ppapi-2.x.rst +++ b/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/libs/pplib/pplib-src/doc/ppcode.rst b/libs/pplib/pplib-src/doc/ppcode.rst index ebe92465d8..e9f6dc7adb 100644 --- a/libs/pplib/pplib-src/doc/ppcode.rst +++ b/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/libs/pplib/pplib-src/src/Makefile.vc b/libs/pplib/pplib-src/src/Makefile.vc index 481d9b20ab..ac0f9d1c6f 100644 --- a/libs/pplib/pplib-src/src/Makefile.vc +++ b/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/libs/pplib/pplib-src/src/ppapi.h b/libs/pplib/pplib-src/src/ppapi.h index 94956f8cb5..56137f8f21 100644 --- a/libs/pplib/pplib-src/src/ppapi.h +++ b/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/libs/pplib/pplib-src/src/ppcrypt.c b/libs/pplib/pplib-src/src/ppcrypt.c index 266bacc29b..832e8c327c 100644 --- a/libs/pplib/pplib-src/src/ppcrypt.c +++ b/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/libs/pplib/pplib-src/src/ppcrypt.h b/libs/pplib/pplib-src/src/ppcrypt.h index 98864f860c..a7131adbb3 100644 --- a/libs/pplib/pplib-src/src/ppcrypt.h +++ b/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/libs/pplib/pplib-src/src/pptest2.c b/libs/pplib/pplib-src/src/pptest2.c index 766110da4c..5dff63afda 100644 --- a/libs/pplib/pplib-src/src/pptest2.c +++ b/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)