summaryrefslogtreecommitdiff
path: root/pdf/pdf_xref.c
diff options
context:
space:
mode:
authorRobin Watts <Robin.Watts@artifex.com>2011-10-04 18:44:19 +0100
committerRobin Watts <Robin.Watts@artifex.com>2011-10-04 18:44:19 +0100
commitd208be26537db558edb70236ae517cea31b7ebab (patch)
tree57da95b97e354a53bd4517a42010e90968f007d9 /pdf/pdf_xref.c
parentba46cad4b09bb957085900a203206c8fa5868cd4 (diff)
downloadmupdf-d208be26537db558edb70236ae517cea31b7ebab.tar.xz
Move to exception handling rather than error passing throughout.
This frees us from passing errors back everywhere, and hence enables us to pass results back as return values. Rather than having to explicitly check for errors everywhere and bubble them, we now allow exception handling to do the work for us; the downside to this is that we no longer emit as much debugging information as we did before (though this could be put back in). For now, the debugging information we have lost has been retained in comments with 'RJW:' at the start. This code needs fuller testing, but is being committed as a work in progress.
Diffstat (limited to 'pdf/pdf_xref.c')
-rw-r--r--pdf/pdf_xref.c685
1 files changed, 321 insertions, 364 deletions
diff --git a/pdf/pdf_xref.c b/pdf/pdf_xref.c
index 37bbc977..cb538ae3 100644
--- a/pdf/pdf_xref.c
+++ b/pdf/pdf_xref.c
@@ -12,7 +12,7 @@ static inline int iswhite(int ch)
* magic version tag and startxref
*/
-static fz_error
+static void
pdf_load_version(pdf_xref *xref)
{
char buf[20];
@@ -20,14 +20,12 @@ pdf_load_version(pdf_xref *xref)
fz_seek(xref->file, 0, 0);
fz_read_line(xref->file, buf, sizeof buf);
if (memcmp(buf, "%PDF-", 5) != 0)
- return fz_error_make("cannot recognize version marker");
+ fz_throw(xref->ctx, "cannot recognize version marker");
xref->version = atoi(buf + 5) * 10 + atoi(buf + 7);
-
- return fz_okay;
}
-static fz_error
+static void
pdf_read_start_xref(pdf_xref *xref)
{
unsigned char buf[1024];
@@ -43,7 +41,7 @@ pdf_read_start_xref(pdf_xref *xref)
n = fz_read(xref->file, buf, sizeof buf);
if (n < 0)
- return fz_error_note(n, "cannot read from file");
+ fz_throw(xref->ctx, "cannot read from file");
for (i = n - 9; i >= 0; i--)
{
@@ -53,21 +51,20 @@ pdf_read_start_xref(pdf_xref *xref)
while (iswhite(buf[i]) && i < n)
i ++;
xref->startxref = atoi((char*)(buf + i));
- return fz_okay;
+ return;
}
}
- return fz_error_make("cannot find startxref");
+ fz_throw(xref->ctx, "cannot find startxref");
}
/*
* trailer dictionary
*/
-static fz_error
+static void
pdf_read_old_trailer(pdf_xref *xref, char *buf, int cap)
{
- fz_error error;
int len;
char *s;
int n;
@@ -77,7 +74,7 @@ pdf_read_old_trailer(pdf_xref *xref, char *buf, int cap)
fz_read_line(xref->file, buf, cap);
if (strncmp(buf, "xref", 4) != 0)
- return fz_error_make("cannot find xref marker");
+ fz_throw(xref->ctx, "cannot find xref marker");
while (1)
{
@@ -89,7 +86,7 @@ pdf_read_old_trailer(pdf_xref *xref, char *buf, int cap)
s = buf;
fz_strsep(&s, " "); /* ignore ofs */
if (!s)
- return fz_error_make("invalid range marker in xref");
+ fz_throw(xref->ctx, "invalid range marker in xref");
len = atoi(fz_strsep(&s, " "));
/* broken pdfs where the section is not on a separate line */
@@ -98,43 +95,45 @@ pdf_read_old_trailer(pdf_xref *xref, char *buf, int cap)
t = fz_tell(xref->file);
if (t < 0)
- return fz_error_make("cannot tell in file");
+ fz_throw(xref->ctx, "cannot tell in file");
fz_seek(xref->file, t + 20 * len, 0);
}
- error = pdf_lex(&tok, xref->file, buf, cap, &n);
- if (error)
- return fz_error_note(error, "cannot parse trailer");
- if (tok != PDF_TOK_TRAILER)
- return fz_error_make("expected trailer marker");
+ fz_try(xref->ctx)
+ {
+ tok = pdf_lex(xref->file, buf, cap, &n);
+ if (tok != PDF_TOK_TRAILER)
+ fz_throw(xref->ctx, "expected trailer marker");
- error = pdf_lex(&tok, xref->file, buf, cap, &n);
- if (error)
- return fz_error_note(error, "cannot parse trailer");
- if (tok != PDF_TOK_OPEN_DICT)
- return fz_error_make("expected trailer dictionary");
+ tok = pdf_lex(xref->file, buf, cap, &n);
+ if (tok != PDF_TOK_OPEN_DICT)
+ fz_throw(xref->ctx, "expected trailer dictionary");
- error = pdf_parse_dict(&xref->trailer, xref, xref->file, buf, cap);
- if (error)
- return fz_error_note(error, "cannot parse trailer");
- return fz_okay;
+ xref->trailer = pdf_parse_dict(xref, xref->file, buf, cap);
+ }
+ fz_catch(xref->ctx)
+ {
+ fz_throw(xref->ctx, "cannot parse trailer");
+ }
}
-static fz_error
+static void
pdf_read_new_trailer(pdf_xref *xref, char *buf, int cap)
{
- fz_error error;
- error = pdf_parse_ind_obj(&xref->trailer, xref, xref->file, buf, cap, NULL, NULL, NULL);
- if (error)
- return fz_error_note(error, "cannot parse trailer (compressed)");
- return fz_okay;
+ fz_try(xref->ctx)
+ {
+ xref->trailer = pdf_parse_ind_obj(xref, xref->file, buf, cap, NULL, NULL, NULL);
+ }
+ fz_catch(xref->ctx)
+ {
+ fz_throw(xref->ctx, "cannot parse trailer (compressed)");
+ }
}
-static fz_error
+static void
pdf_read_trailer(pdf_xref *xref, char *buf, int cap)
{
- fz_error error;
int c;
fz_seek(xref->file, xref->startxref, 0);
@@ -142,25 +141,20 @@ pdf_read_trailer(pdf_xref *xref, char *buf, int cap)
while (iswhite(fz_peek_byte(xref->file)))
fz_read_byte(xref->file);
- c = fz_peek_byte(xref->file);
- if (c == 'x')
+ fz_try(xref->ctx)
{
- error = pdf_read_old_trailer(xref, buf, cap);
- if (error)
- return fz_error_note(error, "cannot read trailer");
- }
- else if (c >= '0' && c <= '9')
- {
- error = pdf_read_new_trailer(xref, buf, cap);
- if (error)
- return fz_error_note(error, "cannot read trailer");
+ c = fz_peek_byte(xref->file);
+ if (c == 'x')
+ pdf_read_old_trailer(xref, buf, cap);
+ else if (c >= '0' && c <= '9')
+ pdf_read_new_trailer(xref, buf, cap);
+ else
+ fz_throw(xref->ctx, "cannot recognize xref format: '%c'", c);
}
- else
+ fz_catch(xref->ctx)
{
- return fz_error_make("cannot recognize xref format: '%c'", c);
+ fz_throw(xref->ctx, "cannot read trailer");
}
-
- return fz_okay;
}
/*
@@ -184,20 +178,20 @@ pdf_resize_xref(pdf_xref *xref, int newlen)
xref->len = newlen;
}
-static fz_error
-pdf_read_old_xref(fz_obj **trailerp, pdf_xref *xref, char *buf, int cap)
+static fz_obj *
+pdf_read_old_xref(pdf_xref *xref, char *buf, int cap)
{
- fz_error error;
int ofs, len;
char *s;
int n;
int tok;
int i;
int c;
+ fz_obj *trailer;
fz_read_line(xref->file, buf, cap);
if (strncmp(buf, "xref", 4) != 0)
- return fz_error_make("cannot find xref marker");
+ fz_throw(xref->ctx, "cannot find xref marker");
while (1)
{
@@ -228,7 +222,7 @@ pdf_read_old_xref(fz_obj **trailerp, pdf_xref *xref, char *buf, int cap)
{
n = fz_read(xref->file, (unsigned char *) buf, 20);
if (n < 0)
- return fz_error_note(n, "cannot read xref table");
+ fz_throw(xref->ctx, "cannot read xref table");
if (!xref->table[i].type)
{
s = buf;
@@ -241,36 +235,37 @@ pdf_read_old_xref(fz_obj **trailerp, pdf_xref *xref, char *buf, int cap)
xref->table[i].gen = atoi(s + 11);
xref->table[i].type = s[17];
if (s[17] != 'f' && s[17] != 'n' && s[17] != 'o')
- return fz_error_make("unexpected xref type: %#x (%d %d R)", s[17], i, xref->table[i].gen);
+ fz_throw(xref->ctx, "unexpected xref type: %#x (%d %d R)", s[17], i, xref->table[i].gen);
}
}
}
- error = pdf_lex(&tok, xref->file, buf, cap, &n);
- if (error)
- return fz_error_note(error, "cannot parse trailer");
- if (tok != PDF_TOK_TRAILER)
- return fz_error_make("expected trailer marker");
+ fz_try(xref->ctx)
+ {
+ tok = pdf_lex(xref->file, buf, cap, &n);
+ if (tok != PDF_TOK_TRAILER)
+ fz_throw(xref->ctx, "expected trailer marker");
- error = pdf_lex(&tok, xref->file, buf, cap, &n);
- if (error)
- return fz_error_note(error, "cannot parse trailer");
- if (tok != PDF_TOK_OPEN_DICT)
- return fz_error_make("expected trailer dictionary");
+ tok = pdf_lex(xref->file, buf, cap, &n);
+ if (tok != PDF_TOK_OPEN_DICT)
+ fz_throw(xref->ctx, "expected trailer dictionary");
- error = pdf_parse_dict(trailerp, xref, xref->file, buf, cap);
- if (error)
- return fz_error_note(error, "cannot parse trailer");
- return fz_okay;
+ trailer = pdf_parse_dict(xref, xref->file, buf, cap);
+ }
+ fz_catch(xref->ctx)
+ {
+ fz_throw(xref->ctx, "cannot parse trailer");
+ }
+ return trailer;
}
-static fz_error
+static void
pdf_read_new_xref_section(pdf_xref *xref, fz_stream *stm, int i0, int i1, int w0, int w1, int w2)
{
int i, n;
if (i0 < 0 || i0 + i1 > xref->len)
- return fz_error_make("xref stream has too many entries");
+ fz_throw(xref->ctx, "xref stream has too many entries");
for (i = i0; i < i0 + i1; i++)
{
@@ -279,7 +274,7 @@ pdf_read_new_xref_section(pdf_xref *xref, fz_stream *stm, int i0, int i1, int w0
int c = 0;
if (fz_is_eof(stm))
- return fz_error_make("truncated xref stream");
+ fz_throw(xref->ctx, "truncated xref stream");
for (n = 0; n < w0; n++)
a = (a << 8) + fz_read_byte(stm);
@@ -296,217 +291,182 @@ pdf_read_new_xref_section(pdf_xref *xref, fz_stream *stm, int i0, int i1, int w0
xref->table[i].gen = w2 ? c : 0;
}
}
-
- return fz_okay;
}
-static fz_error
-pdf_read_new_xref(fz_obj **trailerp, pdf_xref *xref, char *buf, int cap)
+static fz_obj *
+pdf_read_new_xref(pdf_xref *xref, char *buf, int cap)
{
- fz_error error;
fz_stream *stm;
- fz_obj *trailer;
- fz_obj *index;
- fz_obj *obj;
+ fz_obj * volatile trailer = NULL;
+ fz_obj *index = NULL;
+ fz_obj *obj = NULL;
int num, gen, stm_ofs;
int size, w0, w1, w2;
int t;
+ fz_context *ctx = xref->ctx;
- error = pdf_parse_ind_obj(&trailer, xref, xref->file, buf, cap, &num, &gen, &stm_ofs);
- if (error)
- return fz_error_note(error, "cannot parse compressed xref stream object");
-
- obj = fz_dict_gets(trailer, "Size");
- if (!obj)
+ fz_try(ctx)
{
- fz_drop_obj(trailer);
- return fz_error_make("xref stream missing Size entry (%d %d R)", num, gen);
+ trailer = pdf_parse_ind_obj(xref, xref->file, buf, cap, &num, &gen, &stm_ofs);
}
- size = fz_to_int(obj);
-
- if (size > xref->len)
+ fz_catch(ctx)
{
- pdf_resize_xref(xref, size);
+ fz_throw(ctx, "cannot parse compressed xref stream object");
}
- if (num < 0 || num >= xref->len)
+ fz_try(ctx)
{
- fz_drop_obj(trailer);
- return fz_error_make("object id (%d %d R) out of range (0..%d)", num, gen, xref->len - 1);
- }
+ obj = fz_dict_gets(trailer, "Size");
+ if (!obj)
+ fz_throw(ctx, "xref stream missing Size entry (%d %d R)", num, gen);
- obj = fz_dict_gets(trailer, "W");
- if (!obj) {
- fz_drop_obj(trailer);
- return fz_error_make("xref stream missing W entry (%d %d R)", num, gen);
- }
- w0 = fz_to_int(fz_array_get(obj, 0));
- w1 = fz_to_int(fz_array_get(obj, 1));
- w2 = fz_to_int(fz_array_get(obj, 2));
+ size = fz_to_int(obj);
+ if (size > xref->len)
+ pdf_resize_xref(xref, size);
- index = fz_dict_gets(trailer, "Index");
+ if (num < 0 || num >= xref->len)
+ fz_throw(ctx, "object id (%d %d R) out of range (0..%d)", num, gen, xref->len - 1);
- error = pdf_open_stream_at(&stm, xref, num, gen, trailer, stm_ofs);
- if (error)
- {
- fz_drop_obj(trailer);
- return fz_error_note(error, "cannot open compressed xref stream (%d %d R)", num, gen);
- }
+ obj = fz_dict_gets(trailer, "W");
+ if (!obj)
+ fz_throw(ctx, "xref stream missing W entry (%d %d R)", num, gen);
+ w0 = fz_to_int(fz_array_get(obj, 0));
+ w1 = fz_to_int(fz_array_get(obj, 1));
+ w2 = fz_to_int(fz_array_get(obj, 2));
- if (!index)
- {
- error = pdf_read_new_xref_section(xref, stm, 0, size, w0, w1, w2);
- if (error)
+ index = fz_dict_gets(trailer, "Index");
+
+ stm = pdf_open_stream_at(xref, num, gen, trailer, stm_ofs);
+ /* RJW: Ensure pdf_open_stream does fz_throw(ctx, "cannot open compressed xref stream (%d %d R)", num, gen); */
+
+ if (!index)
{
- fz_close(stm);
- fz_drop_obj(trailer);
- return fz_error_note(error, "cannot read xref stream (%d %d R)", num, gen);
+ pdf_read_new_xref_section(xref, stm, 0, size, w0, w1, w2);
+ /* RJW: Ensure above does fz_throw(ctx, "cannot read xref stream (%d %d R)", num, gen); */
}
- }
- else
- {
- int n = fz_array_len(index);
- for (t = 0; t < n; t += 2)
+ else
{
- int i0 = fz_to_int(fz_array_get(index, t + 0));
- int i1 = fz_to_int(fz_array_get(index, t + 1));
- error = pdf_read_new_xref_section(xref, stm, i0, i1, w0, w1, w2);
- if (error)
+ int n = fz_array_len(index);
+ for (t = 0; t < n; t += 2)
{
- fz_close(stm);
- fz_drop_obj(trailer);
- return fz_error_note(error, "cannot read xref stream section (%d %d R)", num, gen);
+ int i0 = fz_to_int(fz_array_get(index, t + 0));
+ int i1 = fz_to_int(fz_array_get(index, t + 1));
+ pdf_read_new_xref_section(xref, stm, i0, i1, w0, w1, w2);
}
}
}
+ fz_catch(ctx)
+ {
+ fz_close(stm);
+ fz_drop_obj(trailer);
+ fz_drop_obj(index);
+ fz_drop_obj(obj);
+ fz_rethrow(ctx);
+ }
fz_close(stm);
- *trailerp = trailer;
-
- return fz_okay;
+ return trailer;
}
-static fz_error
-pdf_read_xref(fz_obj **trailerp, pdf_xref *xref, int ofs, char *buf, int cap)
+static fz_obj *
+pdf_read_xref(pdf_xref *xref, int ofs, char *buf, int cap)
{
- fz_error error;
int c;
+ fz_context *ctx = xref->ctx;
+ fz_obj *trailer;
fz_seek(xref->file, ofs, 0);
while (iswhite(fz_peek_byte(xref->file)))
fz_read_byte(xref->file);
- c = fz_peek_byte(xref->file);
- if (c == 'x')
+ fz_try(ctx)
{
- error = pdf_read_old_xref(trailerp, xref, buf, cap);
- if (error)
- return fz_error_note(error, "cannot read xref (ofs=%d)", ofs);
+ c = fz_peek_byte(xref->file);
+ if (c == 'x')
+ trailer = pdf_read_old_xref(xref, buf, cap);
+ else if (c >= '0' && c <= '9')
+ trailer = pdf_read_new_xref(xref, buf, cap);
+ else
+ fz_throw(ctx, "cannot recognize xref format");
}
- else if (c >= '0' && c <= '9')
+ fz_catch(ctx)
{
- error = pdf_read_new_xref(trailerp, xref, buf, cap);
- if (error)
- return fz_error_note(error, "cannot read xref (ofs=%d)", ofs);
+ fz_throw(ctx, "cannot read xref (ofs=%d)", ofs);
}
- else
- {
- return fz_error_make("cannot recognize xref format");
- }
-
- return fz_okay;
+ return trailer;
}
-static fz_error
+static void
pdf_read_xref_sections(pdf_xref *xref, int ofs, char *buf, int cap)
{
- fz_error error;
- fz_obj *trailer;
- fz_obj *prev;
- fz_obj *xrefstm;
-
- error = pdf_read_xref(&trailer, xref, ofs, buf, cap);
- if (error)
- return fz_error_note(error, "cannot read xref section");
+ fz_obj *trailer = NULL;
+ fz_obj *xrefstm = NULL;
+ fz_obj *prev = NULL;
+ fz_context *ctx = xref->ctx;
- /* FIXME: do we overwrite free entries properly? */
- xrefstm = fz_dict_gets(trailer, "XRefStm");
- if (xrefstm)
+ fz_try(ctx)
{
- error = pdf_read_xref_sections(xref, fz_to_int(xrefstm), buf, cap);
- if (error)
- {
- fz_drop_obj(trailer);
- return fz_error_note(error, "cannot read /XRefStm xref section");
- }
- }
+ trailer = pdf_read_xref(xref, ofs, buf, cap);
+
+ /* FIXME: do we overwrite free entries properly? */
+ xrefstm = fz_dict_gets(trailer, "XRefStm");
+ if (xrefstm)
+ pdf_read_xref_sections(xref, fz_to_int(xrefstm), buf, cap);
- prev = fz_dict_gets(trailer, "Prev");
- if (prev)
+ prev = fz_dict_gets(trailer, "Prev");
+ if (prev)
+ pdf_read_xref_sections(xref, fz_to_int(prev), buf, cap);
+ }
+ fz_catch(ctx)
{
- error = pdf_read_xref_sections(xref, fz_to_int(prev), buf, cap);
- if (error)
- {
- fz_drop_obj(trailer);
- return fz_error_note(error, "cannot read /Prev xref section");
- }
+ fz_drop_obj(trailer);
+ fz_throw(ctx, "Failed to read xref at offset %d", ofs);
}
fz_drop_obj(trailer);
- return fz_okay;
}
/*
* load xref tables from pdf
*/
-static fz_error
+static void
pdf_load_xref(pdf_xref *xref, char *buf, int bufsize)
{
- fz_error error;
fz_obj *size;
int i;
+ fz_context *ctx = xref->ctx;
- error = pdf_load_version(xref);
- if (error)
- return fz_error_note(error, "cannot read version marker");
+ pdf_load_version(xref);
- error = pdf_read_start_xref(xref);
- if (error)
- return fz_error_note(error, "cannot read startxref");
+ pdf_read_start_xref(xref);
- error = pdf_read_trailer(xref, buf, bufsize);
- if (error)
- return fz_error_note(error, "cannot read trailer");
+ pdf_read_trailer(xref, buf, bufsize);
size = fz_dict_gets(xref->trailer, "Size");
if (!size)
- return fz_error_make("trailer missing Size entry");
+ fz_throw(ctx, "trailer missing Size entry");
pdf_resize_xref(xref, fz_to_int(size));
- error = pdf_read_xref_sections(xref, xref->startxref, buf, bufsize);
- if (error)
- return fz_error_note(error, "cannot read xref");
+ pdf_read_xref_sections(xref, xref->startxref, buf, bufsize);
/* broken pdfs where first object is not free */
if (xref->table[0].type != 'f')
- return fz_error_make("first object in xref is not free");
+ fz_throw(ctx, "first object in xref is not free");
/* broken pdfs where object offsets are out of range */
for (i = 0; i < xref->len; i++)
{
if (xref->table[i].type == 'n')
if (xref->table[i].ofs <= 0 || xref->table[i].ofs >= xref->file_size)
- return fz_error_make("object offset out of range: %d (%d 0 R)", xref->table[i].ofs, i);
+ fz_throw(ctx, "object offset out of range: %d (%d 0 R)", xref->table[i].ofs, i);
if (xref->table[i].type == 'o')
if (xref->table[i].ofs <= 0 || xref->table[i].ofs >= xref->len || xref->table[xref->table[i].ofs].type != 'n')
- return fz_error_make("invalid reference to an objstm that does not exist: %d (%d 0 R)", xref->table[i].ofs, i);
+ fz_throw(ctx, "invalid reference to an objstm that does not exist: %d (%d 0 R)", xref->table[i].ofs, i);
}
-
- return fz_okay;
}
/*
@@ -514,29 +474,32 @@ pdf_load_xref(pdf_xref *xref, char *buf, int bufsize)
* If password is not null, try to decrypt.
*/
-fz_error
-pdf_open_xref_with_stream(pdf_xref **xrefp, fz_stream *file, char *password)
+pdf_xref *
+pdf_open_xref_with_stream(fz_stream *file, char *password)
{
pdf_xref *xref;
- fz_error error;
fz_obj *encrypt, *id;
- fz_obj *dict, *obj;
+ fz_obj *dict = NULL;
+ fz_obj *obj;
+ fz_obj *nobj;
int i, repaired = 0;
fz_context *ctx = file->ctx;
+ //fz_var(dict);
+
/* install pdf specific callback */
fz_resolve_indirect = pdf_resolve_indirect;
- xref = fz_malloc(ctx, sizeof(pdf_xref));
- memset(xref, 0, sizeof *xref);
-
+ xref = fz_calloc(ctx, 1, sizeof(pdf_xref));
xref->file = fz_keep_stream(file);
xref->ctx = ctx;
- error = pdf_load_xref(xref, xref->scratch, sizeof xref->scratch);
- if (error)
+ fz_try(ctx)
+ {
+ pdf_load_xref(xref, xref->scratch, sizeof xref->scratch);
+ }
+ fz_catch(ctx)
{
- fz_error_handle(error, "trying to repair");
if (xref->table)
{
fz_free(xref->ctx, xref->table);
@@ -548,50 +511,31 @@ pdf_open_xref_with_stream(pdf_xref **xrefp, fz_stream *file, char *password)
fz_drop_obj(xref->trailer);
xref->trailer = NULL;
}
- error = pdf_repair_xref(xref, xref->scratch, sizeof xref->scratch);
- if (error)
- {
- pdf_free_xref(xref);
- return fz_error_note(error, "cannot repair document");
- }
+ pdf_repair_xref(xref, xref->scratch, sizeof xref->scratch);
repaired = 1;
}
- encrypt = fz_dict_gets(xref->trailer, "Encrypt");
- id = fz_dict_gets(xref->trailer, "ID");
- if (fz_is_dict(encrypt))
+ fz_try(ctx)
{
- error = pdf_new_crypt(ctx, &xref->crypt, encrypt, id);
- if (error)
- {
- pdf_free_xref(xref);
- return fz_error_note(error, "cannot decrypt document");
- }
- }
+ int hasroot, hasinfo;
- if (pdf_needs_password(xref))
- {
- /* Only care if we have a password */
- if (password)
+ encrypt = fz_dict_gets(xref->trailer, "Encrypt");
+ id = fz_dict_gets(xref->trailer, "ID");
+ if (fz_is_dict(encrypt))
+ xref->crypt = pdf_new_crypt(ctx, encrypt, id);
+
+ if (pdf_needs_password(xref))
{
- int okay = pdf_authenticate_password(xref, password);
- if (!okay)
+ /* Only care if we have a password */
+ if (password)
{
- pdf_free_xref(xref);
- return fz_error_make("invalid password");
+ pdf_authenticate_password(xref, password);
}
}
- }
-
- if (repaired)
- {
- int hasroot, hasinfo;
- error = pdf_repair_obj_stms(xref);
- if (error)
+ if (repaired)
{
- pdf_free_xref(xref);
- return fz_error_note(error, "cannot repair document");
+ pdf_repair_obj_stms(xref);
}
hasroot = fz_dict_gets(xref->trailer, "Root") != NULL;
@@ -602,10 +546,13 @@ pdf_open_xref_with_stream(pdf_xref **xrefp, fz_stream *file, char *password)
if (xref->table[i].type == 0 || xref->table[i].type == 'f')
continue;
- error = pdf_load_object(&dict, xref, i, 0);
- if (error)
+ fz_try(ctx)
{
- fz_error_handle(error, "ignoring broken object (%d 0 R)", i);
+ dict = pdf_load_object(xref, i, 0);
+ }
+ fz_catch(ctx)
+ {
+ fz_warn(ctx, "ignoring broken object (%d 0 R)", i);
continue;
}
@@ -614,9 +561,10 @@ pdf_open_xref_with_stream(pdf_xref **xrefp, fz_stream *file, char *password)
obj = fz_dict_gets(dict, "Type");
if (fz_is_name(obj) && !strcmp(fz_to_name(obj), "Catalog"))
{
- obj = fz_new_indirect(ctx, i, 0, xref);
- fz_dict_puts(xref->trailer, "Root", obj);
- fz_drop_obj(obj);
+ nobj = fz_new_indirect(ctx, i, 0, xref);
+ fz_dict_puts(xref->trailer, "Root", nobj);
+ fz_drop_obj(nobj);
+ nobj = NULL;
}
}
@@ -624,18 +572,26 @@ pdf_open_xref_with_stream(pdf_xref **xrefp, fz_stream *file, char *password)
{
if (fz_dict_gets(dict, "Creator") || fz_dict_gets(dict, "Producer"))
{
- obj = fz_new_indirect(ctx, i, 0, xref);
- fz_dict_puts(xref->trailer, "Info", obj);
- fz_drop_obj(obj);
+ nobj = fz_new_indirect(ctx, i, 0, xref);
+ fz_dict_puts(xref->trailer, "Info", nobj);
+ fz_drop_obj(nobj);
+ nobj = NULL;
}
}
fz_drop_obj(dict);
+ dict = NULL;
}
}
+ fz_catch(ctx)
+ {
+ fz_drop_obj(dict);
+ fz_drop_obj(nobj);
+ pdf_free_xref(xref);
+ fz_throw(ctx, "cannot open document");
+ }
- *xrefp = xref;
- return fz_okay;
+ return xref;
}
void
@@ -703,14 +659,13 @@ pdf_debug_xref(pdf_xref *xref)
* compressed object streams
*/
-static fz_error
+static void
pdf_load_obj_stm(pdf_xref *xref, int num, int gen, char *buf, int cap)
{
- fz_error error;
fz_stream *stm;
fz_obj *objstm;
- int *numbuf;
- int *ofsbuf;
+ int * volatile numbuf = NULL;
+ int * volatile ofsbuf = NULL;
fz_obj *obj;
int first;
@@ -719,125 +674,113 @@ pdf_load_obj_stm(pdf_xref *xref, int num, int gen, char *buf, int cap)
int tok;
fz_context *ctx = xref->ctx;
- error = pdf_load_object(&objstm, xref, num, gen);
- if (error)
- return fz_error_note(error, "cannot load object stream object (%d %d R)", num, gen);
-
- count = fz_to_int(fz_dict_gets(objstm, "N"));
- first = fz_to_int(fz_dict_gets(objstm, "First"));
-
- numbuf = fz_malloc_array(ctx, count, sizeof(int));
- ofsbuf = fz_malloc_array(ctx, count, sizeof(int));
-
- error = pdf_open_stream(&stm, xref, num, gen);
- if (error)
+ //fz_var(numbuf);
+ //fz_var(ofsbuf);
+ fz_try(ctx)
{
- error = fz_error_note(error, "cannot open object stream (%d %d R)", num, gen);
- goto cleanupbuf;
- }
+ objstm = pdf_load_object(xref, num, gen);
- for (i = 0; i < count; i++)
- {
- error = pdf_lex(&tok, stm, buf, cap, &n);
- if (error || tok != PDF_TOK_INT)
- {
- error = fz_error_note(error, "corrupt object stream (%d %d R)", num, gen);
- goto cleanupstm;
- }
- numbuf[i] = atoi(buf);
+ count = fz_to_int(fz_dict_gets(objstm, "N"));
+ first = fz_to_int(fz_dict_gets(objstm, "First"));
+
+ numbuf = fz_calloc(ctx, count, sizeof(int));
+ ofsbuf = fz_calloc(ctx, count, sizeof(int));
- error = pdf_lex(&tok, stm, buf, cap, &n);
- if (error || tok != PDF_TOK_INT)
+ stm = pdf_open_stream(xref, num, gen);
+ for (i = 0; i < count; i++)
{
- error = fz_error_note(error, "corrupt object stream (%d %d R)", num, gen);
- goto cleanupstm;
+ tok = pdf_lex(stm, buf, cap, &n);
+ if (tok != PDF_TOK_INT)
+ fz_throw(ctx, "corrupt object stream (%d %d R)", num, gen);
+ numbuf[i] = atoi(buf);
+
+ tok = pdf_lex(stm, buf, cap, &n);
+ if (tok != PDF_TOK_INT)
+ fz_throw(ctx, "corrupt object stream (%d %d R)", num, gen);
+ ofsbuf[i] = atoi(buf);
}
- ofsbuf[i] = atoi(buf);
- }
- fz_seek(stm, first, 0);
+ fz_seek(stm, first, 0);
- for (i = 0; i < count; i++)
- {
- fz_seek(stm, first + ofsbuf[i], 0);
-
- error = pdf_parse_stm_obj(&obj, xref, stm, buf, cap);
- if (error)
+ for (i = 0; i < count; i++)
{
- error = fz_error_note(error, "cannot parse object %d in stream (%d %d R)", i, num, gen);
- goto cleanupstm;
- }
+ fz_seek(stm, first + ofsbuf[i], 0);
- if (numbuf[i] < 1 || numbuf[i] >= xref->len)
- {
- fz_drop_obj(obj);
- error = fz_error_make("object id (%d 0 R) out of range (0..%d)", numbuf[i], xref->len - 1);
- goto cleanupstm;
- }
+ obj = pdf_parse_stm_obj(xref, stm, buf, cap);
+ /* RJW: Ensure above does fz_throw(ctx, "cannot parse object %d in stream (%d %d R)", i, num, gen); */
- if (xref->table[numbuf[i]].type == 'o' && xref->table[numbuf[i]].ofs == num)
- {
- if (xref->table[numbuf[i]].obj)
- fz_drop_obj(xref->table[numbuf[i]].obj);
- xref->table[numbuf[i]].obj = obj;
- }
- else
- {
- fz_drop_obj(obj);
+ if (numbuf[i] < 1 || numbuf[i] >= xref->len)
+ {
+ fz_drop_obj(obj);
+ fz_throw(ctx, "object id (%d 0 R) out of range (0..%d)", numbuf[i], xref->len - 1);
+ }
+
+ if (xref->table[numbuf[i]].type == 'o' && xref->table[numbuf[i]].ofs == num)
+ {
+ if (xref->table[numbuf[i]].obj)
+ fz_drop_obj(xref->table[numbuf[i]].obj);
+ xref->table[numbuf[i]].obj = obj;
+ }
+ else
+ {
+ fz_drop_obj(obj);
+ }
}
}
-
- fz_close(stm);
- fz_free(xref->ctx, ofsbuf);
- fz_free(xref->ctx, numbuf);
- fz_drop_obj(objstm);
- return fz_okay;
-
-cleanupstm:
+ fz_catch(ctx)
+ {
+ fz_close(stm);
+ fz_free(xref->ctx, ofsbuf);
+ fz_free(xref->ctx, numbuf);
+ fz_drop_obj(objstm);
+ fz_throw(ctx, "cannot open object stream (%d %d R)", num, gen);
+ }
fz_close(stm);
-cleanupbuf:
fz_free(xref->ctx, ofsbuf);
fz_free(xref->ctx, numbuf);
fz_drop_obj(objstm);
- return error; /* already rethrown */
}
/*
* object loading
*/
-fz_error
+void
pdf_cache_object(pdf_xref *xref, int num, int gen)
{
- fz_error error;
pdf_xref_entry *x;
int rnum, rgen;
fz_context *ctx = xref->ctx;
if (num < 0 || num >= xref->len)
- return fz_error_make("object out of range (%d %d R); xref size %d", num, gen, xref->len);
+ fz_throw(ctx, "object out of range (%d %d R); xref size %d", num, gen, xref->len);
x = &xref->table[num];
if (x->obj)
- return fz_okay;
+ return;
if (x->type == 'f')
{
x->obj = fz_new_null(ctx);
- return fz_okay;
+ return;
}
else if (x->type == 'n')
{
fz_seek(xref->file, x->ofs, 0);
- error = pdf_parse_ind_obj(&x->obj, xref, xref->file, xref->scratch, sizeof xref->scratch,
- &rnum, &rgen, &x->stm_ofs);
- if (error)
- return fz_error_note(error, "cannot parse object (%d %d R)", num, gen);
+ fz_try(ctx)
+ {
+ x->obj = pdf_parse_ind_obj(xref, xref->file, xref->scratch, sizeof xref->scratch,
+ &rnum, &rgen, &x->stm_ofs);
+ }
+ fz_catch(ctx)
+ {
+ fz_throw(ctx, "cannot parse object (%d %d R)", num, gen);
+ }
if (rnum != num)
- return fz_error_make("found object (%d %d R) instead of (%d %d R)", rnum, rgen, num, gen);
+ fz_throw(ctx, "found object (%d %d R) instead of (%d %d R)", rnum, rgen, num, gen);
if (xref->crypt)
pdf_crypt_obj(ctx, xref->crypt, x->obj, num, gen);
@@ -846,35 +789,41 @@ pdf_cache_object(pdf_xref *xref, int num, int gen)
{
if (!x->obj)
{
- error = pdf_load_obj_stm(xref, x->ofs, 0, xref->scratch, sizeof xref->scratch);
- if (error)
- return fz_error_note(error, "cannot load object stream containing object (%d %d R)", num, gen);
+ fz_try(ctx)
+ {
+ pdf_load_obj_stm(xref, x->ofs, 0, xref->scratch, sizeof xref->scratch);
+ }
+ fz_catch(ctx)
+ {
+ fz_throw(ctx, "cannot load object stream containing object (%d %d R)", num, gen);
+ }
if (!x->obj)
- return fz_error_make("object (%d %d R) was not found in its object stream", num, gen);
+ fz_throw(ctx, "object (%d %d R) was not found in its object stream", num, gen);
}
}
else
{
- return fz_error_make("assert: corrupt xref struct");
+ fz_throw(ctx, "assert: corrupt xref struct");
}
-
- return fz_okay;
}
-fz_error
-pdf_load_object(fz_obj **objp, pdf_xref *xref, int num, int gen)
+fz_obj *
+pdf_load_object(pdf_xref *xref, int num, int gen)
{
- fz_error error;
+ fz_context *ctx = xref->ctx;
- error = pdf_cache_object(xref, num, gen);
- if (error)
- return fz_error_note(error, "cannot load object (%d %d R) into cache", num, gen);
+ fz_try(ctx)
+ {
+ pdf_cache_object(xref, num, gen);
+ }
+ fz_catch(ctx)
+ {
+ fz_throw(ctx, "cannot load object (%d %d R) into cache", num, gen);
+ }
assert(xref->table[num].obj);
- *objp = fz_keep_obj(xref->table[num].obj);
-
- return fz_okay;
+ return fz_keep_obj(xref->table[num].obj);
}
fz_obj *
@@ -883,14 +832,18 @@ pdf_resolve_indirect(fz_obj *ref)
if (fz_is_indirect(ref))
{
pdf_xref *xref = fz_get_indirect_xref(ref);
+ fz_context *ctx = xref->ctx;
int num = fz_to_num(ref);
int gen = fz_to_gen(ref);
if (xref)
{
- fz_error error = pdf_cache_object(xref, num, gen);
- if (error)
+ fz_try(ctx)
+ {
+ pdf_cache_object(xref, num, gen);
+ }
+ fz_catch(ctx)
{
- fz_error_handle(error, "cannot load object (%d %d R) into cache", num, gen);
+ fz_warn(ctx, "cannot load object (%d %d R) into cache", num, gen);
return ref;
}
if (xref->table[num].obj)
@@ -926,20 +879,24 @@ pdf_update_object(pdf_xref *xref, int num, int gen, fz_obj *newobj)
* Convenience function to open a file then call pdf_open_xref_with_stream.
*/
-fz_error
-pdf_open_xref(fz_context *ctx, pdf_xref **xrefp, const char *filename, char *password)
+pdf_xref *
+pdf_open_xref(fz_context *ctx, const char *filename, char *password)
{
- fz_error error;
- fz_stream *file;
-
- file = fz_open_file(ctx, filename);
- if (!file)
- return fz_error_make("cannot open file '%s': %s", filename, strerror(errno));
+ fz_stream *file = NULL;
+ pdf_xref *xref;
- error = pdf_open_xref_with_stream(xrefp, file, password);
- if (error)
- return fz_error_note(error, "cannot load document '%s'", filename);
+ //fz_var(file);
+ fz_try(ctx)
+ {
+ file = fz_open_file(ctx, filename);
+ xref = pdf_open_xref_with_stream(file, password);
+ }
+ fz_catch(ctx)
+ {
+ fz_close(file);
+ fz_throw(ctx, "cannot load document '%s'", filename);
+ }
fz_close(file);
- return fz_okay;
+ return xref;
}