Commit 21b9290785fb03477784cf6312f57cfb96dbe53d

Authored by Jay Berkenbilt
1 parent ea96330b

QPDFJob json: make bare arguments expect the empty string

Changing from bool requiring true to string requiring the empty string
is more consistent with the CLI and makes it possible to add an
optional parameter or choices later without breaking compatibility.
generate_auto_job
... ... @@ -465,14 +465,19 @@ class Main:
465 465 self.json_init.append(
466 466 f'addBare([this]() {{ {config}->{flag_key}(); }});')
467 467 elif kind == 'optional_parameter' or kind == 'required_parameter':
468   - # No optional parameters in json
  468 + # Optional parameters end up just being the empty string,
  469 + # so the handler has to deal with it. The empty string is
  470 + # also allowed for non-optional.
469 471 self.json_init.append(
470 472 f'addParameter([this](char const* p)'
471 473 f' {{ {config}->{flag_key}(p); }});')
472   - elif kind == 'optional_choices' or kind == 'required_choices':
473   - # No optional choices in json
  474 + elif kind == 'optional_choices':
  475 + self.json_init.append(
  476 + f'addChoices({v}_choices, false,'
  477 + f' [this](char const* p) {{ {config}->{flag_key}(p); }});')
  478 + elif kind == 'required_choices':
474 479 self.json_init.append(
475   - f'addChoices({v}_choices,'
  480 + f'addChoices({v}_choices, true,'
476 481 f' [this](char const* p) {{ {config}->{flag_key}(p); }});')
477 482  
478 483 def handle_json_manual(self, path):
... ...
job.sums
1 1 # Generated by generate_auto_job
2   -generate_auto_job 905fed38c06d258af617ac909bed78a7888a5eaba3f14cf143168665f6e90a86
  2 +generate_auto_job 8b3cc47eb96bfd003954d16d51c482e0e015544fdcdc1cbc89b6dcd964f8a2cb
3 3 include/qpdf/auto_job_c_att.hh 7ad43bb374c1370ef32ebdcdcb7b73a61d281f7f4e3f12755585872ab30fb60e
4 4 include/qpdf/auto_job_c_copy_att.hh 32275d03cdc69b703dd7e02ba0bbe15756e714e9ad185484773a6178dc09e1ee
5 5 include/qpdf/auto_job_c_enc.hh 72e138c7b96ed5aacdce78c1dec04b1c20d361faec4f8faf52f64c1d6be99265
... ... @@ -11,7 +11,7 @@ libqpdf/qpdf/auto_job_decl.hh 9f79396ec459f191be4c5fe34cf88c265cf47355a1a945fa39
11 11 libqpdf/qpdf/auto_job_help.hh a0ab6ab4dde2ad3d3f17ecae3ea274919119329e075061f3a3973535f5e367de
12 12 libqpdf/qpdf/auto_job_init.hh c244e03e8b83ed7db732920f40aff0134e5f2e78a6edb9473ea4dd1934a8953e
13 13 libqpdf/qpdf/auto_job_json_decl.hh c5e3fd38a3b0c569eb0c6b4c60953a09cd6bc7d3361a357a81f64fe36af2b0cf
14   -libqpdf/qpdf/auto_job_json_init.hh bfaf88ad1461e1157e7a0eb6e8c90669eba6d03b5b1ffd2e7e7041250c5f0523
  14 +libqpdf/qpdf/auto_job_json_init.hh 3f86ce40931ca8f417d050fcd49104d73c1fa4e977ad19d54b372831a8ea17ed
15 15 libqpdf/qpdf/auto_job_schema.hh 2ec70dffdd15974d74102b4d7ada9f97449bc28c98be119efee5e15507ed22a8
16 16 manual/_ext/qpdf.py e9ac9d6c70642a3d29281ee5ad92ae2422dee8be9306fb8a0bc9dba0ed5e28f3
17 17 manual/cli.rst a75a7e34aa9aba4f06e9c88cae9a2d9a2aa4e55a08521dde1478e8f2d80aadab
... ...
libqpdf/QPDFJob_config.cc
... ... @@ -108,7 +108,7 @@ QPDFJob::Config::coalesceContents()
108 108 QPDFJob::Config*
109 109 QPDFJob::Config::collate(char const* parameter)
110 110 {
111   - auto n = ((parameter == 0) ? 1 :
  111 + auto n = (((parameter == 0) || (strlen(parameter) == 0)) ? 1 :
112 112 QUtil::string_to_uint(parameter));
113 113 o.m->collate = QIntC::to_size(n);
114 114 return this;
... ... @@ -519,7 +519,7 @@ QPDFJob::Config::showXref()
519 519 QPDFJob::Config*
520 520 QPDFJob::Config::splitPages(char const* parameter)
521 521 {
522   - int n = ((parameter == 0) ? 1 :
  522 + int n = (((parameter == 0) || (strlen(parameter) == 0)) ? 1 :
523 523 QUtil::string_to_int(parameter));
524 524 o.m->split_pages = n;
525 525 return this;
... ...
libqpdf/QPDFJob_json.cc
... ... @@ -31,7 +31,7 @@ namespace
31 31  
32 32 void addBare(bare_handler_t);
33 33 void addParameter(param_handler_t);
34   - void addChoices(char const** choices, param_handler_t);
  34 + void addChoices(char const** choices, bool required, param_handler_t);
35 35 void pushKey(std::string const& key);
36 36 void beginDict(json_handler_t start_fn,
37 37 bare_handler_t end_fn);
... ... @@ -106,11 +106,12 @@ Handlers::initHandlers()
106 106 void
107 107 Handlers::addBare(bare_handler_t fn)
108 108 {
109   - jh->addBoolHandler([this, fn](std::string const& path, bool v){
110   - if (! v)
  109 + jh->addStringHandler(
  110 + [this, fn](std::string const& path, std::string const& parameter){
  111 + if (! parameter.empty())
111 112 {
112   - QTC::TC("qpdf", "QPDFJob json bare not true");
113   - usage(path + ": value must be true");
  113 + QTC::TC("qpdf", "QPDFJob json bare not empty");
  114 + usage(path + ": value must be the empty string");
114 115 }
115 116 else
116 117 {
... ... @@ -129,22 +130,28 @@ Handlers::addParameter(param_handler_t fn)
129 130 }
130 131  
131 132 void
132   -Handlers::addChoices(char const** choices,
133   - param_handler_t fn)
  133 +Handlers::addChoices(char const** choices, bool required, param_handler_t fn)
134 134 {
135 135 jh->addStringHandler(
136   - [fn, choices, this](
  136 + [fn, choices, required, this](
137 137 std::string const& path, std::string const& parameter){
138 138  
139 139 char const* p = parameter.c_str();
140 140 bool matches = false;
141   - for (char const** i = choices; *i; ++i)
  141 + if ((! required) && (parameter.empty()))
  142 + {
  143 + matches = true;
  144 + }
  145 + if (! matches)
142 146 {
143   - if (strcmp(*i, p) == 0)
  147 + for (char const** i = choices; *i; ++i)
144 148 {
145   - QTC::TC("qpdf", "QPDFJob json choice match");
146   - matches = true;
147   - break;
  149 + if (strcmp(*i, p) == 0)
  150 + {
  151 + QTC::TC("qpdf", "QPDFJob json choice match");
  152 + matches = true;
  153 + break;
  154 + }
148 155 }
149 156 }
150 157 if (! matches)
... ...
libqpdf/qpdf/auto_job_json_init.hh
... ... @@ -43,19 +43,19 @@ pushKey("newlineBeforeEndstream");
43 43 addBare([this]() { c_main->newlineBeforeEndstream(); });
44 44 popHandler(); // key: newlineBeforeEndstream
45 45 pushKey("normalizeContent");
46   -addChoices(yn_choices, [this](char const* p) { c_main->normalizeContent(p); });
  46 +addChoices(yn_choices, true, [this](char const* p) { c_main->normalizeContent(p); });
47 47 popHandler(); // key: normalizeContent
48 48 pushKey("streamData");
49   -addChoices(stream_data_choices, [this](char const* p) { c_main->streamData(p); });
  49 +addChoices(stream_data_choices, true, [this](char const* p) { c_main->streamData(p); });
50 50 popHandler(); // key: streamData
51 51 pushKey("compressStreams");
52   -addChoices(yn_choices, [this](char const* p) { c_main->compressStreams(p); });
  52 +addChoices(yn_choices, true, [this](char const* p) { c_main->compressStreams(p); });
53 53 popHandler(); // key: compressStreams
54 54 pushKey("recompressFlate");
55 55 addBare([this]() { c_main->recompressFlate(); });
56 56 popHandler(); // key: recompressFlate
57 57 pushKey("decodeLevel");
58   -addChoices(decode_level_choices, [this](char const* p) { c_main->decodeLevel(p); });
  58 +addChoices(decode_level_choices, true, [this](char const* p) { c_main->decodeLevel(p); });
59 59 popHandler(); // key: decodeLevel
60 60 pushKey("decrypt");
61 61 addBare([this]() { c_main->decrypt(); });
... ... @@ -85,7 +85,7 @@ pushKey("linearizePass1");
85 85 addParameter([this](char const* p) { c_main->linearizePass1(p); });
86 86 popHandler(); // key: linearizePass1
87 87 pushKey("objectStreams");
88   -addChoices(object_streams_choices, [this](char const* p) { c_main->objectStreams(p); });
  88 +addChoices(object_streams_choices, true, [this](char const* p) { c_main->objectStreams(p); });
89 89 popHandler(); // key: objectStreams
90 90 pushKey("minVersion");
91 91 addParameter([this](char const* p) { c_main->minVersion(p); });
... ... @@ -110,82 +110,82 @@ popHandler(); // key: ownerPassword
110 110 pushKey("40bit");
111 111 beginDict(bindJSON(&Handlers::beginEncrypt40bit), bindBare(&Handlers::endEncrypt40bit)); // .encrypt.40bit
112 112 pushKey("annotate");
113   -addChoices(yn_choices, [this](char const* p) { c_enc->annotate(p); });
  113 +addChoices(yn_choices, true, [this](char const* p) { c_enc->annotate(p); });
114 114 popHandler(); // key: annotate
115 115 pushKey("extract");
116   -addChoices(yn_choices, [this](char const* p) { c_enc->extract(p); });
  116 +addChoices(yn_choices, true, [this](char const* p) { c_enc->extract(p); });
117 117 popHandler(); // key: extract
118 118 pushKey("modify");
119   -addChoices(modify128_choices, [this](char const* p) { c_enc->modify(p); });
  119 +addChoices(modify128_choices, true, [this](char const* p) { c_enc->modify(p); });
120 120 popHandler(); // key: modify
121 121 pushKey("print");
122   -addChoices(print128_choices, [this](char const* p) { c_enc->print(p); });
  122 +addChoices(print128_choices, true, [this](char const* p) { c_enc->print(p); });
123 123 popHandler(); // key: print
124 124 popHandler(); // key: 40bit
125 125 pushKey("128bit");
126 126 beginDict(bindJSON(&Handlers::beginEncrypt128bit), bindBare(&Handlers::endEncrypt128bit)); // .encrypt.128bit
127 127 pushKey("accessibility");
128   -addChoices(yn_choices, [this](char const* p) { c_enc->accessibility(p); });
  128 +addChoices(yn_choices, true, [this](char const* p) { c_enc->accessibility(p); });
129 129 popHandler(); // key: accessibility
130 130 pushKey("annotate");
131   -addChoices(yn_choices, [this](char const* p) { c_enc->annotate(p); });
  131 +addChoices(yn_choices, true, [this](char const* p) { c_enc->annotate(p); });
132 132 popHandler(); // key: annotate
133 133 pushKey("assemble");
134   -addChoices(yn_choices, [this](char const* p) { c_enc->assemble(p); });
  134 +addChoices(yn_choices, true, [this](char const* p) { c_enc->assemble(p); });
135 135 popHandler(); // key: assemble
136 136 pushKey("cleartextMetadata");
137 137 addBare([this]() { c_enc->cleartextMetadata(); });
138 138 popHandler(); // key: cleartextMetadata
139 139 pushKey("extract");
140   -addChoices(yn_choices, [this](char const* p) { c_enc->extract(p); });
  140 +addChoices(yn_choices, true, [this](char const* p) { c_enc->extract(p); });
141 141 popHandler(); // key: extract
142 142 pushKey("form");
143   -addChoices(yn_choices, [this](char const* p) { c_enc->form(p); });
  143 +addChoices(yn_choices, true, [this](char const* p) { c_enc->form(p); });
144 144 popHandler(); // key: form
145 145 pushKey("modifyOther");
146   -addChoices(yn_choices, [this](char const* p) { c_enc->modifyOther(p); });
  146 +addChoices(yn_choices, true, [this](char const* p) { c_enc->modifyOther(p); });
147 147 popHandler(); // key: modifyOther
148 148 pushKey("modify");
149   -addChoices(modify128_choices, [this](char const* p) { c_enc->modify(p); });
  149 +addChoices(modify128_choices, true, [this](char const* p) { c_enc->modify(p); });
150 150 popHandler(); // key: modify
151 151 pushKey("print");
152   -addChoices(print128_choices, [this](char const* p) { c_enc->print(p); });
  152 +addChoices(print128_choices, true, [this](char const* p) { c_enc->print(p); });
153 153 popHandler(); // key: print
154 154 pushKey("forceV4");
155 155 addBare([this]() { c_enc->forceV4(); });
156 156 popHandler(); // key: forceV4
157 157 pushKey("useAes");
158   -addChoices(yn_choices, [this](char const* p) { c_enc->useAes(p); });
  158 +addChoices(yn_choices, true, [this](char const* p) { c_enc->useAes(p); });
159 159 popHandler(); // key: useAes
160 160 popHandler(); // key: 128bit
161 161 pushKey("256bit");
162 162 beginDict(bindJSON(&Handlers::beginEncrypt256bit), bindBare(&Handlers::endEncrypt256bit)); // .encrypt.256bit
163 163 pushKey("accessibility");
164   -addChoices(yn_choices, [this](char const* p) { c_enc->accessibility(p); });
  164 +addChoices(yn_choices, true, [this](char const* p) { c_enc->accessibility(p); });
165 165 popHandler(); // key: accessibility
166 166 pushKey("annotate");
167   -addChoices(yn_choices, [this](char const* p) { c_enc->annotate(p); });
  167 +addChoices(yn_choices, true, [this](char const* p) { c_enc->annotate(p); });
168 168 popHandler(); // key: annotate
169 169 pushKey("assemble");
170   -addChoices(yn_choices, [this](char const* p) { c_enc->assemble(p); });
  170 +addChoices(yn_choices, true, [this](char const* p) { c_enc->assemble(p); });
171 171 popHandler(); // key: assemble
172 172 pushKey("cleartextMetadata");
173 173 addBare([this]() { c_enc->cleartextMetadata(); });
174 174 popHandler(); // key: cleartextMetadata
175 175 pushKey("extract");
176   -addChoices(yn_choices, [this](char const* p) { c_enc->extract(p); });
  176 +addChoices(yn_choices, true, [this](char const* p) { c_enc->extract(p); });
177 177 popHandler(); // key: extract
178 178 pushKey("form");
179   -addChoices(yn_choices, [this](char const* p) { c_enc->form(p); });
  179 +addChoices(yn_choices, true, [this](char const* p) { c_enc->form(p); });
180 180 popHandler(); // key: form
181 181 pushKey("modifyOther");
182   -addChoices(yn_choices, [this](char const* p) { c_enc->modifyOther(p); });
  182 +addChoices(yn_choices, true, [this](char const* p) { c_enc->modifyOther(p); });
183 183 popHandler(); // key: modifyOther
184 184 pushKey("modify");
185   -addChoices(modify128_choices, [this](char const* p) { c_enc->modify(p); });
  185 +addChoices(modify128_choices, true, [this](char const* p) { c_enc->modify(p); });
186 186 popHandler(); // key: modify
187 187 pushKey("print");
188   -addChoices(print128_choices, [this](char const* p) { c_enc->print(p); });
  188 +addChoices(print128_choices, true, [this](char const* p) { c_enc->print(p); });
189 189 popHandler(); // key: print
190 190 pushKey("allowInsecure");
191 191 addBare([this]() { c_enc->allowInsecure(); });
... ... @@ -238,11 +238,11 @@ pushKey("showAttachment");
238 238 addParameter([this](char const* p) { c_main->showAttachment(p); });
239 239 popHandler(); // key: showAttachment
240 240 pushKey("json");
241   -addChoices(json_version_choices, [this](char const* p) { c_main->json(p); });
  241 +addChoices(json_version_choices, false, [this](char const* p) { c_main->json(p); });
242 242 popHandler(); // key: json
243 243 pushKey("jsonKey");
244 244 beginArray(bindJSON(&Handlers::beginJsonKeyArray), bindBare(&Handlers::endJsonKeyArray)); // .jsonKey[]
245   -addChoices(json_key_choices, [this](char const* p) { c_main->jsonKey(p); });
  245 +addChoices(json_key_choices, true, [this](char const* p) { c_main->jsonKey(p); });
246 246 popHandler(); // array: .jsonKey[]
247 247 popHandler(); // key: jsonKey
248 248 pushKey("jsonObject");
... ... @@ -254,7 +254,7 @@ pushKey("allowWeakCrypto");
254 254 addBare([this]() { c_main->allowWeakCrypto(); });
255 255 popHandler(); // key: allowWeakCrypto
256 256 pushKey("keepFilesOpen");
257   -addChoices(yn_choices, [this](char const* p) { c_main->keepFilesOpen(p); });
  257 +addChoices(yn_choices, true, [this](char const* p) { c_main->keepFilesOpen(p); });
258 258 popHandler(); // key: keepFilesOpen
259 259 pushKey("keepFilesOpenThreshold");
260 260 addParameter([this](char const* p) { c_main->keepFilesOpenThreshold(p); });
... ... @@ -272,7 +272,7 @@ pushKey("passwordIsHexKey");
272 272 addBare([this]() { c_main->passwordIsHexKey(); });
273 273 popHandler(); // key: passwordIsHexKey
274 274 pushKey("passwordMode");
275   -addChoices(password_mode_choices, [this](char const* p) { c_main->passwordMode(p); });
  275 +addChoices(password_mode_choices, true, [this](char const* p) { c_main->passwordMode(p); });
276 276 popHandler(); // key: passwordMode
277 277 pushKey("suppressPasswordRecovery");
278 278 addBare([this]() { c_main->suppressPasswordRecovery(); });
... ... @@ -293,7 +293,7 @@ pushKey("iiMinBytes");
293 293 addParameter([this](char const* p) { c_main->iiMinBytes(p); });
294 294 popHandler(); // key: iiMinBytes
295 295 pushKey("removeUnreferencedResources");
296   -addChoices(remove_unref_choices, [this](char const* p) { c_main->removeUnreferencedResources(p); });
  296 +addChoices(remove_unref_choices, true, [this](char const* p) { c_main->removeUnreferencedResources(p); });
297 297 popHandler(); // key: removeUnreferencedResources
298 298 pushKey("addAttachment");
299 299 beginArray(bindJSON(&Handlers::beginAddAttachmentArray), bindBare(&Handlers::endAddAttachmentArray)); // .addAttachment[]
... ... @@ -345,7 +345,7 @@ pushKey("collate");
345 345 addParameter([this](char const* p) { c_main->collate(p); });
346 346 popHandler(); // key: collate
347 347 pushKey("flattenAnnotations");
348   -addChoices(flatten_choices, [this](char const* p) { c_main->flattenAnnotations(p); });
  348 +addChoices(flatten_choices, true, [this](char const* p) { c_main->flattenAnnotations(p); });
349 349 popHandler(); // key: flattenAnnotations
350 350 pushKey("flattenRotation");
351 351 addBare([this]() { c_main->flattenRotation(); });
... ...
qpdf/qpdf.testcov
... ... @@ -630,7 +630,7 @@ qpdf check password password correct 0
630 630 qpdf check password not encrypted 0
631 631 QPDFJob_config password file 0
632 632 QPDFJob_config password stdin 0
633   -QPDFJob json bare not true 0
  633 +QPDFJob json bare not empty 0
634 634 QPDFJob json choice mismatch 0
635 635 QPDFJob json choice match 0
636 636 QPDFJob json encrypt no key length 0
... ...
qpdf/qtest/qpdf/bad-bare-option-false-json.out
1 1  
2   -qpdf: error with job-json file bad-json-bare-option-false.json: .qdf: value must be true
  2 +qpdf: error with job-json file bad-json-bare-option-false.json: .qdf: value must be the empty string
3 3 Run qpdf--job-json-help for information on the file format.
4 4  
5 5 For help:
... ...
qpdf/qtest/qpdf/bad-json-bare-option-false.json
1 1 {
2   - "qdf": false
  2 + "qdf": "not-empty"
3 3 }
... ...
qpdf/qtest/qpdf/job-json-add-attachments.json
1 1 {
2 2 "inputFile": "minimal.pdf",
3 3 "outputFile": "a.pdf",
4   - "staticId": true,
  4 + "staticId": "",
5 5 "addAttachment": [
6 6 {
7 7 "file": "auto-txt",
... ...
qpdf/qtest/qpdf/job-json-choice-match.json
1 1 {
2 2 "inputFile": "minimal.pdf",
3 3 "outputFile": "a.pdf",
4   - "deterministicId": true,
  4 + "deterministicId": "",
5 5 "objectStreams": "generate"
6 6 }
... ...
qpdf/qtest/qpdf/job-json-copy-attachments.json
1 1 {
2 2 "inputFile": "minimal.pdf",
3 3 "outputFile": "a.pdf",
4   - "staticId": true,
  4 + "staticId": "",
5 5 "copyAttachmentsFrom": [
6 6 {
7 7 "file": "job-json-add-attachments.pdf"
... ...
qpdf/qtest/qpdf/job-json-empty-input.json
1 1 {
2   - "empty": true,
  2 + "empty": "",
3 3 "outputFile": "a.pdf",
4   - "staticId": true,
  4 + "staticId": "",
5 5 "pages": [
6 6 {
7 7 "file": "minimal.pdf"
... ...
qpdf/qtest/qpdf/job-json-encrypt-128.json
1 1 {
2 2 "inputFile": "fxo-blue.pdf",
3 3 "outputFile": "a.pdf",
4   - "staticId": true,
5   - "staticAesIv": true,
  4 + "staticId": "",
  5 + "staticAesIv": "",
6 6 "encrypt": {
7 7 "userPassword": "u",
8 8 "ownerPassword": "o",
... ...
qpdf/qtest/qpdf/job-json-encrypt-256-with-restrictions.json
1 1 {
2 2 "inputFile": "minimal.pdf",
3 3 "outputFile": "a.pdf",
4   - "staticId": true,
5   - "staticAesIv": true,
  4 + "staticId": "",
  5 + "staticAesIv": "",
6 6 "encrypt": {
7 7 "userPassword": "u",
8 8 "ownerPassword": "o",
... ...
qpdf/qtest/qpdf/job-json-encrypt-40.json
1 1 {
2 2 "inputFile": "minimal.pdf",
3 3 "outputFile": "a.pdf",
4   - "staticId": true,
  4 + "staticId": "",
5 5 "encrypt": {
6 6 "userPassword": "u",
7 7 "ownerPassword": "o",
8 8 "40bit": {}
9 9 },
10   - "allowWeakCrypto": true
  10 + "allowWeakCrypto": ""
11 11 }
... ...
qpdf/qtest/qpdf/job-json-input-file-password.json
... ... @@ -2,7 +2,7 @@
2 2 "inputFile": "20-pages.pdf",
3 3 "password": "user",
4 4 "outputFile": "a.pdf",
5   - "staticId": true,
6   - "staticAesIv": true,
  5 + "staticId": "",
  6 + "staticAesIv": "",
7 7 "compressStreams": "n"
8 8 }
... ...
qpdf/qtest/qpdf/job-json-misc-options.json
1 1 {
2 2 "inputFile": "minimal.pdf",
3 3 "outputFile": "a.pdf",
4   - "staticId": true,
5   - "linearize": true,
  4 + "staticId": "",
  5 + "linearize": "",
6 6 "compressStreams": "n"
7 7 }
... ...
qpdf/qtest/qpdf/job-json-replace-input.json
1 1 {
2 2 "inputFile": "a.pdf",
3   - "replaceInput": true,
4   - "staticId": true,
  3 + "replaceInput": "",
  4 + "staticId": "",
5 5 "objectStreams": "generate"
6 6 }
... ...
qpdf/qtest/qpdf/job-json-underlay-overlay-password.json
1 1 {
2 2 "inputFile": "minimal.pdf",
3 3 "outputFile": "a.pdf",
4   - "staticId": true,
  4 + "staticId": "",
5 5 "underlay": {
6 6 "file": "20-pages.pdf",
7 7 "password": "user",
... ...
qpdf/qtest/qpdf/job-json-underlay-overlay.json
... ... @@ -2,8 +2,8 @@
2 2 "inputFile": "20-pages.pdf",
3 3 "password": "owner",
4 4 "outputFile": "a.pdf",
5   - "staticId": true,
6   - "decrypt": true,
  5 + "staticId": "",
  6 + "decrypt": "",
7 7 "underlay": {
8 8 "file": "fxo-green.pdf"
9 9 },
... ...
qpdf/qtest/qpdf/job-show-encryption.json
1 1 {
2   - "showEncryption": true
  2 + "showEncryption": ""
3 3 }
... ...