Commit 5e0ba126871c57a8a688b36614f2b8d78c2675b3
Committed by
Jay Berkenbilt
1 parent
3094955d
Fix /Contents value representation in a signature dictionary
Table 8.93 "Entries in a signature dictionary" in PDF 1.5 reference describes that the value of Contents entry is a hexadecimal string representation when ByteRange is specified. This commit makes QPDF always uses hexadecimal strings representation instead of literal strings for it.
Showing
6 changed files
with
43 additions
and
1 deletions
include/qpdf/QPDFWriter.hh
| @@ -470,6 +470,7 @@ class QPDFWriter | @@ -470,6 +470,7 @@ class QPDFWriter | ||
| 470 | static int const f_stream = 1 << 0; | 470 | static int const f_stream = 1 << 0; |
| 471 | static int const f_filtered = 1 << 1; | 471 | static int const f_filtered = 1 << 1; |
| 472 | static int const f_in_ostream = 1 << 2; | 472 | static int const f_in_ostream = 1 << 2; |
| 473 | + static int const f_hex_string = 1 << 3; | ||
| 473 | 474 | ||
| 474 | enum trailer_e { t_normal, t_lin_first, t_lin_second }; | 475 | enum trailer_e { t_normal, t_lin_first, t_lin_second }; |
| 475 | 476 |
libqpdf/QPDFWriter.cc
| @@ -1687,7 +1687,20 @@ QPDFWriter::unparseObject(QPDFObjectHandle object, int level, | @@ -1687,7 +1687,20 @@ QPDFWriter::unparseObject(QPDFObjectHandle object, int level, | ||
| 1687 | writeStringNoQDF(" "); | 1687 | writeStringNoQDF(" "); |
| 1688 | writeString(QPDF_Name::normalizeName(key)); | 1688 | writeString(QPDF_Name::normalizeName(key)); |
| 1689 | writeString(" "); | 1689 | writeString(" "); |
| 1690 | - unparseChild(object.getKey(key), level + 1, child_flags); | 1690 | + if (key == "/Contents" && |
| 1691 | + object.hasKey("/Type") && | ||
| 1692 | + object.getKey("/Type").isName() && | ||
| 1693 | + object.getKey("/Type").getName() == "/Sig" && | ||
| 1694 | + object.hasKey("/ByteRange")) | ||
| 1695 | + { | ||
| 1696 | + QTC::TC("qpdf", "QPDFWriter no encryption sig contents"); | ||
| 1697 | + unparseChild(object.getKey(key), level + 1, | ||
| 1698 | + child_flags | f_hex_string); | ||
| 1699 | + } | ||
| 1700 | + else | ||
| 1701 | + { | ||
| 1702 | + unparseChild(object.getKey(key), level + 1, child_flags); | ||
| 1703 | + } | ||
| 1691 | writeStringQDF("\n"); | 1704 | writeStringQDF("\n"); |
| 1692 | } | 1705 | } |
| 1693 | 1706 | ||
| @@ -1882,6 +1895,10 @@ QPDFWriter::unparseObject(QPDFObjectHandle object, int level, | @@ -1882,6 +1895,10 @@ QPDFWriter::unparseObject(QPDFObjectHandle object, int level, | ||
| 1882 | val = QPDF_String(std::string(tmp, vlen)).unparse(); | 1895 | val = QPDF_String(std::string(tmp, vlen)).unparse(); |
| 1883 | } | 1896 | } |
| 1884 | } | 1897 | } |
| 1898 | + else if (flags & f_hex_string) | ||
| 1899 | + { | ||
| 1900 | + val = QPDF_String(object.getStringValue()).unparse(true); | ||
| 1901 | + } | ||
| 1885 | else | 1902 | else |
| 1886 | { | 1903 | { |
| 1887 | val = object.unparseResolved(); | 1904 | val = object.unparseResolved(); |
qpdf/qpdf.testcov
| @@ -446,3 +446,4 @@ QPDF_encryption user matches owner V < 5 0 | @@ -446,3 +446,4 @@ QPDF_encryption user matches owner V < 5 0 | ||
| 446 | QPDF_encryption same password 1 | 446 | QPDF_encryption same password 1 |
| 447 | QPDFWriter stream in ostream 0 | 447 | QPDFWriter stream in ostream 0 |
| 448 | QPDFObjectHandle duplicate dict key 0 | 448 | QPDFObjectHandle duplicate dict key 0 |
| 449 | +QPDFWriter no encryption sig contents 0 |
qpdf/qtest/qpdf.test
| @@ -3997,6 +3997,28 @@ $td->runtest("fix-qdf with big object stream", # > 255 objects in a stream | @@ -3997,6 +3997,28 @@ $td->runtest("fix-qdf with big object stream", # > 255 objects in a stream | ||
| 3997 | 3997 | ||
| 3998 | show_ntests(); | 3998 | show_ntests(); |
| 3999 | # ---------- | 3999 | # ---------- |
| 4000 | +$td->notify("--- Signature Dictionary ---"); | ||
| 4001 | +$n_tests += 4; | ||
| 4002 | + | ||
| 4003 | +foreach my $i (qw(preserve disable)) | ||
| 4004 | +{ | ||
| 4005 | + $td->runtest("sig dict contents hex (object-streams=$i)", | ||
| 4006 | + {$td->COMMAND => | ||
| 4007 | + "qpdf --object-streams=$i digitally-signed.pdf a.pdf"}, | ||
| 4008 | + {$td->STRING => "", | ||
| 4009 | + $td->EXIT_STATUS => 0}); | ||
| 4010 | + # Use grep -f rather than writing something in test_driver because | ||
| 4011 | + # the point of the test is to ensure that the contents appears in | ||
| 4012 | + # the output file in the correct format. | ||
| 4013 | + $td->runtest("find desired contents (object-streams=$i)", | ||
| 4014 | + {$td->COMMAND => | ||
| 4015 | + "grep -f digitally-signed-sig-dict-contents.out a.pdf"}, | ||
| 4016 | + {$td->REGEXP => ".*", | ||
| 4017 | + $td->EXIT_STATUS => 0}); | ||
| 4018 | +} | ||
| 4019 | + | ||
| 4020 | +show_ntests(); | ||
| 4021 | +# ---------- | ||
| 4000 | $td->notify("--- Large File Tests ---"); | 4022 | $td->notify("--- Large File Tests ---"); |
| 4001 | my $nlarge = 1; | 4023 | my $nlarge = 1; |
| 4002 | if (defined $large_file_test_path) | 4024 | if (defined $large_file_test_path) |
qpdf/qtest/qpdf/digitally-signed-sig-dict-contents.out
0 → 100644
| 1 | +<3082053e06092a864886f70d010702a082052f3082052b020101310f300d06096086480165030402010500300b06092a864886f70d010701a082032a308203263082020ea003020102020a89839b114e3fe6fb56c0300d06092a864886f70d01010b050030413111300f060355040313084a6f686e20446f65311f301d06092a864886f70d01090116106a646f65406578616d706c652e6f7267310b3009060355040613024a50301e170d3139303932373131303335385a170d3234303932373131303335385a30413111300f060355040313084a6f686e20446f65311f301d06092a864886f70d01090116106a646f65406578616d706c652e6f7267310b3009060355040613024a5030820122300d06092a864886f70d01010105000382010f003082010a0282010100a7aa77c89dd7162ba40a510f82381d947d4e3e37722d8e9ab6d1fac80f65d554693266ca556fbab60821c14028bc815c1db5ec4e8376573b2bdb39a3e97395203479c3f0fc31bf20700c40ff734f61fb78c393f753dff74213b66c4d87dea828e4ac05d10da91e9eb03b3fd1b1f70c33b93dd7dd5b2207baa7e2868a782ca65ec351063720c3cca067b99022e576b5382930a502e22ccb096bab7546cb08b9258c86c255555cd6adc3522960b9c77d4928aebff4efd1d2fa8cd398219ce615c6f5055a8833970838096bc89d51e840977a2460e7b4aed0bfeb21a9a7adb7f2e5692d9c050f4d51fd4fd70c52cb0657e83be335365883beab77557d0462c3d60f0203010001a320301e300f06092a864886f72f01010a04020500300b0603551d0f040403020780300d06092a864886f70d01010b0500038201010063250d3d7f8ba247a2287f601932600f1eb3aa4b4c46a329807a3282e4783925bde4f0cf3efaa9050d5b5c9862c1d192eaf9fb709c21c3ed352033335e79adb04cdb8221916eb6149fb414b51dcd9fa30c271f9b4ca13fadd4f490103fb9b6a0b9341cc3d308db53f0220a38edaa57ae14d231036ef33e61b0e90b2ce618947df1001648960bf502e0fb155d522edffcebf62fcc339bd800540cbe8b4075da6fcdcbcbc6865ee4adc6619faabe0f6cb95b8bc0a11b1f420205901df3ccbaabf04c91dcdba6015aa9d2c7a5b337e730965e8288b5c8362c60ce56d8fd559ebe02d51d315baeaae995a291cd4aad77e74b9c6946110f2a97c9c935ebe334f45ffe318201d8308201d4020101304f30413111300f060355040313084a6f686e20446f65311f301d06092a864886f70d01090116106a646f65406578616d706c652e6f7267310b3009060355040613024a50020a89839b114e3fe6fb56c0300d06096086480165030402010500a05c300f06092a864886f72f01010831023000301806092a864886f70d010903310b06092a864886f70d010701302f06092a864886f70d0109043122042086a00dff97b85b073bc5bf33e259238db835b1357957eef1c0e882e44167a697300d06092a864886f70d01010b0500048201005cfe06ea79c8bc21e8ea5baa67290841a2683109a04410f73a3c9569945de91d5dfa6d0c18d03626b308415c8823abcd616a85af7e4aa9697b94ff73e2282ef961f5a30f0027f1744a54b4af166d239f97d00eea66701445d45145bd3e2362e989f9f4b7f27990d60892bacc011c9cfc6d9bf119ac9de4e2c43e9a1e10a99b807e10b2e759ead8ad5e4c4d02a94ea83739d603606b2deddd063a19c808f6580cd2d7d22e5d2876054d6386c006abf8e57ca6c1fa8f24f29f106d33052a8f83e6b03fa926d78078d84d5952b1058c9e4761f5ea0ad183b07a99e7c2f86f97838147297f80314c8668639dc1dcc4a5ff4cf4271bd1e4eaa32c4f261f327e031c0c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000> | ||
| 0 | \ No newline at end of file | 2 | \ No newline at end of file |
qpdf/qtest/qpdf/digitally-signed.pdf
0 → 100644
No preview for this file type