// Load into a flat array instead of tree pdf_err pdf_page_tree_load(pdf_doc *d, pdf_obj *o) { int i; pdf_obj *a, *kids = o; if (o->t == eRef) { a = pdf_dict_get(o, "Type"); if (!a) return pdf_ok; if (obj_is_name(a) && a->value.k) { if (strcmp(a->value.k, "Pages") == 0) { kids = pdf_dict_get(o, "Kids"); if (!kids || ((kids->t != eArray) && (kids->t != eRef))) return pdf_ok; } else if (strcmp(a->value.k, "Page") == 0) { pdf_page_load(d, o, &d->pages[d->pageidx]); d->pageidx += 1; return pdf_ok; } else { return pdf_ok; } } else { return pdf_ok; } } if (kids->t == eDict || kids->t == eRef) { pdf_page_load(d, kids, &d->pages[d->pageidx]); d->pageidx += 1; } else if (kids->t == eArray) { for (i = 0; i < kids->value.a.len; i++) { pdf_obj a; a = kids->value.a.items[i]; if (a.t == eRef) { pdf_page_tree_load(d, &a); } } } return pdf_ok; }
// Load crypt_filter pdf_err pdf_cf_load(pdf_encrypt* e, pdf_obj *o, char *name, pdfcrypto_priv **cf) { pdf_obj *a; pdfcrypto_algorithm algo; authevent event; int len; *cf = 0; if (!o) return pdf_ok; if (!obj_is_name(o) && o->t != eDict) return pdf_ok; if (obj_is_name(o) && strcmp(o->value.k, "Identity") == 0) return pdf_ok; if (obj_is_name(o)) return pdf_ok; a = pdf_dict_get(o, name); if (!a) return pdf_ok; o = a; a = pdf_dict_get(o, "CFM"); algo = eRC4; if (a && obj_is_name(a)) { if (strcmp(a->value.k, "V2") == 0) { algo = eRC4; } else if (strcmp(a->value.k, "None") == 0) { algo = eNotBeUsed; } else if (strcmp(a->value.k, "AESV2") == 0) { algo = eAESV2; } else if (strcmp(a->value.k, "AESV3") == 0) { algo = eAESV3; } else { algo = eUnpublished; } } a = pdf_dict_get(o, "AuthEvent"); if (a && obj_is_name(a)) { if (strcmp(a->value.k, "EFOpen") == 0) { event = eEFOpen; } else if (strcmp(a->value.k, "DocOpen") == 0) { event = eDocOpen; } } len = e->length; a = pdf_dict_get(o, "Length"); if (a && a->t == eInt) { len = a->value.i*8; } *cf = pdfcrypto_new(algo, event, len); if (!*cf) return pdf_mem_err; return pdf_ok; }
pdf_err pdf_istream_filtered_load(pdf_obj* o, void *crypto, int numobj, int numgen, pdf_stream **stm) { pdf_err e = pdf_ok; pdf_filter *last = NULL, *raw = NULL, *crypt = NULL; pdf_stream *s = 0; sub_stream *ss; pdf_obj *x, *xx; int m, mm; decode_params *dp = 0; *stm = 0; if (o && o->t == eRef) { numobj = o->value.r.num; numgen = o->value.r.gen; } else if (o->t != eDict && o->t != eString) { return pdf_not_ok; } pdf_obj_resolve(o); if (!o) { return pdf_not_ok; } // fill stream info if (o->t == eDict) { int length; pdf_obj *len_obj = pdf_dict_get(o, "Length"); pdf_obj *_decode_params = 0; if (!len_obj) { fprintf(stderr, "%s\n", "Invalid stream."); return pdf_not_ok; } length = pdf_to_int(len_obj); s = pdf_malloc(sizeof(pdf_stream)); if (!s) goto fail; memset(s, 0, sizeof(pdf_stream)); s->length = length; if (length == 0) { // zero lenght stream, just return return pdf_stream_zero_length; } // make raw filter /// internal struct. raw stream object ss = o->value.d.dict->stream; if (!ss) goto fail; ss->len = s->length; _decode_params = pdf_dict_get(o, "DecodeParms"); if (_decode_params) { dp = pdf_decode_params_load(_decode_params); } } else if (o->t == eString) { s = pdf_malloc(sizeof(pdf_stream)); if (!s) goto fail; memset(s, 0, sizeof(pdf_stream)); s->length = o->value.s.len; // make string raw filter ss = string_stream_new(o->value.s.buf, 0, o->value.s.len, 0, 0); } else goto fail; raw = pdf_rawfilter_new(ss); // chain crypto filter if (crypto) { if (which_algo(crypto) == eAESV2) { // need initial_vector unsigned char iv[16]; int n; n = (raw->read)(raw, iv, 16); crypt = pdf_cryptofilter_new(crypto, numobj, numgen, iv); } else { crypt = pdf_cryptofilter_new(crypto, numobj, numgen, NULL); } if (!crypt) goto fail; crypt->next = raw; } if (o->t == eString) { last = (crypt)?crypt:raw; goto done; } // chain the rest x = pdf_dict_get(o, "Filter"); last = (crypt)?crypt:raw; if (!x) { goto done; } else { if (x->t == eArray) { mm = x->value.a.len; xx = x->value.a.items; } else if (obj_is_name(x)) { mm = 1; xx = x; } } for (m = 0; m < mm; m++, xx++) { pdf_filterkind t = Raw; pdf_filter *f; if (!obj_is_name(xx)) { break; } t = pdf_filter_find(xx->value.k); if (t == Limit) { fprintf(stderr, "Unkown filter type: %s\n", xx->value.k); continue; } // make the filter switch (t) { case FlateDecode: case LZWDecode: case ASCII85Decode: case ASCIIHexDecode: f = pdf_filter_new(t, last); if (!f) { if (s) pdf_free(s); if (crypt) PDF_FILTER_CLOSE(crypt, 0); // do not free in_mem stream return pdf_io_err; } /* chain decoding params filter */ if (dp && dp->predictor > 1 && (t == FlateDecode || t == LZWDecode)) { f = pdf_filter_predictor_new(dp, f); } // make the header of chain if (!last) { last = f; s->ffilter = f; } else { #if 0 f->next = last; #endif last = f; } break; default: fprintf(stderr, "filter type: %s is not implemented\n", xx->value.k); e = pdf_not_ok; break; } } if (dp) pdf_free(dp); done: s->ffilter = last; s->close = pdf_istream_filtered_close; s->write = pdf_istream_filtered_write; s->read = pdf_istream_filtered_read; s->getc = pdf_istream_filtered_getc; s->tell = pdf_istream_filtered_tell; s->flush = pdf_stream_base_flush; s->seekp = pdf_stream_base_seekp; s->seekg = pdf_stream_base_seekg; *stm = s; return e; fail: if (s) pdf_free(s); if (raw) raw->close(raw, 1); if (dp) pdf_free(dp); return pdf_not_ok; }