aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog5
-rw-r--r--manual/qpdf-manual.xml62
-rw-r--r--qpdf/qpdf.cc42
-rw-r--r--qpdf/qtest/qpdf.test18
-rw-r--r--qpdf/qtest/qpdf/completion-encrypt-128.out1
-rw-r--r--qpdf/qtest/qpdf/completion-encrypt-256.out1
6 files changed, 120 insertions, 9 deletions
diff --git a/ChangeLog b/ChangeLog
index 1feaffb0..8f1ed679 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -16,6 +16,11 @@
2019-01-14 Jay Berkenbilt <ejb@ql.org>
+ * Add new CLI flags to 128-bit and 256-bit encryption: --assemble,
+ --annotate, --form, and --modify-other to control encryption
+ permissions with more granularity than was allowed with the
+ --modify flag. Fixes #214.
+
* Add new versions of
QPDFWriter::setR{3,4,5,6}EncryptionParameters that allow
individual setting of the various permission bits. The old
diff --git a/manual/qpdf-manual.xml b/manual/qpdf-manual.xml
index 034111c2..c3d62814 100644
--- a/manual/qpdf-manual.xml
+++ b/manual/qpdf-manual.xml
@@ -786,7 +786,12 @@ make
<listitem>
<para>
Determines whether or not to allow accessibility to visually
- impaired.
+ impaired. The qpdf library disregards this field when AES is
+ used or when 256-bit encryption is used. You should really
+ never disable accessibility, but qpdf lets you do it in case
+ you need to configure a file this way for testing purposes.
+ The PDF spec says that conforming readers should disregard
+ this permission and always allow accessibility.
</para>
</listitem>
</varlistentry>
@@ -799,6 +804,45 @@ make
</listitem>
</varlistentry>
<varlistentry>
+ <term><option>--assemble=[yn]</option></term>
+ <listitem>
+ <para>
+ Determines whether document assembly (rotation and reordering
+ of pages) is allowed.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--annotate=[yn]</option></term>
+ <listitem>
+ <para>
+ Determines whether modifying annotations is allowed. This
+ includes adding comments and filling in form fields. Also
+ allows editing of form fields if
+ <option>--modify-other=y</option> is given.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--form=[yn]</option></term>
+ <listitem>
+ <para>
+ Determines whether filling form fields is allowed.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>--modify-other=[yn]</option></term>
+ <listitem>
+ <para>
+ Allow all document editing except those controlled separately
+ by the <option>--assemble</option>,
+ <option>--annotate</option>, and <option>--form</option>
+ options.
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
<term><option>--print=<replaceable>print-opt</replaceable></option></term>
<listitem>
<para>
@@ -829,10 +873,10 @@ make
<term><option>--modify=<replaceable>modify-opt</replaceable></option></term>
<listitem>
<para>
- Controls modify access.
+ Controls modify access. This way of controlling modify access
+ has less granularity than new options added in qpdf 8.4.
<option><replaceable>modify-opt</replaceable></option> may be
- one of the following, each of which implies all the options
- that follow it:
+ one of the following:
<itemizedlist>
<listitem>
<para>
@@ -841,12 +885,14 @@ make
</listitem>
<listitem>
<para>
- <option>annotate</option>: allow comment authoring and form operations
+ <option>annotate</option>: allow comment authoring, form
+ operations, and document assembly
</para>
</listitem>
<listitem>
<para>
<option>form</option>: allow form field fill-in and signing
+ and document assembly
</para>
</listitem>
<listitem>
@@ -860,6 +906,12 @@ make
</para>
</listitem>
</itemizedlist>
+ Using the <option>--modify</option> option does not allow you
+ to create certain combinations of permissions such as allowing
+ form filling but not allowing document assembly. Starting with
+ qpdf 8.4, you can either just use the other options to control
+ fields individually, or you can use something like
+ <option>--modify=form --assembly=n</option> to fine tune.
</para>
</listitem>
</varlistentry>
diff --git a/qpdf/qpdf.cc b/qpdf/qpdf.cc
index 23ca3d10..c0e52a1c 100644
--- a/qpdf/qpdf.cc
+++ b/qpdf/qpdf.cc
@@ -631,6 +631,10 @@ class ArgParser
void arg128Print(char* parameter);
void arg128Modify(char* parameter);
void arg128ClearTextMetadata();
+ void arg128Assemble(char* parameter);
+ void arg128Annotate(char* parameter);
+ void arg128Form(char* parameter);
+ void arg128ModOther(char* parameter);
void arg128UseAes(char* parameter);
void arg128ForceV4();
void arg256ForceR5();
@@ -857,11 +861,16 @@ ArgParser::initOptionTable()
char const* print128_choices[] = {"full", "low", "none", 0};
(*t)["print"] = oe_requiredChoices(
&ArgParser::arg128Print, print128_choices);
+ (*t)["assemble"] = oe_requiredChoices(&ArgParser::arg128Assemble, yn);
+ (*t)["annotate"] = oe_requiredChoices(&ArgParser::arg128Annotate, yn);
+ (*t)["form"] = oe_requiredChoices(&ArgParser::arg128Form, yn);
+ (*t)["modify-other"] = oe_requiredChoices(&ArgParser::arg128ModOther, yn);
char const* modify128_choices[] =
{"all", "annotate", "form", "assembly", "none", 0};
(*t)["modify"] = oe_requiredChoices(
&ArgParser::arg128Modify, modify128_choices);
(*t)["cleartext-metadata"] = oe_bare(&ArgParser::arg128ClearTextMetadata);
+
// The above 128-bit options are also 256-bit options, so copy
// what we have so far. Then continue separately with 128 and 256.
this->encrypt256_option_table = this->encrypt128_option_table;
@@ -1048,7 +1057,11 @@ ArgParser::argHelp()
<< " --accessibility=[yn] allow accessibility to visually impaired\n"
<< " --extract=[yn] allow other text/graphic extraction\n"
<< " --print=print-opt control printing access\n"
- << " --modify=modify-opt control modify access\n"
+ << " --assemble=[yn] allow document assembly\n"
+ << " --annotate=[yn] allow commenting/filling form fields\n"
+ << " --form=[yn] allow filling form fields\n"
+ << " --modify-other=[yn] allow other modifications\n"
+ << " --modify=modify-opt control modify access (old way)\n"
<< " --cleartext-metadata prevents encryption of metadata\n"
<< " --use-aes=[yn] indicates whether to use AES encryption\n"
<< " --force-V4 forces use of V=4 encryption handler\n"
@@ -1072,7 +1085,8 @@ ArgParser::argHelp()
<< " assembly allow document assembly only\n"
<< " none allow no modifications\n"
<< "\n"
- << "The default for each permission option is to be fully permissive.\n"
+ << "The default for each permission option is to be fully permissive. Please\n"
+ << "refer to the manual for more details on the modify options.\n"
<< "\n"
<< "Specifying cleartext-metadata forces the PDF version to at least 1.5.\n"
<< "Specifying use of AES forces the PDF version to at least 1.6. These\n"
@@ -1915,6 +1929,30 @@ ArgParser::arg128ClearTextMetadata()
}
void
+ArgParser::arg128Assemble(char* parameter)
+{
+ o.r3_assemble = (strcmp(parameter, "y") == 0);
+}
+
+void
+ArgParser::arg128Annotate(char* parameter)
+{
+ o.r3_annotate_and_form = (strcmp(parameter, "y") == 0);
+}
+
+void
+ArgParser::arg128Form(char* parameter)
+{
+ o.r3_form_filling = (strcmp(parameter, "y") == 0);
+}
+
+void
+ArgParser::arg128ModOther(char* parameter)
+{
+ o.r3_modify_other = (strcmp(parameter, "y") == 0);
+}
+
+void
ArgParser::arg128UseAes(char* parameter)
{
o.use_aes = (strcmp(parameter, "y") == 0);
diff --git a/qpdf/qtest/qpdf.test b/qpdf/qtest/qpdf.test
index 44aa5421..45f2a6f4 100644
--- a/qpdf/qtest/qpdf.test
+++ b/qpdf/qtest/qpdf.test
@@ -2687,6 +2687,24 @@ my @encrypted_files =
['R3,V2,U=view,O=master', 'master',
'-accessibility=n -print=low', -2564,
0, 1, 1, 0, 1, 1, 1, 1, 1],
+ ['R3,V2,U=view,O=master', 'master',
+ '-modify=all -assemble=n', -1028,
+ 1, 1, 1, 1, 0, 1, 1, 1, 0],
+ ['R3,V2,U=view,O=master', 'master',
+ '-modify=none -form=y', -1068,
+ 1, 1, 1, 1, 0, 1, 0, 0, 0],
+ ['R3,V2,U=view,O=master', 'master',
+ '-modify=annotate -assemble=n', -1036,
+ 1, 1, 1, 1, 0, 1, 1, 0, 0],
+ ['R3,V2,U=view,O=master', 'master',
+ '-form=n', -260,
+ 1, 1, 1, 1, 1, 0, 1, 1, 0],
+ ['R3,V2,U=view,O=master', 'master',
+ '-annotate=n', -36,
+ 1, 1, 1, 1, 1, 1, 0, 1, 0],
+ ['R3,V2,U=view,O=master', 'master',
+ '-modify-other=n', -12,
+ 1, 1, 1, 1, 1, 1, 1, 0, 0],
['R2,V1', '',
'-print=n -modify=n -extract=n -annotate=n', -64,
0, 0, 0, 0, 0, 0, 0, 0, 0],
diff --git a/qpdf/qtest/qpdf/completion-encrypt-128.out b/qpdf/qtest/qpdf/completion-encrypt-128.out
index 2c51a616..b16bce76 100644
--- a/qpdf/qtest/qpdf/completion-encrypt-128.out
+++ b/qpdf/qtest/qpdf/completion-encrypt-128.out
@@ -1,3 +1,2 @@
--force-V4
-!--annotate=
!--force-R5
diff --git a/qpdf/qtest/qpdf/completion-encrypt-256.out b/qpdf/qtest/qpdf/completion-encrypt-256.out
index 7033fbab..6521d2a2 100644
--- a/qpdf/qtest/qpdf/completion-encrypt-256.out
+++ b/qpdf/qtest/qpdf/completion-encrypt-256.out
@@ -1,3 +1,2 @@
--force-R5
-!--annotate=
!--force-V4