fz_error pdf_cacheobject(pdf_xref *xref, int num, int gen) { fz_error error; pdf_xrefentry *x; int rnum, rgen; if (num < 0 || num >= xref->len) return fz_throw("object out of range (%d %d R); xref size %d", num, gen, xref->len); x = &xref->table[num]; if (x->obj) return fz_okay; if (x->type == 'f') { x->obj = fz_newnull(); return fz_okay; } else if (x->type == 'n') { fz_seek(xref->file, x->ofs, 0); error = pdf_parseindobj(&x->obj, xref, xref->file, xref->scratch, sizeof xref->scratch, &rnum, &rgen, &x->stmofs); if (error) return fz_rethrow(error, "cannot parse object (%d %d R)", num, gen); if (rnum != num) return fz_throw("found object (%d %d R) instead of (%d %d R)", rnum, rgen, num, gen); if (xref->crypt) pdf_cryptobj(xref->crypt, x->obj, num, gen); } else if (x->type == 'o') { if (!x->obj) { error = pdf_loadobjstm(xref, x->ofs, 0, xref->scratch, sizeof xref->scratch); if (error) return fz_rethrow(error, "cannot load object stream containing object (%d %d R)", num, gen); if (!x->obj) return fz_throw("object (%d %d R) was not found in its object stream", num, gen); } } else { return fz_throw("assert: corrupt xref struct"); } return fz_okay; }
static fz_error pdf_readnewtrailer(pdf_xref *xref, char *buf, int cap) { fz_error error; pdf_logxref("load new xref format trailer\n"); error = pdf_parseindobj(&xref->trailer, xref, xref->file, buf, cap, nil, nil, nil); if (error) return fz_rethrow(error, "cannot parse trailer (compressed)"); return fz_okay; }
static fz_error pdf_readnewxref(fz_obj **trailerp, pdf_xref *xref, char *buf, int cap) { fz_error error; fz_stream *stm; fz_obj *trailer; fz_obj *index; fz_obj *obj; int num, gen, stmofs; int size, w0, w1, w2; int t; int i; pdf_logxref("load new xref format\n"); error = pdf_parseindobj(&trailer, xref, xref->file, buf, cap, &num, &gen, &stmofs); if (error) return fz_rethrow(error, "cannot parse compressed xref stream object"); obj = fz_dictgets(trailer, "Size"); if (!obj) { fz_dropobj(trailer); return fz_throw("xref stream missing Size entry (%d %d R)", num, gen); } size = fz_toint(obj); if (size >= xref->cap) { xref->cap = size + 1; /* for hack to allow broken pdf generators with off-by-one errors */ xref->table = fz_realloc(xref->table, xref->cap * sizeof(pdf_xrefentry)); } if (size > xref->len) { for (i = xref->len; i < xref->cap; i++) { xref->table[i].ofs = 0; xref->table[i].gen = 0; xref->table[i].stmofs = 0; xref->table[i].obj = nil; xref->table[i].type = 0; } xref->len = size; } if (num < 0 || num >= xref->len) { if (num == xref->len && num < xref->cap) { /* allow broken pdf files that have off-by-one errors in the xref */ fz_warn("object id (%d %d R) out of range (0..%d)", num, gen, xref->len - 1); xref->len ++; } else { fz_dropobj(trailer); return fz_throw("object id (%d %d R) out of range (0..%d)", num, gen, xref->len - 1); } } pdf_logxref("\tnum=%d gen=%d size=%d\n", num, gen, size); obj = fz_dictgets(trailer, "W"); if (!obj) { fz_dropobj(trailer); return fz_throw("xref stream missing W entry (%d %d R)", num, gen); } w0 = fz_toint(fz_arrayget(obj, 0)); w1 = fz_toint(fz_arrayget(obj, 1)); w2 = fz_toint(fz_arrayget(obj, 2)); index = fz_dictgets(trailer, "Index"); error = pdf_openstreamat(&stm, xref, num, gen, trailer, stmofs); if (error) { fz_dropobj(trailer); return fz_rethrow(error, "cannot open compressed xref stream (%d %d R)", num, gen); } if (!index) { error = pdf_readnewxrefsection(xref, stm, 0, size, w0, w1, w2); if (error) { fz_close(stm); fz_dropobj(trailer); return fz_rethrow(error, "cannot read xref stream (%d %d R)", num, gen); } } else { for (t = 0; t < fz_arraylen(index); t += 2) { int i0 = fz_toint(fz_arrayget(index, t + 0)); int i1 = fz_toint(fz_arrayget(index, t + 1)); error = pdf_readnewxrefsection(xref, stm, i0, i1, w0, w1, w2); if (error) { fz_close(stm); fz_dropobj(trailer); return fz_rethrow(error, "cannot read xref stream section (%d %d R)", num, gen); } } } fz_close(stm); *trailerp = trailer; return fz_okay; }
static fz_error readnewxref(fz_obj **trailerp, pdf_xref *xref, char *buf, int cap) { fz_error error; fz_stream *stm; fz_obj *trailer; fz_obj *index; fz_obj *obj; int oid, gen, stmofs; int size, w0, w1, w2; int t; pdf_logxref("load new xref format\n"); error = pdf_parseindobj(&trailer, xref, xref->file, buf, cap, &oid, &gen, &stmofs); if (error) return fz_rethrow(error, "cannot parse compressed xref stream object"); if (oid < 0 || oid >= xref->len) { if (oid == xref->len && oid < xref->cap) { /* allow broken pdf files that have off-by-one errors in the xref */ fz_warn("object id (%d %d R) out of range (0..%d)", oid, gen, xref->len - 1); xref->len ++; } else { fz_dropobj(trailer); return fz_throw("object id (%d %d R) out of range (0..%d)", oid, gen, xref->len - 1); } } xref->table[oid].type = 'n'; xref->table[oid].gen = gen; xref->table[oid].obj = fz_keepobj(trailer); xref->table[oid].stmofs = stmofs; xref->table[oid].ofs = 0; obj = fz_dictgets(trailer, "Size"); if (!obj) { fz_dropobj(trailer); return fz_throw("xref stream missing Size entry"); } size = fz_toint(obj); obj = fz_dictgets(trailer, "W"); if (!obj) { fz_dropobj(trailer); return fz_throw("xref stream missing W entry"); } w0 = fz_toint(fz_arrayget(obj, 0)); w1 = fz_toint(fz_arrayget(obj, 1)); w2 = fz_toint(fz_arrayget(obj, 2)); index = fz_dictgets(trailer, "Index"); error = pdf_openstream(&stm, xref, oid, gen); if (error) { fz_dropobj(trailer); return fz_rethrow(error, "cannot open compressed xref stream"); } if (!index) { error = readnewxrefsection(xref, stm, 0, size, w0, w1, w2); if (error) { fz_dropstream(stm); fz_dropobj(trailer); return fz_rethrow(error, "cannot read xref stream"); } } else { for (t = 0; t < fz_arraylen(index); t += 2) { int i0 = fz_toint(fz_arrayget(index, t + 0)); int i1 = fz_toint(fz_arrayget(index, t + 1)); error = readnewxrefsection(xref, stm, i0, i1, w0, w1, w2); if (error) { fz_dropstream(stm); fz_dropobj(trailer); return fz_rethrow(error, "cannot read xref stream section"); } } } fz_dropstream(stm); *trailerp = trailer; return fz_okay; }