diff options
author | Tor Andersson <tor@ghostscript.com> | 2004-10-05 09:52:44 +0200 |
---|---|---|
committer | Tor Andersson <tor@ghostscript.com> | 2004-10-05 09:52:44 +0200 |
commit | 9ce9759c580d5522ad2d3812b26aff49644d8881 (patch) | |
tree | 2eb3aa263955f7bdfe4461624aa3dfe8d9992e83 | |
parent | 7ad0eac4b8c81c5123ef5a62b23ba2895dd997c8 (diff) | |
download | mupdf-9ce9759c580d5522ad2d3812b26aff49644d8881.tar.xz |
improved reading to buffers and writing files
-rw-r--r-- | filter/buffer.c | 2 | ||||
-rw-r--r-- | filter/filec.c | 9 | ||||
-rw-r--r-- | filter/filer.c | 23 | ||||
-rw-r--r-- | filter/filew.c | 7 | ||||
-rw-r--r-- | include/fitz/file.h | 2 | ||||
-rw-r--r-- | include/mupdf.h | 6 | ||||
-rw-r--r-- | mupdf/font.c | 12 | ||||
-rw-r--r-- | mupdf/fontfile.c | 9 | ||||
-rw-r--r-- | mupdf/save.c | 140 | ||||
-rw-r--r-- | mupdf/stream.c | 20 | ||||
-rw-r--r-- | mupdf/xref.c | 12 | ||||
-rw-r--r-- | test/pdfclean.c | 526 | ||||
-rw-r--r-- | test/pdfdebug.c | 152 |
13 files changed, 239 insertions, 681 deletions
diff --git a/filter/buffer.c b/filter/buffer.c index 25e30a55..aae27474 100644 --- a/filter/buffer.c +++ b/filter/buffer.c @@ -32,7 +32,7 @@ fz_newbufferwithdata(fz_buffer **bp, unsigned char *data, int size) b->bp = data; b->rp = b->bp; - b->wp = b->bp; + b->wp = b->bp + size; b->ep = b->bp + size; b->eof = 0; diff --git a/filter/filec.c b/filter/filec.c index f62d1265..fc5599e1 100644 --- a/filter/filec.c +++ b/filter/filec.c @@ -13,15 +13,20 @@ fz_openfile(fz_file **filep, char *path, int mode) { fz_error *error; fz_file *file; + int realmode; int fd; - assert(mode == O_RDONLY || mode == O_WRONLY); + assert(mode == O_RDONLY || mode == O_WRONLY || mode == O_APPEND); + + realmode = mode; + if (mode == O_WRONLY) + realmode = O_WRONLY | O_CREAT | O_TRUNC; file = *filep = fz_malloc(sizeof(fz_file)); if (!file) return fz_outofmem; - fd = open(path, mode, 0); + fd = open(path, realmode, 0644); if (fd == -1) return fz_throw("ioerror: open '%s': %s", path, strerror(errno)); diff --git a/filter/filer.c b/filter/filer.c index 804d7f7e..368f9dbe 100644 --- a/filter/filer.c +++ b/filter/filer.c @@ -175,11 +175,12 @@ fz_readline(fz_file *f, char *buf, int n) * a freshly allocated buffer; realloced and trimmed to size. */ -enum { CHUNKSIZE = 4096 }; +enum { CHUNKSIZE = 1024 * 32 }; fz_error * -fz_readfile(unsigned char **bufp, int *lenp, fz_file *file) +fz_readfile(fz_buffer **bufp, fz_file *file) { + fz_buffer *real; unsigned char *newbuf; unsigned char *buf; int len; @@ -187,7 +188,6 @@ fz_readfile(unsigned char **bufp, int *lenp, fz_file *file) int n; *bufp = nil; - *lenp = 0; len = 0; pos = 0; @@ -209,8 +209,6 @@ fz_readfile(unsigned char **bufp, int *lenp, fz_file *file) n = fz_read(file, buf + pos, len - pos); -printf("fz_read %d bytes\n", n); - if (n < 0) { fz_free(buf); @@ -228,8 +226,19 @@ printf("fz_read %d bytes\n", n); return fz_outofmem; } - *bufp = newbuf; - *lenp = pos; + real = *bufp = fz_malloc(sizeof(fz_buffer)); + if (!real) + { + fz_free(newbuf); + return fz_outofmem; + } + + real->ownsdata = 1; + real->bp = buf; + real->rp = buf; + real->wp = buf + pos; + real->ep = buf + pos; + return nil; } } diff --git a/filter/filew.c b/filter/filew.c index 0422e60e..a7b15664 100644 --- a/filter/filew.c +++ b/filter/filew.c @@ -99,7 +99,12 @@ fz_write(fz_file *f, char *buf, int n) return -1; } - fz_rewindbuffer(f->in); + if (f->in->rp > f->in->bp) + f->error = fz_rewindbuffer(f->in); + else + f->error = fz_growbuffer(f->in); + if (f->error) + return -1; } } diff --git a/include/fitz/file.h b/include/fitz/file.h index 7807570c..2d6dc977 100644 --- a/include/fitz/file.h +++ b/include/fitz/file.h @@ -26,7 +26,7 @@ int fz_peekbyte(fz_file *f); int fz_readline(fz_file *f, char *buf, int n); int fz_read(fz_file *f, char *buf, int n); -fz_error *fz_readfile(unsigned char **bufp, int *lenp, fz_file *file); +fz_error *fz_readfile(fz_buffer **bufp, fz_file *file); int fz_printstring(fz_file *f, char *s); int fz_printobj(fz_file *f, fz_obj *o, int tight); diff --git a/include/mupdf.h b/include/mupdf.h index c5dcc133..98f40c62 100644 --- a/include/mupdf.h +++ b/include/mupdf.h @@ -81,7 +81,8 @@ fz_error *pdf_buildfilter(fz_filter**, pdf_xref*, fz_obj *stm, int oid, int gid) fz_error *pdf_openstream0(pdf_xref*, fz_obj *stmobj, int oid, int gid, int ofs); fz_error *pdf_openstream(pdf_xref*, fz_obj *stmref); void pdf_closestream(pdf_xref*); -fz_error *pdf_readstream(unsigned char **bufp, int *lenp, pdf_xref*, fz_obj *stmref); +fz_error *pdf_readstream0(fz_buffer **bufp, pdf_xref*, fz_obj *stmobj, int oid, int gid, int ofs); +fz_error *pdf_readstream(fz_buffer **bufp, pdf_xref*, fz_obj *stmref); /* crypt.c */ fz_error *pdf_newdecrypt(pdf_crypt **cp, fz_obj *enc, fz_obj *id); @@ -118,6 +119,9 @@ fz_error *pdf_loadobject0(fz_obj **, pdf_xref*, int oid, int gid, int *stmofs); fz_error *pdf_loadobject(fz_obj **, pdf_xref*, fz_obj *ref, int *stmofs); fz_error *pdf_resolve(fz_obj **, pdf_xref*); +fz_error *pdf_savestream(pdf_xref *xref, int oid, int gid, fz_buffer *buf); +fz_error *pdf_deletestream(pdf_xref *xref, int oid, int gid); + /* save.c */ fz_error *pdf_saveincrementalpdf(pdf_xref *xref, char *path); fz_error *pdf_savepdf(pdf_xref *xref, char *path); diff --git a/mupdf/font.c b/mupdf/font.c index 6d499c60..7c75f585 100644 --- a/mupdf/font.c +++ b/mupdf/font.c @@ -562,17 +562,19 @@ printf(" embedded CMap\n"); cidtogidmap = fz_dictgets(dict, "CIDToGIDMap"); if (fz_isindirect(cidtogidmap)) { - unsigned char *buf; + fz_buffer *buf; int len; - error = pdf_readstream(&buf, &len, xref, cidtogidmap); + error = pdf_readstream(&buf, xref, cidtogidmap); if (error) goto cleanup; + len = buf->wp - buf->rp; + font->cidtogidlen = len / 2; font->cidtogidmap = fz_malloc((len / 2) * sizeof(int)); if (!font->cidtogidmap) { - fz_free(buf); + fz_freebuffer(buf); error = fz_outofmem; goto cleanup; } @@ -580,7 +582,9 @@ printf(" embedded CMap\n"); printf(" cidtogidmap %d\n", len / 2); for (i = 0; i < len / 2; i++) - font->cidtogidmap[i] = (buf[i * 2] << 8) + buf[i * 2 + 1]; + font->cidtogidmap[i] = (buf->rp[i * 2] << 8) + buf->rp[i * 2 + 1]; + + fz_freebuffer(buf); } /* TODO: if truetype font is external, cidtogidmap should not be identity */ diff --git a/mupdf/fontfile.c b/mupdf/fontfile.c index 3c0470f7..21a379b2 100644 --- a/mupdf/fontfile.c +++ b/mupdf/fontfile.c @@ -194,20 +194,17 @@ pdf_loadembeddedfont(void **fontp, pdf_xref *xref, fz_obj *stmref) fz_error *error; int fterr; FT_Face face; - unsigned char *buf; - int len; + fz_buffer *buf; error = initfontlibs(); if (error) return error; - error = pdf_readstream(&buf, &len, xref, stmref); + error = pdf_readstream(&buf, xref, stmref); if (error) return error; -printf("readstream $%p %d\n", buf, len); - - fterr = FT_New_Memory_Face(ftlib, buf, len, 0, &face); + fterr = FT_New_Memory_Face(ftlib, buf->rp, buf->wp - buf->rp, 0, &face); if (fterr) { fz_free(buf); diff --git a/mupdf/save.c b/mupdf/save.c index 1698fc23..32dda709 100644 --- a/mupdf/save.c +++ b/mupdf/save.c @@ -1,9 +1,12 @@ #include <fitz.h> #include <mupdf.h> -static fz_error *writestored(FILE *out, pdf_xref *xref, int oid) +#define TIGHT 0 + +static fz_error *writestored(fz_file *out, pdf_xref *xref, int oid) { pdf_xrefentry *x = xref->table + oid; + fz_error *error; fz_obj *obj; fz_buffer *stm; @@ -16,26 +19,27 @@ static fz_error *writestored(FILE *out, pdf_xref *xref, int oid) if (xref->crypt) pdf_cryptobj(xref->crypt, obj, oid, x->gen); - fprintf(out, "%d %d obj\n", oid, x->gen); - fz_debugobj(obj); - fprintf(out, "\n"); + fz_print(out, "%d %d obj\n", oid, x->gen); + fz_printobj(out, obj, TIGHT); + fz_print(out, "\n"); if (stm) { - fprintf(out, "stream\n"); - fwrite(stm->rp, 1, stm->wp - stm->rp, out); - fprintf(out, "endstream\n"); + fz_print(out, "stream\n"); + fz_write(out, stm->rp, stm->wp - stm->rp); + fz_print(out, "endstream\n"); } - fprintf(out, "endobj\n\n"); + fz_print(out, "endobj\n\n"); - if (ferror(out)) - return fz_throw("ioerror: write failed"); + error = fz_ferror(out); + if (error) + return error; return nil; } -static fz_error *writecopy(FILE *out, pdf_xref *xref, int oid) +static fz_error *writecopy(fz_file *out, pdf_xref *xref, int oid) { pdf_xrefentry *x = xref->table + oid; fz_error *error; @@ -52,13 +56,13 @@ static fz_error *writecopy(FILE *out, pdf_xref *xref, int oid) if (error) return error; - fprintf(out, "%d %d obj\n", oid, x->gen); - fz_debugobj(obj); - fprintf(out, "\n"); + fz_print(out, "%d %d obj\n", oid, x->gen); + fz_printobj(out, obj, TIGHT); + fz_print(out, "\n"); if (stmofs != -1) { - fprintf(out, "stream\n"); + fz_print(out, "stream\n"); length = fz_dictgets(obj, "Length"); error = pdf_resolve(&length, xref); @@ -98,20 +102,21 @@ static fz_error *writecopy(FILE *out, pdf_xref *xref, int oid) fz_popfilter(xref->file); goto cleanup; } - fwrite(buf, 1, n, out); + fz_write(out, buf, n); } fz_popfilter(xref->file); - fprintf(out, "endstream\n"); + fz_print(out, "endstream\n"); } - fprintf(out, "endobj\n\n"); + fz_print(out, "endobj\n\n"); - fz_dropobj(obj); + error = fz_ferror(out); + if (error) + goto cleanup; - if (ferror(out)) - return fz_throw("ioerror: write failed"); + fz_dropobj(obj); return nil; @@ -133,22 +138,23 @@ fz_error * pdf_saveincrementalpdf(pdf_xref *xref, char *path) { fz_error *error; - FILE *out; + fz_file *out; int oid; int i, n; int startxref; fz_obj *obj; - out = fopen(path, "ab"); - if (!out) - return fz_throw("ioerror: could not open '%s': %s", path, strerror(errno)); - fprintf(out, "\n"); + error = fz_openfile(&out, path, O_APPEND); + if (error) + return error; + + fz_print(out, "\n"); for (oid = 0; oid < xref->size; oid++) { if (xref->table[oid].type == 'a') { - xref->table[oid].ofs = ftell(out); + xref->table[oid].ofs = fz_tell(out); error = writestored(out, xref, oid); if (error) goto cleanup; @@ -158,15 +164,15 @@ pdf_saveincrementalpdf(pdf_xref *xref, char *path) /* always write out entry 0 in appended xref sections */ xref->table[0].type = 'd'; - startxref = ftell(out); - fprintf(out, "xref\n"); + startxref = fz_tell(out); + fz_print(out, "xref\n"); oid = 0; while (oid < xref->size) { n = countmodified(xref, oid); - fprintf(out, "%d %d\n", oid, n); + fz_print(out, "%d %d\n", oid, n); for (i = 0; i < n; i++) { @@ -175,7 +181,7 @@ pdf_saveincrementalpdf(pdf_xref *xref, char *path) if (xref->table[oid + i].type == 'a') xref->table[oid + i].type = 'n'; - fprintf(out, "%010d %05d %c \n", + fz_print(out, "%010d %05d %c \n", xref->table[oid + i].ofs, xref->table[oid + i].gen, xref->table[oid + i].type); @@ -188,42 +194,42 @@ pdf_saveincrementalpdf(pdf_xref *xref, char *path) oid ++; } - fprintf(out, "\n"); + fz_print(out, "\n"); - fprintf(out, "trailer\n<<\n /Size %d\n /Prev %d", xref->size, xref->startxref); + fz_print(out, "trailer\n<<\n /Size %d\n /Prev %d", xref->size, xref->startxref); obj = fz_dictgets(xref->trailer, "Root"); - fprintf(out,"\n /Root %d %d R", fz_toobjid(obj), fz_togenid(obj)); + fz_print(out,"\n /Root %d %d R", fz_toobjid(obj), fz_togenid(obj)); obj = fz_dictgets(xref->trailer, "Info"); if (obj) - fprintf(out,"\n /Info %d %d R", fz_toobjid(obj), fz_togenid(obj)); + fz_print(out,"\n /Info %d %d R", fz_toobjid(obj), fz_togenid(obj)); obj = fz_dictgets(xref->trailer, "Encrypt"); if (obj) { - fprintf(out,"\n /Encrypt "); - fz_debugobj(obj); + fz_print(out,"\n /Encrypt "); + fz_printobj(out, obj, TIGHT); } obj = fz_dictgets(xref->trailer, "ID"); if (obj) { - fprintf(out,"\n /ID "); - fz_debugobj(obj); + fz_print(out,"\n /ID "); + fz_printobj(out, obj, TIGHT); } - fprintf(out, "\n>>\n\n"); + fz_print(out, "\n>>\n\n"); - fprintf(out, "startxref\n"); - fprintf(out, "%d\n", startxref); - fprintf(out, "%%%%EOF\n"); + fz_print(out, "startxref\n"); + fz_print(out, "%d\n", startxref); + fz_print(out, "%%%%EOF\n"); xref->startxref = startxref; - fclose(out); + fz_closefile(out); return nil; cleanup: - fclose(out); + fz_closefile(out); return error; } @@ -231,7 +237,7 @@ fz_error * pdf_savepdf(pdf_xref *xref, char *path) { fz_error *error; - FILE *out; + fz_file *out; int oid; int startxref; int *ofsbuf; @@ -241,28 +247,28 @@ pdf_savepdf(pdf_xref *xref, char *path) if (!ofsbuf) return fz_outofmem; - out = fopen(path, "wb"); - if (!out) + error = fz_openfile(&out, path, O_WRONLY); + if (error) { fz_free(ofsbuf); - return fz_throw("ioerror: could not open '%s': %s", path, strerror(errno)); + return error; } - fprintf(out, "%%PDF-%1.1f\n", xref->version); - fprintf(out, "%%\342\343\317\323\n\n"); + fz_print(out, "%%PDF-%1.1f\n", xref->version); + fz_print(out, "%%\342\343\317\323\n\n"); for (oid = 0; oid < xref->size; oid++) { if (xref->table[oid].type == 'n' || xref->table[oid].type == 'o') { - ofsbuf[oid] = ftell(out); + ofsbuf[oid] = fz_tell(out); error = writecopy(out, xref, oid); if (error) goto cleanup; } else if (xref->table[oid].type == 'a') { - ofsbuf[oid] = ftell(out); + ofsbuf[oid] = fz_tell(out); error = writestored(out, xref, oid); if (error) goto cleanup; @@ -273,9 +279,9 @@ pdf_savepdf(pdf_xref *xref, char *path) } } - startxref = ftell(out); - fprintf(out, "xref\n"); - fprintf(out, "0 %d\n", xref->size); + startxref = fz_tell(out); + fz_print(out, "xref\n"); + fz_print(out, "0 %d\n", xref->size); for (oid = 0; oid < xref->size; oid++) { @@ -284,30 +290,30 @@ pdf_savepdf(pdf_xref *xref, char *path) type = 'n'; if (type == 'd') type = 'f'; - fprintf(out, "%010d %05d %c \n", ofsbuf[oid], xref->table[oid].gen, type); + fz_print(out, "%010d %05d %c \n", ofsbuf[oid], xref->table[oid].gen, type); } - fprintf(out, "\n"); + fz_print(out, "\n"); - fprintf(out, "trailer\n<<\n /Size %d", xref->size); + fz_print(out, "trailer\n<<\n /Size %d", xref->size); obj = fz_dictgets(xref->trailer, "Root"); - fprintf(out,"\n /Root %d %d R", fz_toobjid(obj), fz_togenid(obj)); + fz_print(out,"\n /Root %d %d R", fz_toobjid(obj), fz_togenid(obj)); obj = fz_dictgets(xref->trailer, "Info"); if (obj) - fprintf(out,"\n /Info %d %d R", fz_toobjid(obj), fz_togenid(obj)); - fprintf(out, "\n>>\n\n"); + fz_print(out,"\n /Info %d %d R", fz_toobjid(obj), fz_togenid(obj)); + fz_print(out, "\n>>\n\n"); - fprintf(out, "startxref\n"); - fprintf(out, "%d\n", startxref); - fprintf(out, "%%%%EOF\n"); + fz_print(out, "startxref\n"); + fz_print(out, "%d\n", startxref); + fz_print(out, "%%%%EOF\n"); xref->startxref = startxref; - fclose(out); + fz_closefile(out); return nil; cleanup: - fclose(out); + fz_closefile(out); return error; } diff --git a/mupdf/stream.c b/mupdf/stream.c index f3f40e53..ab051865 100644 --- a/mupdf/stream.c +++ b/mupdf/stream.c @@ -245,7 +245,23 @@ pdf_closestream(pdf_xref *xref) } fz_error * -pdf_readstream(unsigned char **bufp, int *lenp, pdf_xref *xref, fz_obj *stmref) +pdf_readstream0(fz_buffer **bufp, pdf_xref *xref, fz_obj *stmobj, int oid, int gid, int ofs) +{ + fz_error *error; + + error = pdf_openstream0(xref, stmobj, oid, gid, ofs); + if (error) + return error; + + error = fz_readfile(bufp, xref->file); + + pdf_closestream(xref); + + return error; +} + +fz_error * +pdf_readstream(fz_buffer **bufp, pdf_xref *xref, fz_obj *stmref) { fz_error *error; @@ -253,7 +269,7 @@ pdf_readstream(unsigned char **bufp, int *lenp, pdf_xref *xref, fz_obj *stmref) if (error) return error; - error = fz_readfile(bufp, lenp, xref->file); + error = fz_readfile(bufp, xref->file); pdf_closestream(xref); diff --git a/mupdf/xref.c b/mupdf/xref.c index 53b9f239..08ab8621 100644 --- a/mupdf/xref.c +++ b/mupdf/xref.c @@ -325,6 +325,18 @@ pdf_saveobject(pdf_xref *xref, int oid, int gid, fz_obj *obj) return nil; } +fz_error * +pdf_savestream(pdf_xref *xref, int oid, int gid, fz_buffer *buf) +{ + return pdf_storestream(xref->store, oid, gid, buf); +} + +fz_error * +pdf_deletestream(pdf_xref *xref, int oid, int gid) +{ + return pdf_deletestoredstream(xref->store, oid, gid); +} + /* * object loading */ diff --git a/test/pdfclean.c b/test/pdfclean.c index 00721842..7eb72cda 100644 --- a/test/pdfclean.c +++ b/test/pdfclean.c @@ -1,30 +1,6 @@ #include <fitz.h> #include <mupdf.h> -#define encrypt encrypt3am - -int (*printobj)(FILE*,fz_obj*) = fz_fprintobj; - -/* - * Rewrite PDF with cleaned up syntax, and consolidate the xref table. - * Remove encryption while we're at it :) - */ - -static FILE *out; - -static pdf_xref *xt; - -static int *ofslist; -static int *genlist; -static int *uselist; - -static int dorebuild = 0; -static int doexpand = 0; -static pdf_crypt *encrypt = nil; -static fz_obj *encryptdict = nil; -static fz_obj *id = nil; -static int dogc = 0; - void usage() { fprintf(stderr, @@ -32,469 +8,129 @@ void usage() " -r\treconstruct broken xref table\n" " -g\tgarbage collect unused objects\n" " -x\texpand compressed streams\n" - " -c\twrite compact objects\n" " -d -\tset user password for decryption\n" " -e\tencrypt outfile\n" - " -u -\tset user password for encryption\n" - " -o -\tset owner password\n" - " -p -\tset permissions\n" - " -n -\tkey length in bits: 40 <= n <= 128\n" + " -u -\tset user password for encryption\n" + " -o -\tset owner password\n" + " -p -\tset permissions\n" + " -n -\tkey length in bits: 40 <= n <= 128\n" ); exit(1); } -void garbagecollect(fz_obj *ref); - -void gc0(fz_obj *obj) -{ - int i; - - if (fz_isdict(obj)) - for (i = 0; i < fz_dictlen(obj); i++) - gc0(fz_dictgetval(obj, i)); - - if (fz_isarray(obj)) - for (i = 0; i < fz_arraylen(obj); i++) - gc0(fz_arrayget(obj, i)); - - if (fz_isindirect(obj)) - garbagecollect(obj); -} - -void garbagecollect(fz_obj *ref) -{ - fz_obj *obj; - int stmofs; - - if (uselist[fz_toobjid(ref)]) - return; - - uselist[fz_toobjid(ref)] = 1; - - pdf_loadindirect(&obj, xt, ref, &stmofs); - - if (stmofs != -1) { - fz_obj *len = fz_dictgets(obj, "Length"); - if (fz_isindirect(len)) { - pdf_loadindirect(&len, xt, len, nil); - fz_dictputs(obj, "Length", len); - } - } - - gc0(obj); -} - -void decodestream(fz_obj *obj, int ofs, int oid, int gid) -{ - fz_error *error; - unsigned char buf[512]; - fz_filter *filter; - fz_file *sf; - int n; - int len; - fz_obj *lenobj; - fz_obj *newdict; - - /* count length of decoded data */ - len = 0; - - error = pdf_buildstream(&filter, xt, obj, oid, gid); - if (error) fz_abort(error); - - n = fz_seek(xt->file, ofs); - - fz_chainfile(&sf, xt->file, filter); - - while (1) { - n = fz_read(sf, buf, sizeof buf); - if (n < 0) - fz_abort(fz_ferror(sf)); - if (n == 0) - break; - len += n; - } - - fz_unchainfile(sf); - - /* change dictionary of object... */ - fz_copydict(&newdict, obj); - - fz_newint(&lenobj, len); - fz_dictputs(newdict, "Length", lenobj); - fz_dropobj(lenobj); - - fz_dictdels(newdict, "Filter"); - fz_dictdels(newdict, "DecodeParms"); - - /* save object */ - fprintf(out, "%d %d obj\n", oid, gid); - printobj(out, newdict); - fprintf(out, "\n"); - fprintf(out, "stream\n"); - - fz_dropobj(newdict); - - /* now decode stream for real */ - error = pdf_buildstream(&filter, xt, obj, oid, gid); - if (error) fz_abort(error); - - fz_seek(xt->file, ofs); - - if (encrypt) { - fz_filter *cf; - pdf_cryptstm(&cf, encrypt, oid, gid); - fz_newpipeline(&filter, filter, cf); - } - - fz_chainfile(&sf, xt->file, filter); - while (1) { - n = fz_read(sf, buf, sizeof buf); - if (n < 0) - fz_abort(fz_ferror(sf)); - if (n == 0) - break; - fwrite(buf, 1, n, out); - } - fz_unchainfile(sf); - - /* the end */ - fprintf(out, "endstream\nendobj\n\n"); - - return; -} - -void savestream(fz_obj *obj, int ofs, int oid, int gid) -{ - unsigned char buf[512]; - fz_filter *filter; - fz_file *sf; - int len; - int n; - - /* save object */ - fprintf(out, "%d %d obj\n", oid, gid); - printobj(out, obj); - fprintf(out, "\n"); - fprintf(out, "stream\n"); - - /* copy stream */ - obj = fz_dictgets(obj, "Length"); - if (fz_isindirect(obj)) { - pdf_loadindirect(&obj, xt, obj, nil); - len = fz_toint(obj); - fz_dropobj(obj); - } - else { - len = fz_toint(obj); - } - - fz_newnullfilter(&filter, len); - - if (xt->crypt) { - fz_filter *cf; - pdf_cryptstm(&cf, xt->crypt, oid, gid); - fz_newpipeline(&filter, cf, filter); - } - - if (encrypt) { - fz_filter *cf; - pdf_cryptstm(&cf, encrypt, oid, gid); - fz_newpipeline(&filter, filter, cf); - } - - fz_seek(xt->file, ofs); - fz_chainfile(&sf, xt->file, filter); - while (1) - { - n = fz_read(sf, buf, sizeof buf); - if (n == 0) - break; - if (n < 0) - fz_abort(fz_ferror(sf)); - fwrite(buf, 1, n, out); - } - fz_unchainfile(sf); - - /* the end */ - fprintf(out, "endstream\nendobj\n\n"); -} - -void deleteobject(int oid, int gid) -{ - uselist[oid] = 0; -} - -void saveobject(int oid, int gid) +void expandstreams(pdf_xref *xref) { fz_error *error; - fz_obj *obj; - fz_obj *t; + fz_obj *stmobj; int stmofs; + fz_buffer *buf; + fz_obj *stmlen; + int i, gen; - error = pdf_loadobj(&obj, xt, oid, gid, &stmofs); - if (error) fz_abort(error); - - /* trash ObjStm and XrefStm objects */ - if (fz_isdict(obj)) { - t = fz_dictgets(obj, "Type"); - if (fz_isname(t) && strcmp(fz_toname(t), "ObjStm") == 0) { - deleteobject(oid, gid); - fz_dropobj(obj); - return; - } - if (fz_isname(t) && strcmp(fz_toname(t), "XRef") == 0) { - deleteobject(oid, gid); - fz_dropobj(obj); - return; + for (i = 0; i < xref->size; i++) + { + if (xref->table[i].type == 'n') + { + gen = xref->table[i].gen; + + error = pdf_loadobject0(&stmobj, xref, i, gen, &stmofs); + if (error) fz_abort(error); + + if (stmofs != -1) + { + error = pdf_readstream0(&buf, xref, stmobj, i, gen, stmofs); + if (error) fz_abort(error); + + fz_dictdels(stmobj, "Filter"); + fz_dictdels(stmobj, "DecodeParms"); + + error = fz_newint(&stmlen, buf->wp - buf->rp); + if (error) fz_abort(error); + error = fz_dictputs(stmobj, "Length", stmlen); + if (error) fz_abort(error); + fz_dropobj(stmlen); + + error = pdf_saveobject(xref, i, gen, stmobj); + if (error) fz_abort(error); + error = pdf_savestream(xref, i, gen, buf); + if (error) fz_abort(error); + } } } - - if (encrypt) - pdf_cryptobj(encrypt, obj, oid, gid); - - if (stmofs == -1) { - fprintf(out, "%d %d obj\n", oid, gid); - printobj(out, obj); - fprintf(out, "\nendobj\n\n"); - } - else if (doexpand) { - decodestream(obj, stmofs, oid, gid); - } - else { - savestream(obj, stmofs, oid, gid); - } - - fz_dropobj(obj); -} - -void savexref(void) -{ - fz_obj *newtrailer; - fz_obj *obj; - int startxref; - int i; - - startxref = ftell(out); - - fprintf(out, "xref\n0 %d\n", xt->size); - for (i = 0; i < xt->size; i++) { - if (uselist[i]) - fprintf(out, "%010d %05d n \n", ofslist[i], genlist[i]); - else - fprintf(out, "%010d %05d f \n", ofslist[i], genlist[i]); - } - fprintf(out, "\n"); - - fz_newdict(&newtrailer, 5); - - fz_newint(&obj, xt->size); - fz_dictputs(newtrailer, "Size", obj); - fz_dropobj(obj); - - obj = fz_dictgets(xt->trailer, "Info"); - if (obj) fz_dictputs(newtrailer, "Info", obj); - - obj = fz_dictgets(xt->trailer, "Root"); - if (obj) fz_dictputs(newtrailer, "Root", obj); - - fz_dictputs(newtrailer, "ID", id); - - if (encryptdict) { - fz_newindirect(&obj, xt->size - 1, 0); - fz_dictputs(newtrailer, "Encrypt", obj); - fz_dropobj(obj); - } - - fprintf(out, "trailer\n"); - printobj(out, newtrailer); - fprintf(out, "\n\n"); - - fprintf(out, "startxref\n%d\n%%%%EOF\n", startxref); } int main(int argc, char **argv) { fz_error *error; - fz_obj *obj; - int lastfree; - char *filename; - int i; + char *infile; + char *outfile; + pdf_xref *xref; int c; int doencrypt = 0; - char *password = ""; + int dorepair = 0; + int doexpand = 0; + int dogc = 0; + char *userpw = ""; char *ownerpw = ""; int perms = -4; /* 0xfffffffc */ int keylen = 40; + char *password = ""; - while (1) + while ((c = getopt(argc, argv, "rgxd:eu:o:p:n:")) != -1) { - c = getopt(argc, argv, "rcxgeu:o:p:n:d:"); - - if (c == -1) - break; - switch (c) { - case 'r': - dorebuild ++; - break; - case 'x': - doexpand ++; - break; - case 'g': - dogc ++; - break; - case 'c': - printobj = fz_fprintcobj; - break; - case 'd': - password = optarg; - break; - case 'e': - doencrypt ++; - break; - case 'u': - userpw = optarg; - break; - case 'o': - ownerpw = optarg; - break; - case 'p': - perms = atoi(optarg); - break; - case 'n': - keylen = atoi(optarg); - break; - default: - usage(); + case 'r': ++ dorepair; break; + case 'x': ++ doexpand; break; + case 'g': ++ dogc; break; + case 'e': ++ doencrypt; break; + case 'u': userpw = optarg; break; + case 'o': ownerpw = optarg; break; + case 'p': perms = atoi(optarg); break; + case 'n': keylen = atoi(optarg); break; + case 'd': password = optarg; break; + default: usage(); } } - if (argc - optind != 2) + if (argc - optind < 2) usage(); - filename = argv[optind]; + infile = argv[optind++]; + outfile = argv[optind++]; - if (dorebuild) - error = pdf_rebuildxref(&xt, filename); - else - error = pdf_openxref(&xt, filename); - if (error) fz_abort(error); - - if (doencrypt && keylen > 40 && xt->version < 1.4) - xt->version = 1.4; - - id = fz_dictgets(xt->trailer, "ID"); - obj = fz_dictgets(xt->trailer, "Encrypt"); - if (fz_isindirect(obj)) { - pdf_loadindirect(&obj, xt, obj, nil); - } - if (obj && id) { - pdf_newdecrypt(&xt->crypt, obj, id); - error = pdf_setpassword(xt->crypt, password); - if (error) fz_abort(error); - } - - id = fz_dictgets(xt->trailer, "ID"); - if (!id) - fz_parseobj(&id, "[ (foobar) (foobar) ]"); - - if (doencrypt) - pdf_newencrypt(&encrypt, &encryptdict, userpw, ownerpw, perms, keylen, id); - - out = fopen(argv[optind + 1], "w"); - if (!out) { - fz_abort(fz_throw("open(%s): %s", argv[optind + 1], strerror(errno))); - } - - fprintf(out, "%%PDF-%.1f\n\n", xt->version); - - ofslist = fz_malloc(sizeof(int) * (xt->size + 1)); - genlist = fz_malloc(sizeof(int) * (xt->size + 1)); - uselist = fz_malloc(sizeof(int) * (xt->size + 1)); - - lastfree = 0; - - ofslist[0] = 0; - genlist[0] = 65535; - uselist[0] = 0; - - for (i = 1; i < xt->size; i++) { - ofslist[i] = 0; - genlist[i] = 0; - uselist[i] = 1; - } + error = pdf_newxref(&xref); + if (error) + fz_abort(error); - /* garbage collect from roots in trailer */ - if (dogc) - { - for (i = 1; i < xt->size; i++) - uselist[i] = 0; - - obj = fz_dictgets(xt->trailer, "Info"); - if (fz_isindirect(obj)) - garbagecollect(obj); - - obj = fz_dictgets(xt->trailer, "Root"); - if (fz_isindirect(obj)) - garbagecollect(obj); + if (dorepair) + error = pdf_repairxref(xref, infile); + else + error = pdf_openxref(xref, infile); + if (error) + fz_abort(error); - obj = fz_dictgets(xt->trailer, "ID"); - if (fz_isindirect(obj)) - garbagecollect(obj); - } + error = pdf_decryptxref(xref); + if (error) + fz_abort(error); - /* pretty print objects */ - for (i = 0; i < xt->size; i++) + if (xref->crypt) { - if (xt->table[i].type == 0) - uselist[i] = 0; - - if (xt->table[i].type == 0) - genlist[i] = xt->table[i].gen; - if (xt->table[i].type == 1) - genlist[i] = xt->table[i].gen; - if (xt->table[i].type == 2) - genlist[i] = 0; - - if (dogc && !uselist[i]) - continue; - - if (xt->table[i].type == 1 || xt->table[i].type == 2) - { - ofslist[i] = ftell(out); - saveobject(i, genlist[i]); - } - } - - /* add encryption dictionary if we crypted */ - if (encryptdict) { - xt->size ++; - ofslist[xt->size - 1] = ftell(out); - genlist[xt->size - 1] = 0; - uselist[xt->size - 1] = 1; - fprintf(out, "%d %d obj\n", xt->size - 1, 0); - printobj(out, encryptdict); - fprintf(out, "\nendobj\n\n"); - } - - /* construct linked list of free object slots */ - lastfree = 0; - for (i = 1; i < xt->size; i++) { - if (!uselist[i]) { - genlist[i] ++; - ofslist[lastfree] = i; - lastfree = i; - } + error = pdf_setpassword(xref->crypt, password); + if (error) fz_abort(error); } - savexref(); + if (doexpand) + expandstreams(xref); - pdf_closexref(xt); +printf("saving %s...\n", outfile); + error = pdf_savepdf(xref, outfile); + if (error) + fz_abort(error); - fclose(out); + pdf_closexref(xref); return 0; } diff --git a/test/pdfdebug.c b/test/pdfdebug.c index d63a720c..ddc10dff 100644 --- a/test/pdfdebug.c +++ b/test/pdfdebug.c @@ -5,11 +5,10 @@ static char *password = ""; static int dodecode = 0; static int dorepair = 0; static int doprintxref = 0; -static int doprintpages = 0; void usage() { - fprintf(stderr, "usage: mupdf [-drxp] [-u password] file.pdf\n"); + fprintf(stderr, "usage: pdfdebug [-drx] [-u password] file.pdf [oid ...]\n"); exit(1); } @@ -127,114 +126,11 @@ void printobject(pdf_xref *xref, int oid, int gid) fz_dropobj(obj); } -/* - * Draw page - */ - -void runcsi(pdf_xref *xref, pdf_csi *csi, pdf_resources *rdb, fz_obj *stmref) -{ - fz_error *error; - - error = pdf_openstream(xref, stmref); - if (error) fz_abort(error); - - error = pdf_runcsi(csi, rdb, xref->file); - if (error) fz_abort(error); - - pdf_closestream(xref); -} - -void showpage(pdf_xref *xref, fz_obj *page) -{ - fz_error *error; - pdf_csi *csi; - pdf_resources *rdb = nil; - fz_obj *resources; - fz_obj *contents; - int i; - - fz_debugobj(page); - printf("\n"); - - resources = fz_dictgets(page, "Resources"); - if (resources) - { - error = pdf_resolve(&resources, xref); - if (error) fz_abort(error); - - error = pdf_loadresources(&rdb, xref, resources); - if (error) fz_abort(error); - - // parse resources into native res dict - fz_dropobj(resources); - } - else - fz_abort(fz_throw("syntaxerror: missing resource dictionary")); - -printf("resources:\n"); -printf(" font:\n"); -fz_debugobj(rdb->font); -printf("\n extgstate:\n"); -fz_debugobj(rdb->extgstate); -printf("\nfitz tree:\n"); - - error = pdf_newcsi(&csi); - if (error) fz_abort(error); - - contents = fz_dictgets(page, "Contents"); - if (contents) - { - if (fz_isarray(contents)) - { - for (i = 0; i < fz_arraylen(contents); i++) - { - runcsi(xref, csi, rdb, fz_arrayget(contents, i)); - } - } - else - { - // XXX resolve and check if it is an array - runcsi(xref, csi, rdb, contents); - } - } - - fz_debugtree(csi->tree); - - { - fz_pixmap *pix; - fz_renderer *gc; - fz_matrix ctm; - -#define W 612 -#define H 792 - -#define xW 1106 -#define xH 1548 - - fz_newrenderer(&gc); - fz_newpixmap(&pix, 0, 0, W, H, 1, 0); - ctm = fz_concat(fz_translate(0, -H), fz_scale(1,-1)); - - memset(pix->samples, 0x00, pix->stride * pix->h * 2); - -printf("rendering!\n"); - fz_rendernode(gc, csi->tree->root, ctm, pix); -printf("done!\n"); - fz_debugpixmap(pix); - - fz_freepixmap(pix); - fz_freerenderer(gc); - } - - pdf_freecsi(csi); -} - int main(int argc, char **argv) { fz_error *error; char *filename; pdf_xref *xref; - pdf_pagetree *pages; int c; while ((c = getopt(argc, argv, "drxopu:")) != -1) @@ -250,9 +146,6 @@ int main(int argc, char **argv) case 'x': doprintxref ++; break; - case 'p': - doprintpages ++; - break; case 'u': password = optarg; break; @@ -290,48 +183,19 @@ int main(int argc, char **argv) if (doprintxref) pdf_debugxref(xref); - if (doprintpages) + if (optind == argc) { - error = pdf_loadpagetree(&pages, xref); - if (error) fz_abort(error); - - if (optind == argc) - { - printf("pagetree\n"); - pdf_debugpagetree(pages); - printf("\n"); - } - else - { - for ( ; optind < argc; optind++) - { - int page = atoi(argv[optind]); - if (page < 1 || page > pages->count) - fprintf(stderr, "page out of bounds: %d\n", page); - printf("page %d\n", page); - showpage(xref, pages->pobj[page - 1]); - } - } + printf("trailer\n"); + fz_debugobj(xref->trailer); + printf("\n"); } - else + for ( ; optind < argc; optind++) { - if (optind == argc) - { - printf("trailer\n"); - fz_debugobj(xref->trailer); - printf("\n"); - } - - for ( ; optind < argc; optind++) - { - printobject(xref, atoi(argv[optind]), 0); - printf("\n"); - } + printobject(xref, atoi(argv[optind]), 0); + printf("\n"); } -printf("done.\n"); - pdf_closexref(xref); return 0; |