Commit 9eb5982fa334a2db42a278fce853bd7ebd2a61a7

Authored by Jay Berkenbilt
1 parent 0ea70e5d

Avoid modifying trailer when writing

When preparing the trailer for writing to the new file, trim a copy of
the trailer instead of the original file's trailer.
include/qpdf/QPDFWriter.hh
... ... @@ -322,6 +322,7 @@ class QPDFWriter
322 322 void setDataKey(int objid);
323 323 int openObject(int objid = 0);
324 324 void closeObject(int objid);
  325 + QPDFObjectHandle getTrimmedTrailer();
325 326 void prepareFileForWrite();
326 327 void writeStandard();
327 328 void writeLinearized();
... ...
libqpdf/QPDFWriter.cc
... ... @@ -1057,7 +1057,7 @@ void
1057 1057 QPDFWriter::writeTrailer(trailer_e which, int size, bool xref_stream,
1058 1058 qpdf_offset_t prev)
1059 1059 {
1060   - QPDFObjectHandle trailer = pdf.getTrailer();
  1060 + QPDFObjectHandle trailer = getTrimmedTrailer();
1061 1061 if (! xref_stream)
1062 1062 {
1063 1063 writeString("trailer <<");
... ... @@ -1932,20 +1932,19 @@ QPDFWriter::generateObjectStreams()
1932 1932 }
1933 1933 }
1934 1934  
1935   -void
1936   -QPDFWriter::prepareFileForWrite()
  1935 +QPDFObjectHandle
  1936 +QPDFWriter::getTrimmedTrailer()
1937 1937 {
1938 1938 // Remove keys from the trailer that necessarily have to be
1939 1939 // replaced when writing the file.
1940 1940  
1941   - QPDFObjectHandle trailer = pdf.getTrailer();
  1941 + QPDFObjectHandle trailer = pdf.getTrailer().shallowCopy();
1942 1942  
1943   - // Note that removing the encryption dictionary does not interfere
1944   - // with reading encrypted files. QPDF loads all the information
1945   - // it needs from the encryption dictionary at the beginning and
1946   - // never looks at it again.
  1943 + // Remove encryption keys
1947 1944 trailer.removeKey("/ID");
1948 1945 trailer.removeKey("/Encrypt");
  1946 +
  1947 + // Remove modification information
1949 1948 trailer.removeKey("/Prev");
1950 1949  
1951 1950 // Remove all trailer keys that potentially come from a
... ... @@ -1958,6 +1957,12 @@ QPDFWriter::prepareFileForWrite()
1958 1957 trailer.removeKey("/Type");
1959 1958 trailer.removeKey("/XRefStm");
1960 1959  
  1960 + return trailer;
  1961 +}
  1962 +
  1963 +void
  1964 +QPDFWriter::prepareFileForWrite()
  1965 +{
1961 1966 // Do a traversal of the entire PDF file structure replacing all
1962 1967 // indirect objects that QPDFWriter wants to be direct. This
1963 1968 // includes stream lengths, stream filtering parameters, and
... ... @@ -1967,7 +1972,7 @@ QPDFWriter::prepareFileForWrite()
1967 1972 // holders.
1968 1973  
1969 1974 std::list<QPDFObjectHandle> queue;
1970   - queue.push_back(pdf.getTrailer());
  1975 + queue.push_back(getTrimmedTrailer());
1971 1976 std::set<int> visited;
1972 1977  
1973 1978 while (! queue.empty())
... ... @@ -2861,7 +2866,7 @@ QPDFWriter::writeStandard()
2861 2866 writeString(this->extra_header_text);
2862 2867  
2863 2868 // Put root first on queue.
2864   - QPDFObjectHandle trailer = pdf.getTrailer();
  2869 + QPDFObjectHandle trailer = getTrimmedTrailer();
2865 2870 enqueueObject(trailer.getKey("/Root"));
2866 2871  
2867 2872 // Next place any other objects referenced from the trailer
... ...