diff options
-rw-r--r-- | filter/filec.c | 13 | ||||
-rw-r--r-- | filter/filter.c | 26 | ||||
-rw-r--r-- | include/mupdf.h | 5 | ||||
-rw-r--r-- | mupdf/crypt.c | 23 | ||||
-rw-r--r-- | mupdf/save.c | 92 | ||||
-rw-r--r-- | test/pdfclean.c | 16 |
6 files changed, 122 insertions, 53 deletions
diff --git a/filter/filec.c b/filter/filec.c index 8402401f..a8a26008 100644 --- a/filter/filec.c +++ b/filter/filec.c @@ -148,13 +148,19 @@ fz_pushfilter(fz_file *file, fz_filter *filter) file->out = file->in; file->in = buf; -// XXX if (file->mode == O_RDONLY) { file->out->rp = file->out->bp; file->out->wp = file->out->bp; file->out->eof = 0; } + else + { + file->out->eof = 0; + file->in->rp = file->in->bp; + file->in->wp = file->in->bp; + file->in->eof = 0; + } file->filter = filter; } @@ -220,11 +226,6 @@ fz_popfilter(fz_file *file) buf = file->out; file->out = file->in; file->in = buf; - -// XXX - file->in->rp = file->in->bp; - file->in->wp = file->in->bp; - file->in->eof = 0; } else { diff --git a/filter/filter.c b/filter/filter.c index 8e28a532..68dd70b9 100644 --- a/filter/filter.c +++ b/filter/filter.c @@ -1,28 +1,8 @@ #include <fitz.h> -fz_error fz_kioneedin = { - .msg = {"<ioneedin>"}, - .func = {"<process>"}, - .file = {"filter.c"}, - .line = 0, - .frozen = 1 -}; - -fz_error fz_kioneedout = { - .msg = {"<ioneedout>"}, - .func = {"<process>"}, - .file = {"filter.c"}, - .line = 0, - .frozen = 1 -}; - -fz_error fz_kiodone = { - .msg = {"<iodone>"}, - .func = {"<process>"}, - .file = {"filter.c"}, - .line = 0, - .frozen = 1 -}; +fz_error fz_kioneedin = { "<ioneedin>", "<process>", "filter.c", 0, 1 }; +fz_error fz_kioneedout = { "<ioneedout>", "<process>", "filter.c", 0, 1 }; +fz_error fz_kiodone = { "<iodone>", "<process>", "filter.c", 0, 1 }; fz_error * fz_process(fz_filter *f, fz_buffer *in, fz_buffer *out) diff --git a/include/mupdf.h b/include/mupdf.h index 3f8b242c..69dc248f 100644 --- a/include/mupdf.h +++ b/include/mupdf.h @@ -70,6 +70,7 @@ struct pdf_crypt_s int r; int n; + fz_obj *encrypt; fz_obj *id; unsigned char key[16]; @@ -86,7 +87,7 @@ 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); -fz_error *pdf_newencrypt(pdf_crypt **cp, fz_obj **edict, char *userpw, char *ownerpw, int p, int n, fz_obj *id); +fz_error *pdf_newencrypt(pdf_crypt **cp, char *userpw, char *ownerpw, int p, int n, fz_obj *id); fz_error *pdf_setpassword(pdf_crypt *crypt, char *pw); fz_error *pdf_cryptstm(fz_filter **fp, pdf_crypt *crypt, int oid, int gid); void pdf_cryptobj(pdf_crypt *crypt, fz_obj *obj, int oid, int gid); @@ -127,7 +128,7 @@ fz_error *pdf_garbagecollect(pdf_xref *xref); /* save.c */ fz_error *pdf_saveincrementalpdf(pdf_xref *xref, char *path); -fz_error *pdf_savepdf(pdf_xref *xref, char *path); +fz_error *pdf_savepdf(pdf_xref *xref, char *path, pdf_crypt *encrypt); /* * high-level semantic objects for resources and pages diff --git a/mupdf/crypt.c b/mupdf/crypt.c index 730c0bd5..903176fe 100644 --- a/mupdf/crypt.c +++ b/mupdf/crypt.c @@ -61,6 +61,9 @@ pdf_newdecrypt(pdf_crypt **cp, fz_obj *enc, fz_obj *id) crypt = *cp = fz_malloc(sizeof(pdf_crypt)); if (!crypt) return fz_outofmem; + crypt->encrypt = fz_keepobj(enc); + crypt->id = nil; + obj = fz_dictgets(enc, "O"); if (!fz_isstring(obj) || fz_tostringlen(obj) != 32) goto cleanup; @@ -116,7 +119,8 @@ cleanup: void pdf_freecrypt(pdf_crypt *crypt) { - fz_dropobj(crypt->id); + if (crypt->encrypt) fz_dropobj(crypt->encrypt); + if (crypt->id) fz_dropobj(crypt->id); fz_free(crypt); } @@ -262,15 +266,17 @@ createuser(pdf_crypt *crypt, char *userpw) } fz_error * -pdf_newencrypt(pdf_crypt **cp, fz_obj **dict, +pdf_newencrypt(pdf_crypt **cp, char *userpw, char *ownerpw, int p, int n, fz_obj *id) { fz_error *error; pdf_crypt *crypt; crypt = *cp = fz_malloc(sizeof(pdf_crypt)); - if (!crypt) return fz_outofmem; + if (!crypt) + return fz_outofmem; + crypt->encrypt = nil; crypt->id = fz_keepobj(fz_arrayget(id, 0)); crypt->p = p; crypt->n = MIN(MAX(n / 8, 5), 16); @@ -280,7 +286,7 @@ pdf_newencrypt(pdf_crypt **cp, fz_obj **dict, createowner(crypt, userpw, ownerpw); createuser(crypt, userpw); - error = fz_packobj(dict, + error = fz_packobj(&crypt->encrypt, "<< /Filter /Standard " "/V %i /R %i " "/O %# /U %# " @@ -292,7 +298,14 @@ pdf_newencrypt(pdf_crypt **cp, fz_obj **dict, crypt->u, 32, crypt->p, crypt->n * 8); - return error; + if (error) + { + pdf_freecrypt(crypt); + return error; + } + + *cp = crypt; + return nil; } /* diff --git a/mupdf/save.c b/mupdf/save.c index 32dda709..36695dd4 100644 --- a/mupdf/save.c +++ b/mupdf/save.c @@ -3,30 +3,54 @@ #define TIGHT 0 -static fz_error *writestored(fz_file *out, pdf_xref *xref, int oid) +static fz_error * +writestored(fz_file *out, pdf_xref *xref, pdf_crypt *encrypt, int oid) { pdf_xrefentry *x = xref->table + oid; fz_error *error; fz_obj *obj; fz_buffer *stm; + fz_filter *filter; + int gid; - obj = pdf_findstoredobject(xref->store, oid, x->gen); - stm = pdf_findstoredstream(xref->store, oid, x->gen); + gid = x->gen; + if (x->type == 'o') + gid = 0; + + obj = pdf_findstoredobject(xref->store, oid, gid); + stm = pdf_findstoredstream(xref->store, oid, gid); if (!obj) return fz_throw("could not find stored object"); - if (xref->crypt) - pdf_cryptobj(xref->crypt, obj, oid, x->gen); + if (encrypt) + pdf_cryptobj(encrypt, obj, oid, gid); - fz_print(out, "%d %d obj\n", oid, x->gen); + fz_print(out, "%d %d obj\n", oid, gid); fz_printobj(out, obj, TIGHT); fz_print(out, "\n"); if (stm) { fz_print(out, "stream\n"); + + if (encrypt) + { + error = pdf_cryptstm(&filter, encrypt, oid, gid); + if (error) + return error; + error = fz_pushfilter(out, filter); + if (error) { + fz_freefilter(filter); + return error; + } + } + fz_write(out, stm->rp, stm->wp - stm->rp); + + if (encrypt) + fz_popfilter(out); + fz_print(out, "endstream\n"); } @@ -39,7 +63,8 @@ static fz_error *writestored(fz_file *out, pdf_xref *xref, int oid) return nil; } -static fz_error *writecopy(fz_file *out, pdf_xref *xref, int oid) +static fz_error * +writecopy(fz_file *out, pdf_xref *xref, pdf_crypt *encrypt, int oid) { pdf_xrefentry *x = xref->table + oid; fz_error *error; @@ -49,14 +74,23 @@ static fz_error *writecopy(fz_file *out, pdf_xref *xref, int oid) fz_filter *cf; fz_filter *nf; fz_filter *pipe; + fz_filter *ef; + int gid; int n; unsigned char buf[4096]; - error = pdf_loadobject0(&obj, xref, oid, x->gen, &stmofs); + gid = x->gen; + if (x->type == 'o') + gid = 0; + + error = pdf_loadobject0(&obj, xref, oid, gid, &stmofs); if (error) return error; - fz_print(out, "%d %d obj\n", oid, x->gen); + if (encrypt) + pdf_cryptobj(encrypt, obj, oid, gid); + + fz_print(out, "%d %d obj\n", oid, gid); fz_printobj(out, obj, TIGHT); fz_print(out, "\n"); @@ -74,7 +108,7 @@ static fz_error *writecopy(fz_file *out, pdf_xref *xref, int oid) error = fz_newnullfilter(&nf, fz_toint(length)); if (error) goto cleanup; - error = pdf_cryptstm(&cf, xref->crypt, oid, x->gen); + error = pdf_cryptstm(&cf, xref->crypt, oid, gid); if (error) goto cleanup; error = fz_newpipeline(&pipe, nf, cf); @@ -91,6 +125,18 @@ static fz_error *writecopy(fz_file *out, pdf_xref *xref, int oid) fz_seek(xref->file, stmofs); fz_pushfilter(xref->file, pipe); + if (encrypt) + { + error = pdf_cryptstm(&ef, encrypt, oid, gid); + if (error) + return error; + error = fz_pushfilter(out, ef); + if (error) { + fz_freefilter(ef); + goto cleanup; + } + } + while (1) { n = fz_read(xref->file, buf, sizeof buf); @@ -101,10 +147,15 @@ static fz_error *writecopy(fz_file *out, pdf_xref *xref, int oid) error = fz_ferror(xref->file); fz_popfilter(xref->file); goto cleanup; + if (encrypt) + fz_popfilter(out); } fz_write(out, buf, n); } + if (encrypt) + fz_popfilter(out); + fz_popfilter(xref->file); fz_print(out, "endstream\n"); @@ -155,7 +206,7 @@ pdf_saveincrementalpdf(pdf_xref *xref, char *path) if (xref->table[oid].type == 'a') { xref->table[oid].ofs = fz_tell(out); - error = writestored(out, xref, oid); + error = writestored(out, xref, xref->crypt, oid); if (error) goto cleanup; } @@ -234,7 +285,7 @@ cleanup: } fz_error * -pdf_savepdf(pdf_xref *xref, char *path) +pdf_savepdf(pdf_xref *xref, char *path, pdf_crypt *encrypt) { fz_error *error; fz_file *out; @@ -262,14 +313,14 @@ pdf_savepdf(pdf_xref *xref, char *path) if (xref->table[oid].type == 'n' || xref->table[oid].type == 'o') { ofsbuf[oid] = fz_tell(out); - error = writecopy(out, xref, oid); + error = writecopy(out, xref, encrypt, oid); if (error) goto cleanup; } else if (xref->table[oid].type == 'a') { ofsbuf[oid] = fz_tell(out); - error = writestored(out, xref, oid); + error = writestored(out, xref, encrypt, oid); if (error) goto cleanup; } @@ -297,10 +348,19 @@ pdf_savepdf(pdf_xref *xref, char *path) fz_print(out, "trailer\n<<\n /Size %d", xref->size); obj = fz_dictgets(xref->trailer, "Root"); - fz_print(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) - fz_print(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)); + if (encrypt) + { + fz_print(out, "\n /Encrypt "); + fz_printobj(out, encrypt->encrypt, 1); + fz_print(out, "\n /ID ["); + fz_printobj(out, encrypt->id, 1); + fz_printobj(out, encrypt->id, 1); + fz_print(out, "]"); + } fz_print(out, "\n>>\n\n"); fz_print(out, "startxref\n"); diff --git a/test/pdfclean.c b/test/pdfclean.c index 3a111a92..c6af657b 100644 --- a/test/pdfclean.c +++ b/test/pdfclean.c @@ -67,6 +67,7 @@ int main(int argc, char **argv) pdf_xref *xref; int c; + pdf_crypt *encrypt = 0; int doencrypt = 0; int dorepair = 0; int doexpand = 0; @@ -122,13 +123,26 @@ int main(int argc, char **argv) if (error) fz_abort(error); } + if (doencrypt) + { + fz_obj *id = fz_dictgets(xref->trailer, "ID"); + if (!id) + fz_packobj(&id, "[(ABCDEFGHIJKLMNOP)(ABCDEFGHIJKLMNOP)]"); + else + fz_keepobj(id); + error = pdf_newencrypt(&encrypt, userpw, ownerpw, perms, keylen, id); + if (error) + fz_abort(error); + fz_dropobj(id); + } + if (doexpand) expandstreams(xref); if (dogc) pdf_garbagecollect(xref); - error = pdf_savepdf(xref, outfile); + error = pdf_savepdf(xref, outfile, encrypt); if (error) fz_abort(error); |