Commit fe122b0b8c8256b5cf5f824701923ded8439ae36

Authored by m-holger
1 parent fad1399f

Refactor `QPDFWriter` to remove `encryption_dictionary` member, streamline encry…

…ption dictionary generation, and reduce redundancy in encryption handling logic.
Showing 1 changed file with 43 additions and 38 deletions
libqpdf/QPDFWriter.cc
... ... @@ -89,7 +89,6 @@ class QPDFWriter::Members
89 89 std::unique_ptr<QPDF::EncryptionData> encryption;
90 90 std::string encryption_key;
91 91 bool encrypt_use_aes{false};
92   - std::map<std::string, std::string> encryption_dictionary;
93 92  
94 93 std::string id1; // for /ID key of
95 94 std::string id2; // trailer dictionary
... ... @@ -783,21 +782,7 @@ void
783 782 QPDFWriter::setEncryptionParametersInternal(
784 783 std::string const& user_password, std::string const& encryption_key)
785 784 {
786   - auto& enc = *m->encryption;
787   - auto const V = enc.getV();
788   - auto const R = enc.getR();
789   - m->encryption_dictionary["/Filter"] = "/Standard";
790   - m->encryption_dictionary["/V"] = std::to_string(enc.getV());
791   - m->encryption_dictionary["/Length"] = std::to_string(enc.getLengthBytes() * 8);
792   - m->encryption_dictionary["/R"] = std::to_string(enc.getR());
793   - m->encryption_dictionary["/P"] = std::to_string(enc.getP());
794   - m->encryption_dictionary["/O"] = QPDF_String(enc.getO()).unparse(true);
795   - m->encryption_dictionary["/U"] = QPDF_String(enc.getU()).unparse(true);
796   - if (V >= 5) {
797   - m->encryption_dictionary["/OE"] = QPDF_String(enc.getOE()).unparse(true);
798   - m->encryption_dictionary["/UE"] = QPDF_String(enc.getUE()).unparse(true);
799   - m->encryption_dictionary["/Perms"] = QPDF_String(enc.getPerms()).unparse(true);
800   - }
  785 + auto const R = m->encryption->getR();
801 786 if (R >= 6) {
802 787 setMinimumPDFVersion("1.7", 8);
803 788 } else if (R == 5) {
... ... @@ -810,23 +795,8 @@ QPDFWriter::setEncryptionParametersInternal(
810 795 setMinimumPDFVersion("1.3");
811 796 }
812 797  
813   - if (R >= 4 && !m->encryption->getEncryptMetadata()) {
814   - m->encryption_dictionary["/EncryptMetadata"] = "false";
815   - }
816   - if ((V == 4) || (V == 5)) {
817   - // The spec says the value for the crypt filter key can be anything, and xpdf seems to
818   - // agree. However, Adobe Reader won't open our files unless we use /StdCF.
819   - m->encryption_dictionary["/StmF"] = "/StdCF";
820   - m->encryption_dictionary["/StrF"] = "/StdCF";
821   - std::string method = (m->encrypt_use_aes ? ((V < 5) ? "/AESV2" : "/AESV3") : "/V2");
822   - // The PDF spec says the /Length key is optional, but the PDF previewer on some versions of
823   - // MacOS won't open encrypted files without it.
824   - m->encryption_dictionary["/CF"] = "<< /StdCF << /AuthEvent /DocOpen /CFM " + method +
825   - " /Length " + std::string((V < 5) ? "16" : "32") + " >> >>";
826   - }
827   -
828   - if (V < 5) {
829   - m->encryption_key = enc.compute_encryption_key(user_password);
  798 + if (m->encryption->getV() < 5) {
  799 + m->encryption_key = m->encryption->compute_encryption_key(user_password);
830 800 } else {
831 801 m->encryption_key = encryption_key;
832 802 }
... ... @@ -2310,13 +2280,48 @@ void
2310 2280 QPDFWriter::writeEncryptionDictionary()
2311 2281 {
2312 2282 m->encryption_dict_objid = openObject(m->encryption_dict_objid);
  2283 + auto& enc = *m->encryption;
  2284 + auto const V = enc.getV();
  2285 +
2313 2286 writeString("<<");
2314   - for (auto const& iter: m->encryption_dictionary) {
2315   - writeString(" ");
2316   - writeString(iter.first);
2317   - writeString(" ");
2318   - writeString(iter.second);
  2287 + if (V >= 4) {
  2288 + writeString(" /CF << /StdCF << /AuthEvent /DocOpen /CFM ");
  2289 + writeString(m->encrypt_use_aes ? ((V < 5) ? "/AESV2" : "/AESV3") : "/V2");
  2290 + // The PDF spec says the /Length key is optional, but the PDF previewer on some versions of
  2291 + // MacOS won't open encrypted files without it.
  2292 + writeString((V < 5) ? " /Length 16 >> >>" : " /Length 32 >> >>");
  2293 + if (!m->encryption->getEncryptMetadata()) {
  2294 + writeString(" /EncryptMetadata false");
  2295 + }
  2296 + }
  2297 + writeString(" /Filter /Standard /Length ");
  2298 + writeString(std::to_string(enc.getLengthBytes() * 8));
  2299 + writeString(" /O ");
  2300 + writeString(QPDF_String(enc.getO()).unparse(true));
  2301 + if (V >= 4) {
  2302 + writeString(" /OE ");
  2303 + writeString(QPDF_String(enc.getOE()).unparse(true));
  2304 + }
  2305 + writeString(" /P ");
  2306 + writeString(std::to_string(enc.getP()));
  2307 + if (V >= 5) {
  2308 + writeString(" /Perms ");
  2309 + writeString(QPDF_String(enc.getPerms()).unparse(true));
  2310 + }
  2311 + writeString(" /R ");
  2312 + writeString(std::to_string(enc.getR()));
  2313 +
  2314 + if (V >= 4) {
  2315 + writeString(" /StmF /StdCF /StrF /StdCF");
  2316 + }
  2317 + writeString(" /U ");
  2318 + writeString(QPDF_String(enc.getU()).unparse(true));
  2319 + if (V >= 4) {
  2320 + writeString(" /UE ");
  2321 + writeString(QPDF_String(enc.getUE()).unparse(true));
2319 2322 }
  2323 + writeString(" /V ");
  2324 + writeString(std::to_string(enc.getV()));
2320 2325 writeString(" >>");
2321 2326 closeObject(m->encryption_dict_objid);
2322 2327 }
... ...