summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--filter/filec.c13
-rw-r--r--filter/filter.c26
-rw-r--r--include/mupdf.h5
-rw-r--r--mupdf/crypt.c23
-rw-r--r--mupdf/save.c92
-rw-r--r--test/pdfclean.c16
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);