pdf_annots* pdf_annots_load(pdf_obj* o) { pdf_annots *a=NULL, *first=NULL, *last = NULL; int i; pdf_obj *x, *t; o = pdf_array_get(o); if (!o) return NULL; for (i = 0; i < pdf_to_arraylen(o); i++) { t = pdf_get_array_item(o, i); pdf_obj_resolve(t); if (!t || t->t != eDict) continue; a = pdf_malloc(sizeof(pdf_annots)); if (!a) return NULL; memset(a, 0, sizeof(pdf_annots)); // default border a->border[0] = 0, a->border[1] = 0, a->border[2] = 1; // load annotation node a->subtype = pdf_annots_type(pdf_dict_get(t, "Subtype")); a->rect = pdf_rect_get(pdf_dict_get(t, "Rect")); if ((x = pdf_dict_get(t, "Border"))) { a->border[0] = pdf_to_float(pdf_get_array_item(x, 0)); a->border[1] = pdf_to_float(pdf_get_array_item(x, 1)); a->border[2] = pdf_to_float(pdf_get_array_item(x, 2)); if (pdf_to_arraylen(x) > 3) { pdf_obj *y = pdf_get_array_item(x, 3); a->border[3] = pdf_to_float(pdf_get_array_item(y, 0)); a->border[4] = pdf_to_float(pdf_get_array_item(y, 1)); } } // make linked list if (last) last->next = a; if (i == 0) { first = a; } last = a; } return first; }
pdf_err pdf_encrypt_load(pdf_obj *o, pdf_encrypt **encrypt) { pdf_obj *a; pdf_encrypt *e; if (!o) return pdf_ok; pdf_obj_resolve(o); if (!o) return pdf_ok; *encrypt = pdf_malloc(sizeof(pdf_encrypt)); if (!*encrypt) return pdf_mem_err; memset(*encrypt, 0, sizeof(pdf_encrypt)); e = *encrypt; e->v = 0; a = pdf_dict_get(o, "Filter"); if (a) { pdf_obj_resolve(a); (*encrypt)->filter = pdf_malloc(strlen(a->value.k)+1); memcpy((*encrypt)->filter, a->value.k, strlen(a->value.k)); (*encrypt)->filter[strlen(a->value.k)] = 0; } a = pdf_dict_get(o, "SubFilter"); if (a) { pdf_obj_resolve(a); (*encrypt)->subfilter = pdf_malloc(strlen(a->value.k)+1); memcpy((*encrypt)->subfilter, a->value.k, strlen(a->value.k)); (*encrypt)->subfilter[strlen(a->value.k)] = 0; } a = pdf_dict_get(o, "V"); if (a) { (*encrypt)->v = pdf_to_int(a); } e->length = 40; a = pdf_dict_get(o, "Length"); if (a) { (*encrypt)->length = pdf_to_int(a); } if (e->v == 4) { pdf_obj *cf = pdf_dict_get(o, "CF"); if (cf) { a = pdf_dict_get(o, "StmF"); if (a) { pdf_obj_resolve(a); pdf_cf_load(e, cf, a->value.k, &e->stmf); } a = pdf_dict_get(o, "StrF"); if (a) { pdf_obj_resolve(a); pdf_cf_load(e, cf, a->value.k, &e->strf); } a = pdf_dict_get(o, "EFF"); if (a) { pdf_obj_resolve(a); pdf_cf_load(e, cf, a->value.k, &e->eff); } } } // standard encryption dictionary (items) a = pdf_dict_get(o, "R"); if (a) { (*encrypt)->r = pdf_to_int(a); } a = pdf_dict_get(o, "O"); // owner password if (a) { // should verify length to 32 bytes pdf_obj_resolve(a); memcpy((*encrypt)->o, a->value.s.buf, a->value.s.len); } a = pdf_dict_get(o, "U"); // user password if (a) { // should verify length to 32 bytes pdf_obj_resolve(a); memcpy((*encrypt)->u, a->value.s.buf, a->value.s.len); } a = pdf_dict_get(o, "P"); // permission flags if (a) { (*encrypt)->p = pdf_to_int(a); } a = pdf_dict_get(o, "EncryptMetadata"); if (a) { pdf_obj_resolve(a); (*encrypt)->encrypt_metadata = a->value.b; } 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; }