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 16  
17 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 28 * Add versions of utf8 to single-byte character transcoders that
20 29 return a success code.
21 30  
... ...
include/qpdf/Constants.h
... ... @@ -80,13 +80,18 @@ enum qpdf_r3_print_e
80 80 qpdf_r3p_low, /* allow only low-resolution printing */
81 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 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 97 /* Form field flags from the PDF spec */
... ...
include/qpdf/QPDFWriter.hh
... ... @@ -344,6 +344,39 @@ class QPDFWriter
344 344 // AES is used, 1.6, and setting R5 or R6 parameters pushes the
345 345 // version to at least 1.7 with extension level 3.
346 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 380 void setR2EncryptionParameters(
348 381 char const* user_password, char const* owner_password,
349 382 bool allow_print, bool allow_modify,
... ... @@ -359,9 +392,6 @@ class QPDFWriter
359 392 bool allow_accessibility, bool allow_extract,
360 393 qpdf_r3_print_e print, qpdf_r3_modify_e modify,
361 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 395 QPDF_DLL
366 396 void setR5EncryptionParameters(
367 397 char const* user_password, char const* owner_password,
... ... @@ -459,6 +489,8 @@ class QPDFWriter
459 489 std::set<int>& bits_to_clear,
460 490 char const* user_password, char const* owner_password,
461 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 494 qpdf_r3_print_e print, qpdf_r3_modify_e modify);
463 495 void disableIncompatibleEncryption(int major, int minor,
464 496 int extension_level);
... ...
include/qpdf/qpdf-c.h
... ... @@ -390,6 +390,40 @@ extern &quot;C&quot; {
390 390 QPDF_BOOL allow_extract, QPDF_BOOL allow_annotate);
391 391  
392 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 427 void qpdf_set_r3_encryption_parameters(
394 428 qpdf_data qpdf, char const* user_password, char const* owner_password,
395 429 QPDF_BOOL allow_accessibility, QPDF_BOOL allow_extract,
... ...
libqpdf/QPDFWriter.cc
... ... @@ -409,7 +409,26 @@ QPDFWriter::setR3EncryptionParameters(
409 409 std::set<int> clear;
410 410 interpretR3EncryptionParameters(
411 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 432 setEncryptionParameters(user_password, owner_password, 2, 3, 16, clear);
414 433 }
415 434  
... ... @@ -423,7 +442,29 @@ QPDFWriter::setR4EncryptionParameters(
423 442 std::set<int> clear;
424 443 interpretR3EncryptionParameters(
425 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 468 this->m->encrypt_use_aes = use_aes;
428 469 this->m->encrypt_metadata = encrypt_metadata;
429 470 setEncryptionParameters(user_password, owner_password, 4, 4, 16, clear);
... ... @@ -439,7 +480,29 @@ QPDFWriter::setR5EncryptionParameters(
439 480 std::set<int> clear;
440 481 interpretR3EncryptionParameters(
441 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 506 this->m->encrypt_use_aes = true;
444 507 this->m->encrypt_metadata = encrypt_metadata;
445 508 setEncryptionParameters(user_password, owner_password, 5, 5, 32, clear);
... ... @@ -455,7 +518,29 @@ QPDFWriter::setR6EncryptionParameters(
455 518 std::set<int> clear;
456 519 interpretR3EncryptionParameters(
457 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 544 this->m->encrypt_use_aes = true;
460 545 this->m->encrypt_metadata = encrypt_metadata;
461 546 setEncryptionParameters(user_password, owner_password, 5, 6, 32, clear);
... ... @@ -466,6 +551,8 @@ QPDFWriter::interpretR3EncryptionParameters(
466 551 std::set<int>& clear,
467 552 char const* user_password, char const* owner_password,
468 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 556 qpdf_r3_print_e print, qpdf_r3_modify_e modify)
470 557 {
471 558 // Acrobat 5 security options:
... ... @@ -486,8 +573,21 @@ QPDFWriter::interpretR3EncryptionParameters(
486 573 // Low Resolution
487 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 588 if (! allow_accessibility)
490 589 {
  590 + // setEncryptionParameters sets this if R > 3
491 591 clear.insert(10);
492 592 }
493 593 if (! allow_extract)
... ... @@ -511,6 +611,13 @@ QPDFWriter::interpretR3EncryptionParameters(
511 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 621 switch (modify)
515 622 {
516 623 case qpdf_r3m_none:
... ... @@ -530,6 +637,24 @@ QPDFWriter::interpretR3EncryptionParameters(
530 637  
531 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 660 void
... ...
libqpdf/qpdf-c.cc
... ... @@ -603,12 +603,77 @@ void qpdf_set_r2_encryption_parameters(
603 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 672 void qpdf_set_r3_encryption_parameters(
607 673 qpdf_data qpdf, char const* user_password, char const* owner_password,
608 674 QPDF_BOOL allow_accessibility, QPDF_BOOL allow_extract,
609 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 677 qpdf->qpdf_writer->setR3EncryptionParameters(
613 678 user_password, owner_password,
614 679 allow_accessibility, allow_extract, print, modify);
... ... @@ -620,7 +685,6 @@ void qpdf_set_r4_encryption_parameters(
620 685 qpdf_r3_print_e print, qpdf_r3_modify_e modify,
621 686 QPDF_BOOL encrypt_metadata, QPDF_BOOL use_aes)
622 687 {
623   - QTC::TC("qpdf", "qpdf-c called qpdf_set_r4_encryption_parameters");
624 688 qpdf->qpdf_writer->setR4EncryptionParameters(
625 689 user_password, owner_password,
626 690 allow_accessibility, allow_extract, print, modify,
... ... @@ -633,7 +697,6 @@ void qpdf_set_r5_encryption_parameters(
633 697 qpdf_r3_print_e print, qpdf_r3_modify_e modify,
634 698 QPDF_BOOL encrypt_metadata)
635 699 {
636   - QTC::TC("qpdf", "qpdf-c called qpdf_set_r5_encryption_parameters");
637 700 qpdf->qpdf_writer->setR5EncryptionParameters(
638 701 user_password, owner_password,
639 702 allow_accessibility, allow_extract, print, modify,
... ... @@ -646,7 +709,6 @@ void qpdf_set_r6_encryption_parameters(
646 709 qpdf_r3_print_e print, qpdf_r3_modify_e modify,
647 710 QPDF_BOOL encrypt_metadata)
648 711 {
649   - QTC::TC("qpdf", "qpdf-c called qpdf_set_r6_encryption_parameters");
650 712 qpdf->qpdf_writer->setR6EncryptionParameters(
651 713 user_password, owner_password,
652 714 allow_accessibility, allow_extract, print, modify,
... ...
qpdf/qpdf-ctest.c
... ... @@ -303,9 +303,10 @@ static void test12(char const* infile,
303 303 qpdf_read(qpdf, infile, password);
304 304 qpdf_init_write(qpdf, outfile);
305 305 qpdf_set_static_ID(qpdf, QPDF_TRUE);
306   - qpdf_set_r3_encryption_parameters(
  306 + qpdf_set_r3_encryption_parameters2(
307 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 310 qpdf_write(qpdf);
310 311 report_errors();
311 312 }
... ... @@ -350,9 +351,10 @@ static void test15(char const* infile,
350 351 qpdf_init_write(qpdf, outfile);
351 352 qpdf_set_static_ID(qpdf, QPDF_TRUE);
352 353 qpdf_set_static_aes_IV(qpdf, QPDF_TRUE);
353   - qpdf_set_r4_encryption_parameters(
  354 + qpdf_set_r4_encryption_parameters2(
354 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 358 qpdf_write(qpdf);
357 359 report_errors();
358 360 }
... ... @@ -405,9 +407,10 @@ static void test17(char const* infile,
405 407 qpdf_init_write(qpdf, outfile);
406 408 qpdf_set_static_ID(qpdf, QPDF_TRUE);
407 409 qpdf_set_static_aes_IV(qpdf, QPDF_TRUE);
408   - qpdf_set_r5_encryption_parameters(
  410 + qpdf_set_r5_encryption_parameters2(
409 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 414 qpdf_write(qpdf);
412 415 report_errors();
413 416 }
... ... @@ -421,9 +424,10 @@ static void test18(char const* infile,
421 424 qpdf_init_write(qpdf, outfile);
422 425 qpdf_set_static_ID(qpdf, QPDF_TRUE);
423 426 qpdf_set_static_aes_IV(qpdf, QPDF_TRUE);
424   - qpdf_set_r6_encryption_parameters(
  427 + qpdf_set_r6_encryption_parameters2(
425 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 431 qpdf_write(qpdf);
428 432 report_errors();
429 433 }
... ...
qpdf/qpdf.cc
... ... @@ -80,8 +80,11 @@ struct Options
80 80 r2_annotate(true),
81 81 r3_accessibility(true),
82 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 87 r3_print(qpdf_r3p_full),
84   - r3_modify(qpdf_r3m_all),
85 88 force_V4(false),
86 89 force_R5(false),
87 90 cleartext_metadata(false),
... ... @@ -160,8 +163,11 @@ struct Options
160 163 bool r2_annotate;
161 164 bool r3_accessibility;
162 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 170 qpdf_r3_print_e r3_print;
164   - qpdf_r3_modify_e r3_modify;
165 171 bool force_V4;
166 172 bool force_R5;
167 173 bool cleartext_metadata;
... ... @@ -1863,23 +1869,38 @@ ArgParser::arg128Modify(char* parameter)
1863 1869 {
1864 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 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 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 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 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 1905 else
1885 1906 {
... ... @@ -4030,25 +4051,34 @@ static void set_encryption_options(QPDF&amp; pdf, Options&amp; o, QPDFWriter&amp; w)
4030 4051 case 3:
4031 4052 w.setR3EncryptionParameters(
4032 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 4058 break;
4035 4059 case 4:
4036 4060 w.setR4EncryptionParameters(
4037 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 4066 break;
4041 4067 case 5:
4042 4068 w.setR5EncryptionParameters(
4043 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 4074 break;
4047 4075 case 6:
4048 4076 w.setR6EncryptionParameters(
4049 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 4082 break;
4053 4083 default:
4054 4084 throw std::logic_error("bad encryption R value");
... ...