summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin Watts <Robin.Watts@artifex.com>2011-06-14 17:00:04 +0100
committerRobin Watts <Robin.Watts@artifex.com>2011-06-14 17:00:04 +0100
commitcbf50e333dc1e80cd968c5ee931b4d6886b116a4 (patch)
tree03ca5709d081197b76e904947e0e8b570d5b9c6d
parentff0b19b58d678ee3ed8e8da58dc4e7641e1bb922 (diff)
downloadmupdf-cbf50e333dc1e80cd968c5ee931b4d6886b116a4.tar.xz
Fix Bug 692277: PDF file won't open.
Acrobat (and gs, see bug 690478) will open a file without a CF dictionary by assuming that the encryption type is RC4. Mirror this in mupdf.
-rw-r--r--pdf/pdf_crypt.c90
1 files changed, 49 insertions, 41 deletions
diff --git a/pdf/pdf_crypt.c b/pdf/pdf_crypt.c
index f05b7366..5cbe6678 100644
--- a/pdf/pdf_crypt.c
+++ b/pdf/pdf_crypt.c
@@ -40,7 +40,7 @@ struct pdf_crypt_s
unsigned char key[32]; /* decryption key generated from password */
};
-static fz_error pdf_parse_crypt_filter(pdf_crypt_filter *cf, fz_obj *dict, int defaultlength);
+static fz_error pdf_parse_crypt_filter(pdf_crypt_filter *cf, fz_obj *dict, char *name, int defaultlength);
/*
* Create crypt object for decrypting strings and streams
@@ -129,43 +129,37 @@ pdf_new_crypt(pdf_crypt **cryptp, fz_obj *dict, fz_obj *id)
if (fz_is_dict(obj))
{
crypt->cf = fz_keep_obj(obj);
+ }
+ else
+ {
+ crypt->cf = NULL;
+ }
- obj = fz_dict_gets(dict, "StmF");
- if (fz_is_name(obj))
+ obj = fz_dict_gets(dict, "StmF");
+ if (fz_is_name(obj))
+ {
+ error = pdf_parse_crypt_filter(&crypt->stmf, crypt->cf, fz_to_name(obj), crypt->length);
+ if (error)
{
- /* should verify that it is either Identity or StdCF */
- obj = fz_dict_gets(crypt->cf, fz_to_name(obj));
- if (fz_is_dict(obj))
- {
- error = pdf_parse_crypt_filter(&crypt->stmf, obj, crypt->length);
- if (error)
- {
- pdf_free_crypt(crypt);
- return fz_rethrow(error, "cannot parse stream crypt filter (%d %d R)", fz_to_num(obj), fz_to_gen(obj));
- }
- }
+ pdf_free_crypt(crypt);
+ return fz_rethrow(error, "cannot parse stream crypt filter (%d %d R)", fz_to_num(obj), fz_to_gen(obj));
}
+ }
- obj = fz_dict_gets(dict, "StrF");
- if (fz_is_name(obj))
+ obj = fz_dict_gets(dict, "StrF");
+ if (fz_is_name(obj))
+ {
+ error = pdf_parse_crypt_filter(&crypt->strf, crypt->cf, fz_to_name(obj), crypt->length);
+ if (error)
{
- /* should verify that it is either Identity or StdCF */
- obj = fz_dict_gets(crypt->cf, fz_to_name(obj));
- if (fz_is_dict(obj))
- {
- error = pdf_parse_crypt_filter(&crypt->strf, obj, crypt->length);
- if (error)
- {
- pdf_free_crypt(crypt);
- return fz_rethrow(error, "cannot parse string crypt filter (%d %d R)", fz_to_num(obj), fz_to_gen(obj));
- }
- }
+ pdf_free_crypt(crypt);
+ return fz_rethrow(error, "cannot parse string crypt filter (%d %d R)", fz_to_num(obj), fz_to_gen(obj));
}
-
- /* in crypt revision 4, the crypt filter determines the key length */
- if (crypt->strf.method != PDF_CRYPT_NONE)
- crypt->length = crypt->stmf.length;
}
+
+ /* in crypt revision 4, the crypt filter determines the key length */
+ if (crypt->strf.method != PDF_CRYPT_NONE)
+ crypt->length = crypt->stmf.length;
}
/* Standard security handler (PDF 1.7 table 3.19) */
@@ -270,13 +264,31 @@ pdf_free_crypt(pdf_crypt *crypt)
*/
static fz_error
-pdf_parse_crypt_filter(pdf_crypt_filter *cf, fz_obj *dict, int defaultlength)
+pdf_parse_crypt_filter(pdf_crypt_filter *cf, fz_obj *cf_obj, char *name, int defaultlength)
{
fz_obj *obj;
+ fz_obj *dict;
+ int is_identity = (strcmp(name, "Identity") == 0);
+ int is_stdcf = (!is_identity && (strcmp(name, "StdCF") == 0));
+ if (!is_identity && !is_stdcf)
+ {
+ return fz_throw("Crypt Filter not Identity or StdCF (%d %d R)", fz_to_num(cf_obj), fz_to_gen(cf_obj));
+ }
cf->method = PDF_CRYPT_NONE;
cf->length = defaultlength;
+ if (cf_obj == NULL)
+ {
+ cf->method = (is_identity ? PDF_CRYPT_NONE : PDF_CRYPT_RC4);
+ return fz_okay;
+ }
+
+ dict = fz_dict_gets(cf_obj, name);
+ if (fz_is_dict(dict))
+ {
+ return fz_throw("cannot parse crypt filter (%d %d R)", fz_to_num(cf_obj), fz_to_gen(cf_obj));
+ }
obj = fz_dict_gets(dict, "CFM");
if (fz_is_name(obj))
{
@@ -805,15 +817,11 @@ pdf_open_crypt_with_filter(fz_stream *chain, pdf_crypt *crypt, char *name, int n
if (strcmp(name, "Identity"))
{
- fz_obj *obj = fz_dict_gets(crypt->cf, name);
- if (fz_is_dict(obj))
- {
- error = pdf_parse_crypt_filter(&cf, obj, crypt->length);
- if (error)
- fz_catch(error, "cannot parse crypt filter (%d %d R)", fz_to_num(obj), fz_to_gen(obj));
- else
- return pdf_open_crypt_imp(chain, crypt, &cf, num, gen);
- }
+ error = pdf_parse_crypt_filter(&cf, crypt->cf, name, crypt->length);
+ if (error)
+ fz_catch(error, "cannot parse crypt filter (%d %d R)", num, gen);
+ else
+ return pdf_open_crypt_imp(chain, crypt, &cf, num, gen);
}
return chain;
}