Commit 6ec22f117d9ad9d7ba5315c4b493b85222f93b4b

Authored by Jay Berkenbilt
1 parent 46303777

Modernize encryption API for more granularity

Setting encryption permissions for R >= 3 set permission bits in
groups corresponding to menu options in Acrobat 5. The new API allows
the bits to be set individually.
ChangeLog
@@ -16,6 +16,15 @@ @@ -16,6 +16,15 @@
16 16
17 2019-01-14 Jay Berkenbilt <ejb@ql.org> 17 2019-01-14 Jay Berkenbilt <ejb@ql.org>
18 18
  19 + * Add new versions of
  20 + QPDFWriter::setR{3,4,5,6}EncryptionParameters that allow
  21 + individual setting of the various permission bits. The old
  22 + interfaces are retained for backward compatibility. In the "C"
  23 + API, add qpdf_set_r{3,4,5,6}_encryption_parameters2. The new
  24 + interfaces use separate booleans for various permissions instead
  25 + of the qpdf_r3_modify_e enumerated type, which set permission bits
  26 + in predefined groups.
  27 +
19 * Add versions of utf8 to single-byte character transcoders that 28 * Add versions of utf8 to single-byte character transcoders that
20 return a success code. 29 return a success code.
21 30
include/qpdf/Constants.h
@@ -80,13 +80,18 @@ enum qpdf_r3_print_e @@ -80,13 +80,18 @@ enum qpdf_r3_print_e
80 qpdf_r3p_low, /* allow only low-resolution printing */ 80 qpdf_r3p_low, /* allow only low-resolution printing */
81 qpdf_r3p_none /* allow no printing */ 81 qpdf_r3p_none /* allow no printing */
82 }; 82 };
  83 +
  84 +/* qpdf_r3_modify_e doesn't allow the full flexibility of the spec. It
  85 + * corresponds to options in Acrobat 5's menus. The new interface in
  86 + * QPDFWriter offers more granularity and no longer uses this type.
  87 + */
83 enum qpdf_r3_modify_e /* Allowed changes: */ 88 enum qpdf_r3_modify_e /* Allowed changes: */
84 { 89 {
85 - qpdf_r3m_all = 0, /* General editing, comments, forms */  
86 - qpdf_r3m_annotate, /* Comments, form field fill-in, and signing */  
87 - qpdf_r3m_form, /* form field fill-in and signing */  
88 - qpdf_r3m_assembly, /* only document assembly */  
89 - qpdf_r3m_none /* no modifications */ 90 + qpdf_r3m_all = 0, /* All editing */
  91 + qpdf_r3m_annotate, /* Comments, fill forms, signing, assembly */
  92 + qpdf_r3m_form, /* Fill forms, signing, assembly */
  93 + qpdf_r3m_assembly, /* Only document assembly */
  94 + qpdf_r3m_none /* No modifications */
90 }; 95 };
91 96
92 /* Form field flags from the PDF spec */ 97 /* Form field flags from the PDF spec */
include/qpdf/QPDFWriter.hh
@@ -344,6 +344,39 @@ class QPDFWriter @@ -344,6 +344,39 @@ class QPDFWriter
344 // AES is used, 1.6, and setting R5 or R6 parameters pushes the 344 // AES is used, 1.6, and setting R5 or R6 parameters pushes the
345 // version to at least 1.7 with extension level 3. 345 // version to at least 1.7 with extension level 3.
346 QPDF_DLL 346 QPDF_DLL
  347 + void setR3EncryptionParameters(
  348 + char const* user_password, char const* owner_password,
  349 + bool allow_accessibility, bool allow_extract,
  350 + bool allow_assemble, bool allow_annotate_and_form,
  351 + bool allow_form_filling, bool allow_modify_other,
  352 + qpdf_r3_print_e print);
  353 + QPDF_DLL
  354 + void setR4EncryptionParameters(
  355 + char const* user_password, char const* owner_password,
  356 + bool allow_accessibility, bool allow_extract,
  357 + bool allow_assemble, bool allow_annotate_and_form,
  358 + bool allow_form_filling, bool allow_modify_other,
  359 + qpdf_r3_print_e print, bool encrypt_metadata, bool use_aes);
  360 + // R5 is deprecated. Do not use it for production use. Writing
  361 + // R5 is supported by qpdf primarily to generate test files for
  362 + // applications that may need to test R5 support.
  363 + QPDF_DLL
  364 + void setR5EncryptionParameters(
  365 + char const* user_password, char const* owner_password,
  366 + bool allow_accessibility, bool allow_extract,
  367 + bool allow_assemble, bool allow_annotate_and_form,
  368 + bool allow_form_filling, bool allow_modify_other,
  369 + qpdf_r3_print_e print, bool encrypt_metadata);
  370 + QPDF_DLL
  371 + void setR6EncryptionParameters(
  372 + char const* user_password, char const* owner_password,
  373 + bool allow_accessibility, bool allow_extract,
  374 + bool allow_assemble, bool allow_annotate_and_form,
  375 + bool allow_form_filling, bool allow_modify_other,
  376 + qpdf_r3_print_e print, bool encrypt_metadata_aes);
  377 +
  378 + // Pre qpdf 8.4.0 API
  379 + QPDF_DLL
347 void setR2EncryptionParameters( 380 void setR2EncryptionParameters(
348 char const* user_password, char const* owner_password, 381 char const* user_password, char const* owner_password,
349 bool allow_print, bool allow_modify, 382 bool allow_print, bool allow_modify,
@@ -359,9 +392,6 @@ class QPDFWriter @@ -359,9 +392,6 @@ class QPDFWriter
359 bool allow_accessibility, bool allow_extract, 392 bool allow_accessibility, bool allow_extract,
360 qpdf_r3_print_e print, qpdf_r3_modify_e modify, 393 qpdf_r3_print_e print, qpdf_r3_modify_e modify,
361 bool encrypt_metadata, bool use_aes); 394 bool encrypt_metadata, bool use_aes);
362 - // R5 is deprecated. Do not use it for production use. Writing  
363 - // R5 is supported by qpdf primarily to generate test files for  
364 - // applications that may need to test R5 support.  
365 QPDF_DLL 395 QPDF_DLL
366 void setR5EncryptionParameters( 396 void setR5EncryptionParameters(
367 char const* user_password, char const* owner_password, 397 char const* user_password, char const* owner_password,
@@ -459,6 +489,8 @@ class QPDFWriter @@ -459,6 +489,8 @@ class QPDFWriter
459 std::set<int>& bits_to_clear, 489 std::set<int>& bits_to_clear,
460 char const* user_password, char const* owner_password, 490 char const* user_password, char const* owner_password,
461 bool allow_accessibility, bool allow_extract, 491 bool allow_accessibility, bool allow_extract,
  492 + bool allow_assemble, bool allow_annotate_and_form,
  493 + bool allow_form_filling, bool allow_modify_other,
462 qpdf_r3_print_e print, qpdf_r3_modify_e modify); 494 qpdf_r3_print_e print, qpdf_r3_modify_e modify);
463 void disableIncompatibleEncryption(int major, int minor, 495 void disableIncompatibleEncryption(int major, int minor,
464 int extension_level); 496 int extension_level);
include/qpdf/qpdf-c.h
@@ -390,6 +390,40 @@ extern &quot;C&quot; { @@ -390,6 +390,40 @@ extern &quot;C&quot; {
390 QPDF_BOOL allow_extract, QPDF_BOOL allow_annotate); 390 QPDF_BOOL allow_extract, QPDF_BOOL allow_annotate);
391 391
392 QPDF_DLL 392 QPDF_DLL
  393 + void qpdf_set_r3_encryption_parameters2(
  394 + qpdf_data qpdf, char const* user_password, char const* owner_password,
  395 + QPDF_BOOL allow_accessibility, QPDF_BOOL allow_extract,
  396 + QPDF_BOOL allow_assemble, QPDF_BOOL allow_annotate_and_form,
  397 + QPDF_BOOL allow_form_filling, QPDF_BOOL allow_modify_other,
  398 + enum qpdf_r3_print_e print);
  399 +
  400 + QPDF_DLL
  401 + void qpdf_set_r4_encryption_parameters2(
  402 + qpdf_data qpdf, char const* user_password, char const* owner_password,
  403 + QPDF_BOOL allow_accessibility, QPDF_BOOL allow_extract,
  404 + QPDF_BOOL allow_assemble, QPDF_BOOL allow_annotate_and_form,
  405 + QPDF_BOOL allow_form_filling, QPDF_BOOL allow_modify_other,
  406 + enum qpdf_r3_print_e print,
  407 + QPDF_BOOL encrypt_metadata, QPDF_BOOL use_aes);
  408 +
  409 + QPDF_DLL
  410 + void qpdf_set_r5_encryption_parameters2(
  411 + qpdf_data qpdf, char const* user_password, char const* owner_password,
  412 + QPDF_BOOL allow_accessibility, QPDF_BOOL allow_extract,
  413 + QPDF_BOOL allow_assemble, QPDF_BOOL allow_annotate_and_form,
  414 + QPDF_BOOL allow_form_filling, QPDF_BOOL allow_modify_other,
  415 + enum qpdf_r3_print_e print, QPDF_BOOL encrypt_metadata);
  416 +
  417 + QPDF_DLL
  418 + void qpdf_set_r6_encryption_parameters2(
  419 + qpdf_data qpdf, char const* user_password, char const* owner_password,
  420 + QPDF_BOOL allow_accessibility, QPDF_BOOL allow_extract,
  421 + QPDF_BOOL allow_assemble, QPDF_BOOL allow_annotate_and_form,
  422 + QPDF_BOOL allow_form_filling, QPDF_BOOL allow_modify_other,
  423 + enum qpdf_r3_print_e print, QPDF_BOOL encrypt_metadata);
  424 +
  425 + /* Pre 8.4.0 encryption API */
  426 + QPDF_DLL
393 void qpdf_set_r3_encryption_parameters( 427 void qpdf_set_r3_encryption_parameters(
394 qpdf_data qpdf, char const* user_password, char const* owner_password, 428 qpdf_data qpdf, char const* user_password, char const* owner_password,
395 QPDF_BOOL allow_accessibility, QPDF_BOOL allow_extract, 429 QPDF_BOOL allow_accessibility, QPDF_BOOL allow_extract,
libqpdf/QPDFWriter.cc
@@ -409,7 +409,26 @@ QPDFWriter::setR3EncryptionParameters( @@ -409,7 +409,26 @@ QPDFWriter::setR3EncryptionParameters(
409 std::set<int> clear; 409 std::set<int> clear;
410 interpretR3EncryptionParameters( 410 interpretR3EncryptionParameters(
411 clear, user_password, owner_password, 411 clear, user_password, owner_password,
412 - allow_accessibility, allow_extract, print, modify); 412 + allow_accessibility, allow_extract,
  413 + true, true, true, true, print, modify);
  414 + setEncryptionParameters(user_password, owner_password, 2, 3, 16, clear);
  415 +}
  416 +
  417 +void
  418 +QPDFWriter::setR3EncryptionParameters(
  419 + char const* user_password, char const* owner_password,
  420 + bool allow_accessibility, bool allow_extract,
  421 + bool allow_assemble, bool allow_annotate_and_form,
  422 + bool allow_form_filling, bool allow_modify_other,
  423 + qpdf_r3_print_e print)
  424 +{
  425 + std::set<int> clear;
  426 + interpretR3EncryptionParameters(
  427 + clear, user_password, owner_password,
  428 + allow_accessibility, allow_extract,
  429 + allow_assemble, allow_annotate_and_form,
  430 + allow_form_filling, allow_modify_other,
  431 + print, qpdf_r3m_all);
413 setEncryptionParameters(user_password, owner_password, 2, 3, 16, clear); 432 setEncryptionParameters(user_password, owner_password, 2, 3, 16, clear);
414 } 433 }
415 434
@@ -423,7 +442,29 @@ QPDFWriter::setR4EncryptionParameters( @@ -423,7 +442,29 @@ QPDFWriter::setR4EncryptionParameters(
423 std::set<int> clear; 442 std::set<int> clear;
424 interpretR3EncryptionParameters( 443 interpretR3EncryptionParameters(
425 clear, user_password, owner_password, 444 clear, user_password, owner_password,
426 - allow_accessibility, allow_extract, print, modify); 445 + allow_accessibility, allow_extract,
  446 + true, true, true, true, print, modify);
  447 + this->m->encrypt_use_aes = use_aes;
  448 + this->m->encrypt_metadata = encrypt_metadata;
  449 + setEncryptionParameters(user_password, owner_password, 4, 4, 16, clear);
  450 +}
  451 +
  452 +void
  453 +QPDFWriter::setR4EncryptionParameters(
  454 + char const* user_password, char const* owner_password,
  455 + bool allow_accessibility, bool allow_extract,
  456 + bool allow_assemble, bool allow_annotate_and_form,
  457 + bool allow_form_filling, bool allow_modify_other,
  458 + qpdf_r3_print_e print,
  459 + bool encrypt_metadata, bool use_aes)
  460 +{
  461 + std::set<int> clear;
  462 + interpretR3EncryptionParameters(
  463 + clear, user_password, owner_password,
  464 + allow_accessibility, allow_extract,
  465 + allow_assemble, allow_annotate_and_form,
  466 + allow_form_filling, allow_modify_other,
  467 + print, qpdf_r3m_all);
427 this->m->encrypt_use_aes = use_aes; 468 this->m->encrypt_use_aes = use_aes;
428 this->m->encrypt_metadata = encrypt_metadata; 469 this->m->encrypt_metadata = encrypt_metadata;
429 setEncryptionParameters(user_password, owner_password, 4, 4, 16, clear); 470 setEncryptionParameters(user_password, owner_password, 4, 4, 16, clear);
@@ -439,7 +480,29 @@ QPDFWriter::setR5EncryptionParameters( @@ -439,7 +480,29 @@ QPDFWriter::setR5EncryptionParameters(
439 std::set<int> clear; 480 std::set<int> clear;
440 interpretR3EncryptionParameters( 481 interpretR3EncryptionParameters(
441 clear, user_password, owner_password, 482 clear, user_password, owner_password,
442 - allow_accessibility, allow_extract, print, modify); 483 + allow_accessibility, allow_extract,
  484 + true, true, true, true, print, modify);
  485 + this->m->encrypt_use_aes = true;
  486 + this->m->encrypt_metadata = encrypt_metadata;
  487 + setEncryptionParameters(user_password, owner_password, 5, 5, 32, clear);
  488 +}
  489 +
  490 +void
  491 +QPDFWriter::setR5EncryptionParameters(
  492 + char const* user_password, char const* owner_password,
  493 + bool allow_accessibility, bool allow_extract,
  494 + bool allow_assemble, bool allow_annotate_and_form,
  495 + bool allow_form_filling, bool allow_modify_other,
  496 + qpdf_r3_print_e print,
  497 + bool encrypt_metadata)
  498 +{
  499 + std::set<int> clear;
  500 + interpretR3EncryptionParameters(
  501 + clear, user_password, owner_password,
  502 + allow_accessibility, allow_extract,
  503 + allow_assemble, allow_annotate_and_form,
  504 + allow_form_filling, allow_modify_other,
  505 + print, qpdf_r3m_all);
443 this->m->encrypt_use_aes = true; 506 this->m->encrypt_use_aes = true;
444 this->m->encrypt_metadata = encrypt_metadata; 507 this->m->encrypt_metadata = encrypt_metadata;
445 setEncryptionParameters(user_password, owner_password, 5, 5, 32, clear); 508 setEncryptionParameters(user_password, owner_password, 5, 5, 32, clear);
@@ -455,7 +518,29 @@ QPDFWriter::setR6EncryptionParameters( @@ -455,7 +518,29 @@ QPDFWriter::setR6EncryptionParameters(
455 std::set<int> clear; 518 std::set<int> clear;
456 interpretR3EncryptionParameters( 519 interpretR3EncryptionParameters(
457 clear, user_password, owner_password, 520 clear, user_password, owner_password,
458 - allow_accessibility, allow_extract, print, modify); 521 + allow_accessibility, allow_extract,
  522 + true, true, true, true, print, modify);
  523 + this->m->encrypt_use_aes = true;
  524 + this->m->encrypt_metadata = encrypt_metadata;
  525 + setEncryptionParameters(user_password, owner_password, 5, 6, 32, clear);
  526 +}
  527 +
  528 +void
  529 +QPDFWriter::setR6EncryptionParameters(
  530 + char const* user_password, char const* owner_password,
  531 + bool allow_accessibility, bool allow_extract,
  532 + bool allow_assemble, bool allow_annotate_and_form,
  533 + bool allow_form_filling, bool allow_modify_other,
  534 + qpdf_r3_print_e print,
  535 + bool encrypt_metadata)
  536 +{
  537 + std::set<int> clear;
  538 + interpretR3EncryptionParameters(
  539 + clear, user_password, owner_password,
  540 + allow_accessibility, allow_extract,
  541 + allow_assemble, allow_annotate_and_form,
  542 + allow_form_filling, allow_modify_other,
  543 + print, qpdf_r3m_all);
459 this->m->encrypt_use_aes = true; 544 this->m->encrypt_use_aes = true;
460 this->m->encrypt_metadata = encrypt_metadata; 545 this->m->encrypt_metadata = encrypt_metadata;
461 setEncryptionParameters(user_password, owner_password, 5, 6, 32, clear); 546 setEncryptionParameters(user_password, owner_password, 5, 6, 32, clear);
@@ -466,6 +551,8 @@ QPDFWriter::interpretR3EncryptionParameters( @@ -466,6 +551,8 @@ QPDFWriter::interpretR3EncryptionParameters(
466 std::set<int>& clear, 551 std::set<int>& clear,
467 char const* user_password, char const* owner_password, 552 char const* user_password, char const* owner_password,
468 bool allow_accessibility, bool allow_extract, 553 bool allow_accessibility, bool allow_extract,
  554 + bool allow_assemble, bool allow_annotate_and_form,
  555 + bool allow_form_filling, bool allow_modify_other,
469 qpdf_r3_print_e print, qpdf_r3_modify_e modify) 556 qpdf_r3_print_e print, qpdf_r3_modify_e modify)
470 { 557 {
471 // Acrobat 5 security options: 558 // Acrobat 5 security options:
@@ -486,8 +573,21 @@ QPDFWriter::interpretR3EncryptionParameters( @@ -486,8 +573,21 @@ QPDFWriter::interpretR3EncryptionParameters(
486 // Low Resolution 573 // Low Resolution
487 // Full printing 574 // Full printing
488 575
  576 + // Meanings of bits in P when R >= 3
  577 + //
  578 + // 3: low-resolution printing
  579 + // 4: document modification except as controlled by 6, 9, and 11
  580 + // 5: extraction
  581 + // 6: add/modify annotations (comment), fill in forms
  582 + // if 4+6 are set, also allows modification of form fields
  583 + // 9: fill in forms even if 6 is clear
  584 + // 10: accessibility; ignored by readers, should always be set
  585 + // 11: document assembly even if 4 is clear
  586 + // 12: high-resolution printing
  587 +
489 if (! allow_accessibility) 588 if (! allow_accessibility)
490 { 589 {
  590 + // setEncryptionParameters sets this if R > 3
491 clear.insert(10); 591 clear.insert(10);
492 } 592 }
493 if (! allow_extract) 593 if (! allow_extract)
@@ -511,6 +611,13 @@ QPDFWriter::interpretR3EncryptionParameters( @@ -511,6 +611,13 @@ QPDFWriter::interpretR3EncryptionParameters(
511 // no default so gcc warns for missing cases 611 // no default so gcc warns for missing cases
512 } 612 }
513 613
  614 + // Modify options. The qpdf_r3_modify_e options control groups of
  615 + // bits and lack the full flexibility of the spec. This is
  616 + // unfortunate, but it's been in the API for ages, and we're stuck
  617 + // with it. See also allow checks below to control the bits
  618 + // individually.
  619 +
  620 + // NOT EXERCISED IN TEST SUITE
514 switch (modify) 621 switch (modify)
515 { 622 {
516 case qpdf_r3m_none: 623 case qpdf_r3m_none:
@@ -530,6 +637,24 @@ QPDFWriter::interpretR3EncryptionParameters( @@ -530,6 +637,24 @@ QPDFWriter::interpretR3EncryptionParameters(
530 637
531 // no default so gcc warns for missing cases 638 // no default so gcc warns for missing cases
532 } 639 }
  640 + // END NOT EXERCISED IN TEST SUITE
  641 +
  642 + if (! allow_assemble)
  643 + {
  644 + clear.insert(11);
  645 + }
  646 + if (! allow_annotate_and_form)
  647 + {
  648 + clear.insert(6);
  649 + }
  650 + if (! allow_form_filling)
  651 + {
  652 + clear.insert(9);
  653 + }
  654 + if (! allow_modify_other)
  655 + {
  656 + clear.insert(4);
  657 + }
533 } 658 }
534 659
535 void 660 void
libqpdf/qpdf-c.cc
@@ -603,12 +603,77 @@ void qpdf_set_r2_encryption_parameters( @@ -603,12 +603,77 @@ void qpdf_set_r2_encryption_parameters(
603 allow_print, allow_modify, allow_extract, allow_annotate); 603 allow_print, allow_modify, allow_extract, allow_annotate);
604 } 604 }
605 605
  606 +void qpdf_set_r3_encryption_parameters2(
  607 + qpdf_data qpdf, char const* user_password, char const* owner_password,
  608 + QPDF_BOOL allow_accessibility, QPDF_BOOL allow_extract,
  609 + QPDF_BOOL allow_assemble, QPDF_BOOL allow_annotate_and_form,
  610 + QPDF_BOOL allow_form_filling, QPDF_BOOL allow_modify_other,
  611 + enum qpdf_r3_print_e print)
  612 +{
  613 + QTC::TC("qpdf", "qpdf-c called qpdf_set_r3_encryption_parameters");
  614 + qpdf->qpdf_writer->setR3EncryptionParameters(
  615 + user_password, owner_password,
  616 + allow_accessibility, allow_extract,
  617 + allow_assemble, allow_annotate_and_form,
  618 + allow_form_filling, allow_modify_other,
  619 + print);
  620 +}
  621 +
  622 +void qpdf_set_r4_encryption_parameters2(
  623 + qpdf_data qpdf, char const* user_password, char const* owner_password,
  624 + QPDF_BOOL allow_accessibility, QPDF_BOOL allow_extract,
  625 + QPDF_BOOL allow_assemble, QPDF_BOOL allow_annotate_and_form,
  626 + QPDF_BOOL allow_form_filling, QPDF_BOOL allow_modify_other,
  627 + enum qpdf_r3_print_e print,
  628 + QPDF_BOOL encrypt_metadata, QPDF_BOOL use_aes)
  629 +{
  630 + QTC::TC("qpdf", "qpdf-c called qpdf_set_r4_encryption_parameters");
  631 + qpdf->qpdf_writer->setR4EncryptionParameters(
  632 + user_password, owner_password,
  633 + allow_accessibility, allow_extract,
  634 + allow_assemble, allow_annotate_and_form,
  635 + allow_form_filling, allow_modify_other,
  636 + print, encrypt_metadata, use_aes);
  637 +}
  638 +
  639 +
  640 +void qpdf_set_r5_encryption_parameters2(
  641 + qpdf_data qpdf, char const* user_password, char const* owner_password,
  642 + QPDF_BOOL allow_accessibility, QPDF_BOOL allow_extract,
  643 + QPDF_BOOL allow_assemble, QPDF_BOOL allow_annotate_and_form,
  644 + QPDF_BOOL allow_form_filling, QPDF_BOOL allow_modify_other,
  645 + enum qpdf_r3_print_e print, QPDF_BOOL encrypt_metadata)
  646 +{
  647 + QTC::TC("qpdf", "qpdf-c called qpdf_set_r5_encryption_parameters");
  648 + qpdf->qpdf_writer->setR5EncryptionParameters(
  649 + user_password, owner_password,
  650 + allow_accessibility, allow_extract,
  651 + allow_assemble, allow_annotate_and_form,
  652 + allow_form_filling, allow_modify_other,
  653 + print, encrypt_metadata);
  654 +}
  655 +
  656 +void qpdf_set_r6_encryption_parameters2(
  657 + qpdf_data qpdf, char const* user_password, char const* owner_password,
  658 + QPDF_BOOL allow_accessibility, QPDF_BOOL allow_extract,
  659 + QPDF_BOOL allow_assemble, QPDF_BOOL allow_annotate_and_form,
  660 + QPDF_BOOL allow_form_filling, QPDF_BOOL allow_modify_other,
  661 + enum qpdf_r3_print_e print, QPDF_BOOL encrypt_metadata)
  662 +{
  663 + QTC::TC("qpdf", "qpdf-c called qpdf_set_r6_encryption_parameters");
  664 + qpdf->qpdf_writer->setR6EncryptionParameters(
  665 + user_password, owner_password,
  666 + allow_accessibility, allow_extract,
  667 + allow_assemble, allow_annotate_and_form,
  668 + allow_form_filling, allow_modify_other,
  669 + print, encrypt_metadata);
  670 +}
  671 +
606 void qpdf_set_r3_encryption_parameters( 672 void qpdf_set_r3_encryption_parameters(
607 qpdf_data qpdf, char const* user_password, char const* owner_password, 673 qpdf_data qpdf, char const* user_password, char const* owner_password,
608 QPDF_BOOL allow_accessibility, QPDF_BOOL allow_extract, 674 QPDF_BOOL allow_accessibility, QPDF_BOOL allow_extract,
609 qpdf_r3_print_e print, qpdf_r3_modify_e modify) 675 qpdf_r3_print_e print, qpdf_r3_modify_e modify)
610 { 676 {
611 - QTC::TC("qpdf", "qpdf-c called qpdf_set_r3_encryption_parameters");  
612 qpdf->qpdf_writer->setR3EncryptionParameters( 677 qpdf->qpdf_writer->setR3EncryptionParameters(
613 user_password, owner_password, 678 user_password, owner_password,
614 allow_accessibility, allow_extract, print, modify); 679 allow_accessibility, allow_extract, print, modify);
@@ -620,7 +685,6 @@ void qpdf_set_r4_encryption_parameters( @@ -620,7 +685,6 @@ void qpdf_set_r4_encryption_parameters(
620 qpdf_r3_print_e print, qpdf_r3_modify_e modify, 685 qpdf_r3_print_e print, qpdf_r3_modify_e modify,
621 QPDF_BOOL encrypt_metadata, QPDF_BOOL use_aes) 686 QPDF_BOOL encrypt_metadata, QPDF_BOOL use_aes)
622 { 687 {
623 - QTC::TC("qpdf", "qpdf-c called qpdf_set_r4_encryption_parameters");  
624 qpdf->qpdf_writer->setR4EncryptionParameters( 688 qpdf->qpdf_writer->setR4EncryptionParameters(
625 user_password, owner_password, 689 user_password, owner_password,
626 allow_accessibility, allow_extract, print, modify, 690 allow_accessibility, allow_extract, print, modify,
@@ -633,7 +697,6 @@ void qpdf_set_r5_encryption_parameters( @@ -633,7 +697,6 @@ void qpdf_set_r5_encryption_parameters(
633 qpdf_r3_print_e print, qpdf_r3_modify_e modify, 697 qpdf_r3_print_e print, qpdf_r3_modify_e modify,
634 QPDF_BOOL encrypt_metadata) 698 QPDF_BOOL encrypt_metadata)
635 { 699 {
636 - QTC::TC("qpdf", "qpdf-c called qpdf_set_r5_encryption_parameters");  
637 qpdf->qpdf_writer->setR5EncryptionParameters( 700 qpdf->qpdf_writer->setR5EncryptionParameters(
638 user_password, owner_password, 701 user_password, owner_password,
639 allow_accessibility, allow_extract, print, modify, 702 allow_accessibility, allow_extract, print, modify,
@@ -646,7 +709,6 @@ void qpdf_set_r6_encryption_parameters( @@ -646,7 +709,6 @@ void qpdf_set_r6_encryption_parameters(
646 qpdf_r3_print_e print, qpdf_r3_modify_e modify, 709 qpdf_r3_print_e print, qpdf_r3_modify_e modify,
647 QPDF_BOOL encrypt_metadata) 710 QPDF_BOOL encrypt_metadata)
648 { 711 {
649 - QTC::TC("qpdf", "qpdf-c called qpdf_set_r6_encryption_parameters");  
650 qpdf->qpdf_writer->setR6EncryptionParameters( 712 qpdf->qpdf_writer->setR6EncryptionParameters(
651 user_password, owner_password, 713 user_password, owner_password,
652 allow_accessibility, allow_extract, print, modify, 714 allow_accessibility, allow_extract, print, modify,
qpdf/qpdf-ctest.c
@@ -303,9 +303,10 @@ static void test12(char const* infile, @@ -303,9 +303,10 @@ static void test12(char const* infile,
303 qpdf_read(qpdf, infile, password); 303 qpdf_read(qpdf, infile, password);
304 qpdf_init_write(qpdf, outfile); 304 qpdf_init_write(qpdf, outfile);
305 qpdf_set_static_ID(qpdf, QPDF_TRUE); 305 qpdf_set_static_ID(qpdf, QPDF_TRUE);
306 - qpdf_set_r3_encryption_parameters( 306 + qpdf_set_r3_encryption_parameters2(
307 qpdf, "user2", "owner2", QPDF_TRUE, QPDF_TRUE, 307 qpdf, "user2", "owner2", QPDF_TRUE, QPDF_TRUE,
308 - qpdf_r3p_low, qpdf_r3m_all); 308 + QPDF_TRUE, QPDF_TRUE, QPDF_TRUE, QPDF_TRUE,
  309 + qpdf_r3p_low);
309 qpdf_write(qpdf); 310 qpdf_write(qpdf);
310 report_errors(); 311 report_errors();
311 } 312 }
@@ -350,9 +351,10 @@ static void test15(char const* infile, @@ -350,9 +351,10 @@ static void test15(char const* infile,
350 qpdf_init_write(qpdf, outfile); 351 qpdf_init_write(qpdf, outfile);
351 qpdf_set_static_ID(qpdf, QPDF_TRUE); 352 qpdf_set_static_ID(qpdf, QPDF_TRUE);
352 qpdf_set_static_aes_IV(qpdf, QPDF_TRUE); 353 qpdf_set_static_aes_IV(qpdf, QPDF_TRUE);
353 - qpdf_set_r4_encryption_parameters( 354 + qpdf_set_r4_encryption_parameters2(
354 qpdf, "user2", "owner2", QPDF_TRUE, QPDF_TRUE, 355 qpdf, "user2", "owner2", QPDF_TRUE, QPDF_TRUE,
355 - qpdf_r3p_low, qpdf_r3m_all, QPDF_TRUE, QPDF_TRUE); 356 + QPDF_TRUE, QPDF_TRUE, QPDF_TRUE, QPDF_TRUE,
  357 + qpdf_r3p_low, QPDF_TRUE, QPDF_TRUE);
356 qpdf_write(qpdf); 358 qpdf_write(qpdf);
357 report_errors(); 359 report_errors();
358 } 360 }
@@ -405,9 +407,10 @@ static void test17(char const* infile, @@ -405,9 +407,10 @@ static void test17(char const* infile,
405 qpdf_init_write(qpdf, outfile); 407 qpdf_init_write(qpdf, outfile);
406 qpdf_set_static_ID(qpdf, QPDF_TRUE); 408 qpdf_set_static_ID(qpdf, QPDF_TRUE);
407 qpdf_set_static_aes_IV(qpdf, QPDF_TRUE); 409 qpdf_set_static_aes_IV(qpdf, QPDF_TRUE);
408 - qpdf_set_r5_encryption_parameters( 410 + qpdf_set_r5_encryption_parameters2(
409 qpdf, "user3", "owner3", QPDF_TRUE, QPDF_TRUE, 411 qpdf, "user3", "owner3", QPDF_TRUE, QPDF_TRUE,
410 - qpdf_r3p_low, qpdf_r3m_all, QPDF_TRUE); 412 + QPDF_TRUE, QPDF_TRUE, QPDF_TRUE, QPDF_TRUE,
  413 + qpdf_r3p_low, QPDF_TRUE);
411 qpdf_write(qpdf); 414 qpdf_write(qpdf);
412 report_errors(); 415 report_errors();
413 } 416 }
@@ -421,9 +424,10 @@ static void test18(char const* infile, @@ -421,9 +424,10 @@ static void test18(char const* infile,
421 qpdf_init_write(qpdf, outfile); 424 qpdf_init_write(qpdf, outfile);
422 qpdf_set_static_ID(qpdf, QPDF_TRUE); 425 qpdf_set_static_ID(qpdf, QPDF_TRUE);
423 qpdf_set_static_aes_IV(qpdf, QPDF_TRUE); 426 qpdf_set_static_aes_IV(qpdf, QPDF_TRUE);
424 - qpdf_set_r6_encryption_parameters( 427 + qpdf_set_r6_encryption_parameters2(
425 qpdf, "user4", "owner4", QPDF_TRUE, QPDF_TRUE, 428 qpdf, "user4", "owner4", QPDF_TRUE, QPDF_TRUE,
426 - qpdf_r3p_low, qpdf_r3m_all, QPDF_TRUE); 429 + QPDF_TRUE, QPDF_TRUE, QPDF_TRUE, QPDF_TRUE,
  430 + qpdf_r3p_low, QPDF_TRUE);
427 qpdf_write(qpdf); 431 qpdf_write(qpdf);
428 report_errors(); 432 report_errors();
429 } 433 }
qpdf/qpdf.cc
@@ -80,8 +80,11 @@ struct Options @@ -80,8 +80,11 @@ struct Options
80 r2_annotate(true), 80 r2_annotate(true),
81 r3_accessibility(true), 81 r3_accessibility(true),
82 r3_extract(true), 82 r3_extract(true),
  83 + r3_assemble(true),
  84 + r3_annotate_and_form(true),
  85 + r3_form_filling(true),
  86 + r3_modify_other(true),
83 r3_print(qpdf_r3p_full), 87 r3_print(qpdf_r3p_full),
84 - r3_modify(qpdf_r3m_all),  
85 force_V4(false), 88 force_V4(false),
86 force_R5(false), 89 force_R5(false),
87 cleartext_metadata(false), 90 cleartext_metadata(false),
@@ -160,8 +163,11 @@ struct Options @@ -160,8 +163,11 @@ struct Options
160 bool r2_annotate; 163 bool r2_annotate;
161 bool r3_accessibility; 164 bool r3_accessibility;
162 bool r3_extract; 165 bool r3_extract;
  166 + bool r3_assemble;
  167 + bool r3_annotate_and_form;
  168 + bool r3_form_filling;
  169 + bool r3_modify_other;
163 qpdf_r3_print_e r3_print; 170 qpdf_r3_print_e r3_print;
164 - qpdf_r3_modify_e r3_modify;  
165 bool force_V4; 171 bool force_V4;
166 bool force_R5; 172 bool force_R5;
167 bool cleartext_metadata; 173 bool cleartext_metadata;
@@ -1863,23 +1869,38 @@ ArgParser::arg128Modify(char* parameter) @@ -1863,23 +1869,38 @@ ArgParser::arg128Modify(char* parameter)
1863 { 1869 {
1864 if (strcmp(parameter, "all") == 0) 1870 if (strcmp(parameter, "all") == 0)
1865 { 1871 {
1866 - o.r3_modify = qpdf_r3m_all; 1872 + o.r3_assemble = true;
  1873 + o.r3_annotate_and_form = true;
  1874 + o.r3_form_filling = true;
  1875 + o.r3_modify_other = true;
1867 } 1876 }
1868 else if (strcmp(parameter, "annotate") == 0) 1877 else if (strcmp(parameter, "annotate") == 0)
1869 { 1878 {
1870 - o.r3_modify = qpdf_r3m_annotate; 1879 + o.r3_assemble = true;
  1880 + o.r3_annotate_and_form = true;
  1881 + o.r3_form_filling = true;
  1882 + o.r3_modify_other = false;
1871 } 1883 }
1872 else if (strcmp(parameter, "form") == 0) 1884 else if (strcmp(parameter, "form") == 0)
1873 { 1885 {
1874 - o.r3_modify = qpdf_r3m_form; 1886 + o.r3_assemble = true;
  1887 + o.r3_annotate_and_form = false;
  1888 + o.r3_form_filling = true;
  1889 + o.r3_modify_other = false;
1875 } 1890 }
1876 else if (strcmp(parameter, "assembly") == 0) 1891 else if (strcmp(parameter, "assembly") == 0)
1877 { 1892 {
1878 - o.r3_modify = qpdf_r3m_assembly; 1893 + o.r3_assemble = true;
  1894 + o.r3_annotate_and_form = false;
  1895 + o.r3_form_filling = false;
  1896 + o.r3_modify_other = false;
1879 } 1897 }
1880 else if (strcmp(parameter, "none") == 0) 1898 else if (strcmp(parameter, "none") == 0)
1881 { 1899 {
1882 - o.r3_modify = qpdf_r3m_none; 1900 + o.r3_assemble = false;
  1901 + o.r3_annotate_and_form = false;
  1902 + o.r3_form_filling = false;
  1903 + o.r3_modify_other = false;
1883 } 1904 }
1884 else 1905 else
1885 { 1906 {
@@ -4030,25 +4051,34 @@ static void set_encryption_options(QPDF&amp; pdf, Options&amp; o, QPDFWriter&amp; w) @@ -4030,25 +4051,34 @@ static void set_encryption_options(QPDF&amp; pdf, Options&amp; o, QPDFWriter&amp; w)
4030 case 3: 4051 case 3:
4031 w.setR3EncryptionParameters( 4052 w.setR3EncryptionParameters(
4032 o.user_password.c_str(), o.owner_password.c_str(), 4053 o.user_password.c_str(), o.owner_password.c_str(),
4033 - o.r3_accessibility, o.r3_extract, o.r3_print, o.r3_modify); 4054 + o.r3_accessibility, o.r3_extract,
  4055 + o.r3_assemble, o.r3_annotate_and_form,
  4056 + o.r3_form_filling, o.r3_modify_other,
  4057 + o.r3_print);
4034 break; 4058 break;
4035 case 4: 4059 case 4:
4036 w.setR4EncryptionParameters( 4060 w.setR4EncryptionParameters(
4037 o.user_password.c_str(), o.owner_password.c_str(), 4061 o.user_password.c_str(), o.owner_password.c_str(),
4038 - o.r3_accessibility, o.r3_extract, o.r3_print, o.r3_modify,  
4039 - !o.cleartext_metadata, o.use_aes); 4062 + o.r3_accessibility, o.r3_extract,
  4063 + o.r3_assemble, o.r3_annotate_and_form,
  4064 + o.r3_form_filling, o.r3_modify_other,
  4065 + o.r3_print, !o.cleartext_metadata, o.use_aes);
4040 break; 4066 break;
4041 case 5: 4067 case 5:
4042 w.setR5EncryptionParameters( 4068 w.setR5EncryptionParameters(
4043 o.user_password.c_str(), o.owner_password.c_str(), 4069 o.user_password.c_str(), o.owner_password.c_str(),
4044 - o.r3_accessibility, o.r3_extract, o.r3_print, o.r3_modify,  
4045 - !o.cleartext_metadata); 4070 + o.r3_accessibility, o.r3_extract,
  4071 + o.r3_assemble, o.r3_annotate_and_form,
  4072 + o.r3_form_filling, o.r3_modify_other,
  4073 + o.r3_print, !o.cleartext_metadata);
4046 break; 4074 break;
4047 case 6: 4075 case 6:
4048 w.setR6EncryptionParameters( 4076 w.setR6EncryptionParameters(
4049 o.user_password.c_str(), o.owner_password.c_str(), 4077 o.user_password.c_str(), o.owner_password.c_str(),
4050 - o.r3_accessibility, o.r3_extract, o.r3_print, o.r3_modify,  
4051 - !o.cleartext_metadata); 4078 + o.r3_accessibility, o.r3_extract,
  4079 + o.r3_assemble, o.r3_annotate_and_form,
  4080 + o.r3_form_filling, o.r3_modify_other,
  4081 + o.r3_print, !o.cleartext_metadata);
4052 break; 4082 break;
4053 default: 4083 default:
4054 throw std::logic_error("bad encryption R value"); 4084 throw std::logic_error("bad encryption R value");