Commit a15d0afa3e362ef7744f43c9a238c46ddd902cf6
1 parent
44fa03c6
Refactor `QPDFWriter`: move `generateID` and `getOriginalID1` to `QPDFWriter::Me…
…mbers` and update encryption parameter handling logic.
Showing
2 changed files
with
38 additions
and
32 deletions
include/qpdf/QPDFWriter.hh
| ... | ... | @@ -494,8 +494,6 @@ class QPDFWriter |
| 494 | 494 | void initializeSpecialStreams(); |
| 495 | 495 | void preserveObjectStreams(); |
| 496 | 496 | void generateObjectStreams(); |
| 497 | - std::string getOriginalID1(); | |
| 498 | - void generateID(bool encrypted); | |
| 499 | 497 | void interpretR3EncryptionParameters( |
| 500 | 498 | bool allow_accessibility, |
| 501 | 499 | bool allow_extract, | ... | ... |
libqpdf/QPDFWriter.cc
| ... | ... | @@ -285,10 +285,13 @@ class QPDFWriter::Members |
| 285 | 285 | } |
| 286 | 286 | |
| 287 | 287 | void setMinimumPDFVersion(std::string const& version, int extension_level); |
| 288 | + void copyEncryptionParameters(QPDF&); | |
| 288 | 289 | |
| 289 | 290 | void disableIncompatibleEncryption(int major, int minor, int extension_level); |
| 290 | 291 | void parseVersion(std::string const& version, int& major, int& minor) const; |
| 291 | 292 | int compareVersions(int major1, int minor1, int major2, int minor2) const; |
| 293 | + void generateID(bool encrypted); | |
| 294 | + std::string getOriginalID1(); | |
| 292 | 295 | |
| 293 | 296 | private: |
| 294 | 297 | QPDFWriter& w; |
| ... | ... | @@ -867,7 +870,7 @@ QPDFWriter::interpretR3EncryptionParameters( |
| 867 | 870 | void |
| 868 | 871 | QPDFWriter::setEncryptionParameters(char const* user_password, char const* owner_password) |
| 869 | 872 | { |
| 870 | - generateID(true); | |
| 873 | + m->generateID(true); | |
| 871 | 874 | m->encryption->setId1(m->id1); |
| 872 | 875 | m->encryption_key = m->encryption->compute_parameters(user_password, owner_password); |
| 873 | 876 | setEncryptionMinimumVersion(); |
| ... | ... | @@ -876,11 +879,17 @@ QPDFWriter::setEncryptionParameters(char const* user_password, char const* owner |
| 876 | 879 | void |
| 877 | 880 | QPDFWriter::copyEncryptionParameters(QPDF& qpdf) |
| 878 | 881 | { |
| 879 | - m->preserve_encryption = false; | |
| 882 | + m->copyEncryptionParameters(qpdf); | |
| 883 | +} | |
| 884 | + | |
| 885 | +void | |
| 886 | +QPDFWriter::Members::copyEncryptionParameters(QPDF& qpdf) | |
| 887 | +{ | |
| 888 | + preserve_encryption = false; | |
| 880 | 889 | QPDFObjectHandle trailer = qpdf.getTrailer(); |
| 881 | 890 | if (trailer.hasKey("/Encrypt")) { |
| 882 | 891 | generateID(true); |
| 883 | - m->id1 = trailer.getKey("/ID").getArrayItem(0).getStringValue(); | |
| 892 | + id1 = trailer.getKey("/ID").getArrayItem(0).getStringValue(); | |
| 884 | 893 | QPDFObjectHandle encrypt = trailer.getKey("/Encrypt"); |
| 885 | 894 | int V = encrypt.getKey("/V").getIntValueAsInt(); |
| 886 | 895 | int key_len = 5; |
| ... | ... | @@ -896,12 +905,12 @@ QPDFWriter::copyEncryptionParameters(QPDF& qpdf) |
| 896 | 905 | // Acrobat doesn't create files with V >= 4 that don't use AES, and the logic of |
| 897 | 906 | // figuring out whether AES is used or not is complicated with /StmF, /StrF, and /EFF |
| 898 | 907 | // all potentially having different values. |
| 899 | - m->encrypt_use_aes = true; | |
| 908 | + encrypt_use_aes = true; | |
| 900 | 909 | } |
| 901 | 910 | QTC::TC("qpdf", "QPDFWriter copy encrypt metadata", encrypt_metadata ? 0 : 1); |
| 902 | - QTC::TC("qpdf", "QPDFWriter copy use_aes", m->encrypt_use_aes ? 0 : 1); | |
| 911 | + QTC::TC("qpdf", "QPDFWriter copy use_aes", encrypt_use_aes ? 0 : 1); | |
| 903 | 912 | |
| 904 | - m->encryption = std::make_unique<QPDF::EncryptionData>( | |
| 913 | + encryption = std::make_unique<QPDF::EncryptionData>( | |
| 905 | 914 | V, |
| 906 | 915 | encrypt.getKey("/R").getIntValueAsInt(), |
| 907 | 916 | key_len, |
| ... | ... | @@ -911,12 +920,11 @@ QPDFWriter::copyEncryptionParameters(QPDF& qpdf) |
| 911 | 920 | V < 5 ? "" : encrypt.getKey("/OE").getStringValue(), |
| 912 | 921 | V < 5 ? "" : encrypt.getKey("/UE").getStringValue(), |
| 913 | 922 | V < 5 ? "" : encrypt.getKey("/Perms").getStringValue(), |
| 914 | - m->id1, // m->id1 == the other file's id1 | |
| 923 | + id1, // id1 == the other file's id1 | |
| 915 | 924 | encrypt_metadata); |
| 916 | - m->encryption_key = V >= 5 | |
| 917 | - ? qpdf.getEncryptionKey() | |
| 918 | - : m->encryption->compute_encryption_key(qpdf.getPaddedUserPassword()); | |
| 919 | - setEncryptionMinimumVersion(); | |
| 925 | + encryption_key = V >= 5 ? qpdf.getEncryptionKey() | |
| 926 | + : encryption->compute_encryption_key(qpdf.getPaddedUserPassword()); | |
| 927 | + w.setEncryptionMinimumVersion(); | |
| 920 | 928 | } |
| 921 | 929 | } |
| 922 | 930 | |
| ... | ... | @@ -1292,7 +1300,7 @@ QPDFWriter::writeTrailer( |
| 1292 | 1300 | // Write ID |
| 1293 | 1301 | write_qdf(" ").write(" /ID ["); |
| 1294 | 1302 | if (linearization_pass == 1) { |
| 1295 | - std::string original_id1 = getOriginalID1(); | |
| 1303 | + std::string original_id1 = m->getOriginalID1(); | |
| 1296 | 1304 | if (original_id1.empty()) { |
| 1297 | 1305 | write("<00000000000000000000000000000000>"); |
| 1298 | 1306 | } else { |
| ... | ... | @@ -1308,7 +1316,7 @@ QPDFWriter::writeTrailer( |
| 1308 | 1316 | if (linearization_pass == 0 && m->deterministic_id) { |
| 1309 | 1317 | computeDeterministicIDData(); |
| 1310 | 1318 | } |
| 1311 | - generateID(m->encryption.get()); | |
| 1319 | + m->generateID(m->encryption.get()); | |
| 1312 | 1320 | write_string(m->id1, true).write_string(m->id2, true); |
| 1313 | 1321 | } |
| 1314 | 1322 | write("]"); |
| ... | ... | @@ -1855,9 +1863,9 @@ QPDFWriter::writeObject(QPDFObjectHandle object, int object_stream_index) |
| 1855 | 1863 | } |
| 1856 | 1864 | |
| 1857 | 1865 | std::string |
| 1858 | -QPDFWriter::getOriginalID1() | |
| 1866 | +QPDFWriter::Members::getOriginalID1() | |
| 1859 | 1867 | { |
| 1860 | - QPDFObjectHandle trailer = m->pdf.getTrailer(); | |
| 1868 | + QPDFObjectHandle trailer = pdf.getTrailer(); | |
| 1861 | 1869 | if (trailer.hasKey("/ID")) { |
| 1862 | 1870 | return trailer.getKey("/ID").getArrayItem(0).getStringValue(); |
| 1863 | 1871 | } else { |
| ... | ... | @@ -1866,20 +1874,20 @@ QPDFWriter::getOriginalID1() |
| 1866 | 1874 | } |
| 1867 | 1875 | |
| 1868 | 1876 | void |
| 1869 | -QPDFWriter::generateID(bool encrypted) | |
| 1877 | +QPDFWriter::Members::generateID(bool encrypted) | |
| 1870 | 1878 | { |
| 1871 | 1879 | // Generate the ID lazily so that we can handle the user's preference to use static or |
| 1872 | 1880 | // deterministic ID generation. |
| 1873 | 1881 | |
| 1874 | - if (!m->id2.empty()) { | |
| 1882 | + if (!id2.empty()) { | |
| 1875 | 1883 | return; |
| 1876 | 1884 | } |
| 1877 | 1885 | |
| 1878 | - QPDFObjectHandle trailer = m->pdf.getTrailer(); | |
| 1886 | + QPDFObjectHandle trailer = pdf.getTrailer(); | |
| 1879 | 1887 | |
| 1880 | 1888 | std::string result; |
| 1881 | 1889 | |
| 1882 | - if (m->static_id) { | |
| 1890 | + if (static_id) { | |
| 1883 | 1891 | // For test suite use only... |
| 1884 | 1892 | static unsigned char tmp[] = { |
| 1885 | 1893 | 0x31, |
| ... | ... | @@ -1911,20 +1919,20 @@ QPDFWriter::generateID(bool encrypted) |
| 1911 | 1919 | // that case, would have the same ID regardless of the output file's name. |
| 1912 | 1920 | |
| 1913 | 1921 | std::string seed; |
| 1914 | - if (m->deterministic_id) { | |
| 1922 | + if (deterministic_id) { | |
| 1915 | 1923 | if (encrypted) { |
| 1916 | 1924 | throw std::runtime_error( |
| 1917 | 1925 | "QPDFWriter: unable to generated a deterministic ID because the file to be " |
| 1918 | 1926 | "written is encrypted (even though the file may not require a password)"); |
| 1919 | 1927 | } |
| 1920 | - if (m->deterministic_id_data.empty()) { | |
| 1928 | + if (deterministic_id_data.empty()) { | |
| 1921 | 1929 | throw std::logic_error( |
| 1922 | 1930 | "INTERNAL ERROR: QPDFWriter::generateID has no data for deterministic ID"); |
| 1923 | 1931 | } |
| 1924 | - seed += m->deterministic_id_data; | |
| 1932 | + seed += deterministic_id_data; | |
| 1925 | 1933 | } else { |
| 1926 | 1934 | seed += std::to_string(QUtil::get_current_time()); |
| 1927 | - seed += m->filename; | |
| 1935 | + seed += filename; | |
| 1928 | 1936 | seed += " "; |
| 1929 | 1937 | } |
| 1930 | 1938 | seed += " QPDF "; |
| ... | ... | @@ -1937,21 +1945,21 @@ QPDFWriter::generateID(bool encrypted) |
| 1937 | 1945 | } |
| 1938 | 1946 | } |
| 1939 | 1947 | |
| 1940 | - MD5 m; | |
| 1941 | - m.encodeString(seed.c_str()); | |
| 1948 | + MD5 md5; | |
| 1949 | + md5.encodeString(seed.c_str()); | |
| 1942 | 1950 | MD5::Digest digest; |
| 1943 | - m.digest(digest); | |
| 1951 | + md5.digest(digest); | |
| 1944 | 1952 | result = std::string(reinterpret_cast<char*>(digest), sizeof(MD5::Digest)); |
| 1945 | 1953 | } |
| 1946 | 1954 | |
| 1947 | 1955 | // If /ID already exists, follow the spec: use the original first word and generate a new second |
| 1948 | 1956 | // word. Otherwise, we'll use the generated ID for both. |
| 1949 | 1957 | |
| 1950 | - m->id2 = result; | |
| 1958 | + id2 = result; | |
| 1951 | 1959 | // Note: keep /ID from old file even if --static-id was given. |
| 1952 | - m->id1 = getOriginalID1(); | |
| 1953 | - if (m->id1.empty()) { | |
| 1954 | - m->id1 = m->id2; | |
| 1960 | + id1 = getOriginalID1(); | |
| 1961 | + if (id1.empty()) { | |
| 1962 | + id1 = id2; | |
| 1955 | 1963 | } |
| 1956 | 1964 | } |
| 1957 | 1965 | ... | ... |