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,6 +322,7 @@ class QPDFWriter
322 void setDataKey(int objid); 322 void setDataKey(int objid);
323 int openObject(int objid = 0); 323 int openObject(int objid = 0);
324 void closeObject(int objid); 324 void closeObject(int objid);
  325 + QPDFObjectHandle getTrimmedTrailer();
325 void prepareFileForWrite(); 326 void prepareFileForWrite();
326 void writeStandard(); 327 void writeStandard();
327 void writeLinearized(); 328 void writeLinearized();
libqpdf/QPDFWriter.cc
@@ -1057,7 +1057,7 @@ void @@ -1057,7 +1057,7 @@ void
1057 QPDFWriter::writeTrailer(trailer_e which, int size, bool xref_stream, 1057 QPDFWriter::writeTrailer(trailer_e which, int size, bool xref_stream,
1058 qpdf_offset_t prev) 1058 qpdf_offset_t prev)
1059 { 1059 {
1060 - QPDFObjectHandle trailer = pdf.getTrailer(); 1060 + QPDFObjectHandle trailer = getTrimmedTrailer();
1061 if (! xref_stream) 1061 if (! xref_stream)
1062 { 1062 {
1063 writeString("trailer <<"); 1063 writeString("trailer <<");
@@ -1932,20 +1932,19 @@ QPDFWriter::generateObjectStreams() @@ -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 // Remove keys from the trailer that necessarily have to be 1938 // Remove keys from the trailer that necessarily have to be
1939 // replaced when writing the file. 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 trailer.removeKey("/ID"); 1944 trailer.removeKey("/ID");
1948 trailer.removeKey("/Encrypt"); 1945 trailer.removeKey("/Encrypt");
  1946 +
  1947 + // Remove modification information
1949 trailer.removeKey("/Prev"); 1948 trailer.removeKey("/Prev");
1950 1949
1951 // Remove all trailer keys that potentially come from a 1950 // Remove all trailer keys that potentially come from a
@@ -1958,6 +1957,12 @@ QPDFWriter::prepareFileForWrite() @@ -1958,6 +1957,12 @@ QPDFWriter::prepareFileForWrite()
1958 trailer.removeKey("/Type"); 1957 trailer.removeKey("/Type");
1959 trailer.removeKey("/XRefStm"); 1958 trailer.removeKey("/XRefStm");
1960 1959
  1960 + return trailer;
  1961 +}
  1962 +
  1963 +void
  1964 +QPDFWriter::prepareFileForWrite()
  1965 +{
1961 // Do a traversal of the entire PDF file structure replacing all 1966 // Do a traversal of the entire PDF file structure replacing all
1962 // indirect objects that QPDFWriter wants to be direct. This 1967 // indirect objects that QPDFWriter wants to be direct. This
1963 // includes stream lengths, stream filtering parameters, and 1968 // includes stream lengths, stream filtering parameters, and
@@ -1967,7 +1972,7 @@ QPDFWriter::prepareFileForWrite() @@ -1967,7 +1972,7 @@ QPDFWriter::prepareFileForWrite()
1967 // holders. 1972 // holders.
1968 1973
1969 std::list<QPDFObjectHandle> queue; 1974 std::list<QPDFObjectHandle> queue;
1970 - queue.push_back(pdf.getTrailer()); 1975 + queue.push_back(getTrimmedTrailer());
1971 std::set<int> visited; 1976 std::set<int> visited;
1972 1977
1973 while (! queue.empty()) 1978 while (! queue.empty())
@@ -2861,7 +2866,7 @@ QPDFWriter::writeStandard() @@ -2861,7 +2866,7 @@ QPDFWriter::writeStandard()
2861 writeString(this->extra_header_text); 2866 writeString(this->extra_header_text);
2862 2867
2863 // Put root first on queue. 2868 // Put root first on queue.
2864 - QPDFObjectHandle trailer = pdf.getTrailer(); 2869 + QPDFObjectHandle trailer = getTrimmedTrailer();
2865 enqueueObject(trailer.getKey("/Root")); 2870 enqueueObject(trailer.getKey("/Root"));
2866 2871
2867 // Next place any other objects referenced from the trailer 2872 // Next place any other objects referenced from the trailer