Examples

Example 1


#include <stdio.h>
#include "ppapi.h"
#include "util/utiliof.h"

static const char * sizenum (size_t s)
{
  static char buffer[32];
  if (s < 1000)
    sprintf(buffer, "%uB", (unsigned)s);
  else if (s < 1000000)
    sprintf(buffer, "%.2fkB", (double)(s) / 1000);
  else
    sprintf(buffer, "%.2fMB", (double)(s) / 1000000);
  return buffer;
}

static const char * crypt_info (ppdoc *pdf)
{
  switch (ppdoc_crypt_status(pdf))
  {
    case PPCRYPT_NONE:
      return "none";
    case PPCRYPT_DONE:
      return "empty password";
    case PPCRYPT_PASS:
      return "nonempty password";
    default:
      break;
  }
  return "this shouldn't happen";
}

static void print_info (ppdoc *pdf)
{
  ppdict *info;
  ppstring *creator, *producer;
  size_t memused, memwaste;

  if ((info = ppdoc_info(pdf)) != NULL)
  {
    if ((creator = ppdict_rget_string(info, "Creator")) != NULL)
      printf("  creator: %s\n", ppstring_decoded_data(creator));
    if ((producer = ppdict_rget_string(info, "Producer")) != NULL)
      printf("  producer: %s\n", ppstring_decoded_data(producer));
  }
  printf("  version: %s\n", ppdoc_version_string(pdf));
  printf("  protection: %s\n", crypt_info(pdf));
  printf("  filesize: %s\n", sizenum(ppdoc_file_size(pdf)));
  printf("  objects: %lu\n", (unsigned long)ppdoc_objects(pdf));
  printf("  pagecount: %lu\n", (unsigned long)ppdoc_page_count(pdf));
  memused = ppdoc_memory(pdf, &memwaste);
  printf("  memused: %s\n", sizenum(memused));
  printf("  memwaste: %s\n", sizenum(memwaste));
}

static int usage (const char *argv0)
{
  printf("pplib " pplib_version ", " pplib_author "\n");
  printf("usage: %s file1.pdf file2.pdf ...\n", argv0);
  return 0;
}

int main (int argc, const char **argv)
{
  const char *filepath;
  int a;
  ppdoc *pdf;
  const void *data;
  size_t size;

  if (argc < 2)
    return usage(argv[0]);
  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");
    print_info(pdf);
    ppdoc_free(pdf);
    /* now loading from memory buffer */
    printf("loading %s from mem buffer... ", filepath);
    data = iof_copy_file_data(filepath, &size);
    if (data != NULL)
    {
      pdf = ppdoc_mem(data, size);
      if (pdf == NULL)
      {
        printf("failed\n");
        continue;
      }
      printf("done.\n");
      //print_info(pdf);
      ppdoc_free(pdf);
    }
  }
  return 0;
}

Example 2


#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 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 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;

  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;
}

Example 3


#include <stdio.h>
//#include "ppapi.h"
#include "pplib.h"
#include "assert.h"

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 void print_result_filter (ppstream *stream, int decode)
{
  ppstream_filter info;
  size_t i;

  ppstream_filter_info(stream, &info, decode);
  printf("  when %s: /Filter [", decode ? "uncompressed" : "compressed");
  for (i = 0; i < info.count; ++i)
    printf(" /%s", ppstream_filter_name[info.filters[i]]);
  printf(" ]");
  if (info.params != NULL)
  {
    printf(" /DecodeParms [");
    for (i = 0; i < info.count; ++i)
      printf(" %s", info.params[i] != NULL ? "<<...>>" : "null");
    printf(" ]");
  }
  printf("\n");
}

static void print_stream_info (ppref *ref, ppstream *stream)
{
  size_t length;
  printf("object %lu %lu R\n", (unsigned long)ref->number, (unsigned long)ref->version);
  if (stream->flags & PPSTREAM_FILTER)
    printf("  filtered ");
  else
    printf("  plain ");
  if (stream->flags & PPSTREAM_IMAGE)
    printf("image ");
  else
    printf("stream ");
  if (stream->flags & PPSTREAM_ENCRYPTED)
    printf("encrypted ");
  if (stream->flags & PPSTREAM_NOT_SUPPORTED)
    printf("invalid ");
  if (!ppdict_rget_uint(stream->dict, "Length", &length))
    length = 0;
  assert(stream->length == length);
  printf("length %lu (/Length %lu)\n", (unsigned long)stream->length, (unsigned long)length);
  print_result_filter(stream, 0);
  print_result_filter(stream, 1);
}

static void check_stream_chunks (ppstream *stream)
{
  size_t sum, size;
  uint8_t *data;
  const int decode[2] = {0, 1};
  int d;

  for (d = 0; d < 2; ++d)
  {
    for (sum = 0, data = ppstream_first(stream, &size, decode[d]); data != NULL; data = ppstream_next(stream, &size))
      sum += size;
    ppstream_done(stream);
    ppstream_all(stream, &size, decode[d]);
    ppstream_done(stream);
    assert(sum == size);
    printf("  %s chunks size [%lu]\n", (decode[d] ? "decoded" : "raw"), (unsigned long)size);
  }
}

#define USE_BUFFERS_POOL 1

int main (int argc, const char **argv)
{
  const char *filepath;
  int a;
  ppdoc *pdf;
  ppxref *xref;
  ppxsec *xsec;
  size_t xi;
  ppuint refnum;
  ppref *ref;

  if (argc < 2)
    return usage(argv[0]);
  if (USE_BUFFERS_POOL)
    ppstream_init_buffers();
  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");
    for (xref = ppdoc_xref(pdf); xref != NULL; xref = ppxref_prev(xref))
    {
      for (xi = 0, xsec = xref->sects; xi < xref->size; ++xi, ++xsec)
      {
        for (refnum = xsec->first, ref = xsec->refs; refnum <= xsec->last; ++refnum, ++ref)
        {
          if (ref->object.type != PPSTREAM)
            continue;
          print_stream_info(ref, ref->object.stream);
          check_stream_chunks(ref->object.stream);
        }
      }
    }
    ppdoc_free(pdf);
  }
  if (USE_BUFFERS_POOL)
    ppstream_free_buffers();
  return 0;
}

ppapi.h


#ifndef PP_API_H
#define PP_API_H

#include <stdint.h>
#include <stddef.h>
#include <string.h>

#include "ppconf.h"

#define pplib_version "v2.05 less toxic i hope"
#define pplib_author "p.jackowski@gust.org.pl"

/* types */

typedef int64_t ppint;
typedef size_t ppuint; // machine word

typedef char ppbyte;

typedef double ppnum;

typedef struct ppname ppname;
typedef struct ppstring ppstring;

struct ppname {
  ppbyte *data;
  size_t size;
  ppname *alterego;
  int flags;
};

struct ppstring {
  ppbyte *data;
  size_t size;
  ppstring *alterego;
  int flags;
};

typedef struct ppobj ppobj;
typedef struct ppref ppref;

typedef struct {
  ppobj *data;
  size_t size;
} pparray;

typedef struct {
  ppobj *data;
  ppname **keys;
  size_t size;
} ppdict;

typedef enum {
  PPSTREAM_BASE16 = 0,
  PPSTREAM_BASE85,
  PPSTREAM_RUNLENGTH,
  PPSTREAM_FLATE,
  PPSTREAM_LZW,
  PPSTREAM_CCITT,
  PPSTREAM_DCT,
  PPSTREAM_JBIG2,
  PPSTREAM_JPX,
  PPSTREAM_CRYPT
} ppstreamtp;

typedef struct {
  ppstreamtp *filters;
  ppdict **params;
  size_t count;
} ppstream_filter;

typedef struct {
  ppdict *dict;
  void *input, *I;
  size_t offset;
  size_t length;
  ppstream_filter filter;
  ppobj *filespec;
  ppstring *cryptkey;
  int flags;
} ppstream;

PPDEF extern const char * ppstream_filter_name[];
PPAPI int ppstream_filter_type (ppname *filtername, ppstreamtp *filtertype);
PPAPI void ppstream_filter_info (ppstream *stream, ppstream_filter *info, int decode);

#define PPSTREAM_FILTER (1<<0)
#define PPSTREAM_IMAGE (1<<1)
#define PPSTREAM_ENCRYPTED_AES (1<<2)
#define PPSTREAM_ENCRYPTED_RC4 (1<<3)
#define PPSTREAM_ENCRYPTED (PPSTREAM_ENCRYPTED_AES|PPSTREAM_ENCRYPTED_RC4)
#define PPSTREAM_ENCRYPTED_OWN (1<<4)
#define PPSTREAM_NOT_SUPPORTED (1<<6)

#define ppstream_compressed(stream) ((stream)->flags & (PPSTREAM_FILTER|PPSTREAM_IMAGE))
#define ppstream_filtered(stream) ((stream)->flags & PPSTREAM_FILTER)
#define ppstream_image(stream) ((stream)->flags & PPSTREAM_IMAGE)
#define ppstream_encrypted(stream) ((stream)->flags & PPSTREAM_ENCRYPTED)

typedef enum {
  PPNONE = 0,
  PPNULL,
  PPBOOL,
  PPINT,
  PPNUM,
  PPNAME,
  PPSTRING,
  PPARRAY,
  PPDICT,
  PPSTREAM,
  PPREF
} ppobjtp;

PPDEF extern const char * ppobj_kind[];

struct ppobj {
  union {
    ppint integer;
    ppnum number;
    ppname *name;
    ppstring *string;
    pparray *array;
    ppdict *dict;
    ppstream *stream;
    ppref *ref;
    void *any;
  };
  ppobjtp type;
};

typedef struct ppxref ppxref;

struct ppref {
  ppobj object;
  ppuint number, version;
  size_t offset;
  size_t length;
  ppxref *xref;
};

typedef struct ppdoc ppdoc;

/* object */

#define ppobj_get_null(o) ((o)->type == PPNULL ? 1 : 0)
#define ppobj_get_bool(o, v) ((o)->type == PPBOOL ? ((v = ((o)->integer != 0)), 1) : 0)
#define ppobj_get_int(o, v) ((o)->type == PPINT ? ((v = (o)->integer), 1) : 0)
#define ppobj_get_uint(o, v) ((o)->type == PPINT && (o)->integer >= 0 ? ((v = (ppuint)((o)->integer)), 1) : 0)
#define ppobj_get_num(o, v) ((o)->type == PPNUM ? ((v = (o)->number), 1) : (((o)->type == PPINT ? ((v = (ppnum)((o)->integer)), 1) : 0)))
#define ppobj_get_name(o) ((o)->type == PPNAME ? (o)->name : NULL)
#define ppobj_get_string(o) ((o)->type == PPSTRING ? (o)->string : NULL)
#define ppobj_get_array(o) ((o)->type == PPARRAY ? (o)->array : NULL)
#define ppobj_get_dict(o) ((o)->type == PPDICT ? (o)->dict : NULL)
#define ppobj_get_stream(o) ((o)->type == PPSTREAM ? (o)->stream : NULL)
#define ppobj_get_ref(o) ((o)->type == PPREF ? (o)->ref : NULL)

#define ppobj_rget_obj(o) ((o)->type == PPREF ? ppref_obj((o)->ref) : o)
#define ppobj_rget_null(o) ((o)->type == PPNULL ? 1 : ((o)->type == PPREF ? ppobj_get_null(ppref_obj((o)->ref)) : 0))
#define ppobj_rget_bool(o, v) ((o)->type == PPBOOL ? ((v = ((o)->integer != 0)), 1) : ((o)->type == PPREF ? ppobj_get_bool(ppref_obj((o)->ref), v) : 0))
#define ppobj_rget_int(o, v) ((o)->type == PPINT ? ((v = (o)->integer), 1) : ((o)->type == PPREF ? ppobj_get_int(ppref_obj((o)->ref), v) : 0))
#define ppobj_rget_uint(o, v) ((o)->type == PPINT && (o)->integer >= 0 ? ((v = (ppuint)((o)->integer)), 1) : ((o)->type == PPREF ? ppobj_get_uint(ppref_obj((o)->ref), v) : 0))
#define ppobj_rget_num(o, v) ((o)->type == PPNUM ? ((v = (o)->number), 1) : (((o)->type == PPINT ? ((v = (ppnum)((o)->integer)), 1) : ((o)->type == PPREF ? ppobj_get_num(ppref_obj((o)->ref), v) : 0))))
#define ppobj_rget_name(o) ((o)->type == PPNAME ? (o)->name : ((o)->type == PPREF ? ppobj_get_name(ppref_obj((o)->ref)) : NULL))
#define ppobj_rget_string(o) ((o)->type == PPSTRING ? (o)->string : ((o)->type == PPREF ? ppobj_get_string(ppref_obj((o)->ref)) : NULL))
#define ppobj_rget_array(o) ((o)->type == PPARRAY ? (o)->array : ((o)->type == PPREF ? ppobj_get_array(ppref_obj((o)->ref)) : NULL))
#define ppobj_rget_dict(o) ((o)->type == PPDICT ? (o)->dict : ((o)->type == PPREF ? ppobj_get_dict(ppref_obj((o)->ref)) : NULL))
#define ppobj_rget_stream(o) ((o)->type == PPSTREAM ? (o)->stream : ((o)->type == PPREF ? ppobj_get_stream(ppref_obj((o)->ref)) : NULL))
#define ppobj_rget_ref(o) ((o)->type == PPREF ? (o)->ref : ((o)->type == PPREF ? ppobj_get_ref(ppref_obj((o)->ref)) : NULL))

#define ppobj_get_bool_value(o) ((o)->type == PPBOOL ? ((o)->integer != 0) : 0)
#define ppobj_get_int_value(o) ((o)->type == PPINT ? (o)->integer : 0)
#define ppobj_get_num_value(o) ((o)->type == PPNUM  ? (o)->number : ((o)->type == PPINT  ? (ppnum)((o)->integer) : 0.0))

/* name */

#define ppname_is(name, s) (memcmp((name)->data, s, sizeof("" s) - 1) == 0)
#define ppname_eq(name, n) (memcmp((name)->data, s, (name)->size) == 0)

#define ppname_size(name) ((name)->size)
#define ppname_exec(name) ((name)->flags & PPNAME_EXEC)
#define ppname_data(name) ((name)->data)

#define PPNAME_ENCODED (1 << 0)
#define PPNAME_DECODED (1 << 1)
#define PPNAME_EXEC (1 << 1)

PPAPI ppname * ppname_decoded (ppname *name);
PPAPI ppname * ppname_encoded (ppname *name);

PPAPI ppbyte * ppname_decoded_data (ppname *name);
PPAPI ppbyte * ppname_encoded_data (ppname *name);

/* string */

#define ppstring_size(string) ((string)->size)
#define ppstring_data(string) ((string)->data)

#define PPSTRING_ENCODED (1 << 0)
#define PPSTRING_DECODED (1 << 1)
//#define PPSTRING_EXEC (1 << 2) // postscript only
#define PPSTRING_PLAIN 0
#define PPSTRING_BASE16 (1 << 3)
#define PPSTRING_BASE85 (1 << 4)
#define PPSTRING_UTF16BE (1 << 5)
#define PPSTRING_UTF16LE (1 << 6)

#define ppstring_type(string) ((string)->flags & (PPSTRING_BASE16|PPSTRING_BASE85))
#define ppstring_hex(string) ((string)->flags & PPSTRING_BASE16)
#define ppstring_utf(string) ((string)->flags & (PPSTRING_UTF16BE|PPSTRING_UTF16LE))

PPAPI ppstring * ppstring_decoded (ppstring *string);
PPAPI ppstring * ppstring_encoded (ppstring *string);

PPAPI ppbyte * ppstring_decoded_data (ppstring *string);
PPAPI ppbyte * ppstring_encoded_data (ppstring *string);

/* array */

#define pparray_size(array) ((array)->size)
#define pparray_at(array, index) ((array)->data + index)

#define pparray_first(array, index, obj) ((index) = 0, (obj) = pparray_at(array,  0))
#define pparray_next(index, obj) (++(index), ++(obj))

#define pparray_get(array, index) (index < (array)->size ? pparray_at(array, index) : NULL)

PPAPI ppobj * pparray_get_obj (pparray *array, size_t index);
PPAPI int pparray_get_bool (pparray *array, size_t index, int *v);
PPAPI int pparray_get_int (pparray *array, size_t index, ppint *v);
PPAPI int pparray_get_uint (pparray *array, size_t index, ppuint *v);
PPAPI int pparray_get_num (pparray *array, size_t index, ppnum *v);
PPAPI ppname * pparray_get_name (pparray *array, size_t index);
PPAPI ppstring * pparray_get_string (pparray *array, size_t index);
PPAPI pparray * pparray_get_array (pparray *array, size_t index);
PPAPI ppdict * pparray_get_dict (pparray *array, size_t index);
//PPAPI ppstream * pparray_get_stream (pparray *array, size_t index);
PPAPI ppref * pparray_get_ref (pparray *array, size_t index);

PPAPI ppobj * pparray_rget_obj (pparray *array, size_t index);
PPAPI int pparray_rget_bool (pparray *array, size_t index, int *v);
PPAPI int pparray_rget_int (pparray *array, size_t index, ppint *v);
PPAPI int pparray_rget_uint (pparray *array, size_t index, ppuint *v);
PPAPI int pparray_rget_num (pparray *array, size_t index, ppnum *v);
PPAPI ppname * pparray_rget_name (pparray *array, size_t index);
PPAPI ppstring * pparray_rget_string (pparray *array, size_t index);
PPAPI pparray * pparray_rget_array (pparray *array, size_t index);
PPAPI ppdict * pparray_rget_dict (pparray *array, size_t index);
PPAPI ppstream * pparray_rget_stream (pparray *array, size_t index);
PPAPI ppref * pparray_rget_ref (pparray *array, size_t index);

/* dict */

#define ppdict_size(dict) ((dict)->size)
#define ppdict_at(dict, index) ((dict)->data + index)
#define ppdict_key(dict, index) ((dict)->keys[index])

PPAPI ppobj * ppdict_get_obj (ppdict *dict, const char *name);
PPAPI int ppdict_get_bool (ppdict *dict, const char *name, int *v);
PPAPI int ppdict_get_int (ppdict *dict, const char *name, ppint *v);
PPAPI int ppdict_get_uint (ppdict *dict, const char *name, ppuint *v);
PPAPI int ppdict_get_num (ppdict *dict, const char *name, ppnum *v);
PPAPI ppname * ppdict_get_name (ppdict *dict, const char *name);
PPAPI ppstring * ppdict_get_string (ppdict *dict, const char *name);
PPAPI pparray * ppdict_get_array (ppdict *dict, const char *name);
PPAPI ppdict * ppdict_get_dict (ppdict *dict, const char *name);
//PPAPI ppstream * ppdict_get_stream (ppdict *dict, const char *name);
PPAPI ppref * ppdict_get_ref (ppdict *dict, const char *name);

PPAPI ppobj * ppdict_rget_obj (ppdict *dict, const char *name);
PPAPI int ppdict_rget_bool (ppdict *dict, const char *name, int *v);
PPAPI int ppdict_rget_int (ppdict *dict, const char *name, ppint *v);
PPAPI int ppdict_rget_uint (ppdict *dict, const char *name, ppuint *v);
PPAPI int ppdict_rget_num (ppdict *dict, const char *name, ppnum *v);
PPAPI ppname * ppdict_rget_name (ppdict *dict, const char *name);
PPAPI ppstring * ppdict_rget_string (ppdict *dict, const char *name);
PPAPI pparray * ppdict_rget_array (ppdict *dict, const char *name);
PPAPI ppdict * ppdict_rget_dict (ppdict *dict, const char *name);
PPAPI ppstream * ppdict_rget_stream (ppdict *dict, const char *name);
PPAPI ppref * ppdict_rget_ref (ppdict *dict, const char *name);

#define ppdict_first(dict, pkey, obj) (pkey = (dict)->keys, obj = (dict)->data)
#define ppdict_next(pkey, obj) (++(pkey), ++(obj))

/* stream */

#define ppstream_dict(stream) ((stream)->dict)

PPAPI uint8_t * ppstream_first (ppstream *stream, size_t *size, int decode);
PPAPI uint8_t * ppstream_next (ppstream *stream, size_t *size);
PPAPI uint8_t * ppstream_all (ppstream *stream, size_t *size, int decode);
PPAPI void ppstream_done (ppstream *stream);

PPAPI void ppstream_init_buffers (void);
PPAPI void ppstream_free_buffers (void);

/* ref */

#define ppref_obj(ref) (&(ref)->object)

/* xref */

PPAPI ppxref * ppdoc_xref (ppdoc *pdf);
PPAPI ppxref * ppxref_prev (ppxref *xref);
PPAPI ppdict * ppxref_trailer (ppxref *xref);
PPAPI ppdict * ppxref_catalog (ppxref *xref);
PPAPI ppdict * ppxref_info (ppxref *xref);
PPAPI ppref * ppxref_pages (ppxref *xref);
PPAPI ppref * ppxref_find (ppxref *xref, ppuint refnumber);

/* doc */

PPAPI ppdoc * ppdoc_load (const char *filename);
PPAPI ppdoc * ppdoc_filehandle (FILE *file, int closefile);
#define ppdoc_file(file) ppdoc_filehandle(file, 1)
PPAPI ppdoc * ppdoc_mem (const void *data, size_t size);
PPAPI void ppdoc_free (ppdoc *pdf);

#define ppdoc_trailer(pdf) ppxref_trailer(ppdoc_xref(pdf))
#define ppdoc_catalog(pdf) ppxref_catalog(ppdoc_xref(pdf))
#define ppdoc_info(pdf) ppxref_info(ppdoc_xref(pdf))
#define ppdoc_pages(pdf) ppxref_pages(ppdoc_xref(pdf))

PPAPI ppuint ppdoc_page_count (ppdoc *pdf);
PPAPI ppref * ppdoc_page (ppdoc *pdf, ppuint index);
PPAPI ppref *  ppdoc_first_page (ppdoc *pdf);
PPAPI ppref * ppdoc_next_page (ppdoc *pdf);

PPAPI ppstream * ppcontents_first (ppdict *dict);
PPAPI ppstream * ppcontents_next (ppdict *dict, ppstream *stream);

/* crypt */

typedef enum {
  PPCRYPT_NONE = 0,
  PPCRYPT_DONE = 1,
  PPCRYPT_FAIL = -1,
  PPCRYPT_PASS = -2
} ppcrypt_status;

PPAPI ppcrypt_status ppdoc_crypt_status (ppdoc *pdf);
PPAPI ppcrypt_status ppdoc_crypt_pass (ppdoc *pdf, const void *userpass, size_t userpasslength, const void *ownerpass, size_t ownerpasslength);

/* permission flags, effect in Acrobat File -> Properties -> Security tab */

PPAPI ppint ppdoc_permissions (ppdoc *pdf);

#define PPDOC_ALLOW_PRINT (1<<2)        // printing
#define PPDOC_ALLOW_MODIFY (1<<3)       // filling form fields, signing, creating template pages
#define PPDOC_ALLOW_COPY (1<<4)         // copying, copying for accessibility
#define PPDOC_ALLOW_ANNOTS (1<<5)       // filling form fields, copying, signing
#define PPDOC_ALLOW_EXTRACT (1<<9)      // contents copying for accessibility
#define PPDOC_ALLOW_ASSEMBLY (1<<10)    // (no effect)
#define PPDOC_ALLOW_PRINT_HIRES (1<<11) // (no effect)

/* context */

typedef struct ppcontext ppcontext;

PPAPI ppcontext * ppcontext_new (void);
PPAPI void ppcontext_done (ppcontext *context);
PPAPI void ppcontext_free (ppcontext *context);

/* contents parser */

PPAPI ppobj * ppcontents_first_op (ppcontext *context, ppstream *stream, size_t *psize, ppname **pname);
PPAPI ppobj * ppcontents_next_op (ppcontext *context, ppstream *stream, size_t *psize, ppname **pname);
PPAPI ppobj * ppcontents_parse (ppcontext *context, ppstream *stream, size_t *psize);

/* boxes and transforms */

typedef struct {
  ppnum lx, ly, rx, ry;
} pprect;

PPAPI pprect * pparray_to_rect (pparray *array, pprect *rect);
PPAPI pprect * ppdict_get_rect (ppdict *dict, const char *name, pprect *rect);
PPAPI pprect * ppdict_get_box (ppdict *dict, const char *name, pprect *rect);

typedef struct {
  ppnum xx, xy, yx, yy, x, y;
} ppmatrix;

PPAPI ppmatrix * pparray_to_matrix (pparray *array, ppmatrix *matrix);
PPAPI ppmatrix * ppdict_get_matrix (ppdict *dict, const char *name, ppmatrix *matrix);

/* logger */

typedef void (*pplogger_callback) (const char *message, void *alien);
PPAPI void pplog_callback (pplogger_callback logger, void *alien);
PPAPI int pplog_prefix (const char *prefix);

/* version */

PPAPI const char * ppdoc_version_string (ppdoc *pdf);
PPAPI int ppdoc_version_number (ppdoc *pdf, int *minor);

/* doc info */

PPAPI size_t ppdoc_file_size (ppdoc *pdf);
PPAPI ppuint ppdoc_objects (ppdoc *pdf);
PPAPI size_t ppdoc_memory (ppdoc *pdf, size_t *waste);

#endif

Changes

v0.97

First release integrated with luatex sources, plus portability changes from Luigi.

v0.98

Changed references resolving in case of incremental updates; tech notes ppxref_find() in ppxref.c.

v0.99

Fixed streams handling; null characters should NOT be gobbled after “stream” keyword

v1.00

Fixed streams handling (Luigi); object streams updated before other streams Revised streams handling, ppstream API extended

v1.01

Fixed names handling (thanks Hans); digits after ‘#’ weren’t skipped

v1.02

Fixed page finder (thanks Luigi)

v1.03

Fixed TIFF predictor (thanks folks)

v1.04

Fixed TIFF predictor for ARM

v1.05

Attempt to fix parsing inline images crap

v2.00

Deep rework on allocators. Deep rework on strings and names.

v2.01

Fixed invalid stream buffer handling; iof_discard() no longer reclaims the source (filter->next) filter. Sanity alignment adjustments in iof_heap.

v2.02

Fixed incorrect encoding of strings alterego with octal escaping, thanks Luigi. On Hans request added ppdoc_filehandle() function and ppdoc_file() macro for loading ppdoc from FILE *.

v2.03

Fixed alloc/free of ppdoc heap; ppdoc is now mallocated, no longer taken from its own heap. Again, thanks Luigi. Fixed warnings about dereferencing type-puned pointers, and some others.

v2.04

Byte lookups for names/strings loaders are now int8_t, as char might be signed. ppdoc_first_page() / ppdoc_next_page() iterator now handles a case when /Kids array is empty. Fixed generating keys for encrypted streams; ppstring_internal() returns the string of the proper size. More stream tests in pptest3.c. Some rework on md5 and sha2.

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)