summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHenrique Nakashima <hnakashima@chromium.org>2017-11-08 16:19:50 +0000
committerChromium commit bot <commit-bot@chromium.org>2017-11-08 16:19:50 +0000
commit20f22a0a38a6c6d9ccd0ead2e65093e79f0bd051 (patch)
treea02ebaf3432516a879d356748545552aa78fb8b0
parent9a93484a61fe0e9b8a4a4c664f596857eb78f819 (diff)
downloadpdfium-20f22a0a38a6c6d9ccd0ead2e65093e79f0bd051.tar.xz
Fix FPDF_SaveAsCopy for linearized PDFs.
Only the last trailer was written to the new PDF. In linearized PDFs, this means Info and Root were not copied to the newly written PDF. This CL makes CPDF_Parser remember the Root and provide that to CPDF_Creator. Bug: pdfium:614 Change-Id: Ia61f5f6a337f7de3010ee0ed39b022c1b2732ea2 Reviewed-on: https://pdfium-review.googlesource.com/17987 Reviewed-by: dsinclair <dsinclair@chromium.org> Commit-Queue: Henrique Nakashima <hnakashima@chromium.org>
-rw-r--r--core/fpdfapi/edit/cpdf_creator.cpp2
-rw-r--r--core/fpdfapi/parser/cpdf_parser.cpp40
-rw-r--r--core/fpdfapi/parser/cpdf_parser.h6
3 files changed, 41 insertions, 7 deletions
diff --git a/core/fpdfapi/edit/cpdf_creator.cpp b/core/fpdfapi/edit/cpdf_creator.cpp
index 38abb85822..590229bf4f 100644
--- a/core/fpdfapi/edit/cpdf_creator.cpp
+++ b/core/fpdfapi/edit/cpdf_creator.cpp
@@ -624,7 +624,7 @@ int32_t CPDF_Creator::WriteDoc_Stage4() {
}
if (m_pParser) {
- CPDF_Dictionary* p = m_pParser->GetTrailer();
+ std::unique_ptr<CPDF_Dictionary> p = m_pParser->GetCombinedTrailer();
for (const auto& it : *p) {
const ByteString& key = it.first;
CPDF_Object* pValue = it.second.get();
diff --git a/core/fpdfapi/parser/cpdf_parser.cpp b/core/fpdfapi/parser/cpdf_parser.cpp
index d02989000c..5b57b949ba 100644
--- a/core/fpdfapi/parser/cpdf_parser.cpp
+++ b/core/fpdfapi/parser/cpdf_parser.cpp
@@ -61,6 +61,20 @@ class CPDF_Parser::TrailerData {
CPDF_Dictionary* GetMainTrailer() const { return main_trailer_.get(); }
+ std::unique_ptr<CPDF_Dictionary> GetCombinedTrailer() const {
+ std::unique_ptr<CPDF_Dictionary> result =
+ ToDictionary(main_trailer_->Clone());
+
+ // Info is optional.
+ uint32_t info_obj_num = GetInfoObjNum();
+ if (info_obj_num > 0)
+ result->SetNewFor<CPDF_Reference>("Info", nullptr, GetInfoObjNum());
+
+ // Root is required.
+ result->SetNewFor<CPDF_Reference>("Root", nullptr, GetRootObjNum());
+ return result;
+ }
+
void SetMainTrailer(std::unique_ptr<CPDF_Dictionary> trailer) {
ASSERT(trailer);
main_trailer_ = std::move(trailer);
@@ -75,6 +89,7 @@ class CPDF_Parser::TrailerData {
void Clear() {
main_trailer_.reset();
last_info_obj_num_ = 0;
+ last_root_obj_num_ = 0;
}
uint32_t GetInfoObjNum() const {
@@ -83,6 +98,12 @@ class CPDF_Parser::TrailerData {
return pRef ? pRef->GetRefObjNum() : last_info_obj_num_;
}
+ uint32_t GetRootObjNum() const {
+ const CPDF_Reference* pRef = ToReference(
+ GetMainTrailer() ? GetMainTrailer()->GetObjectFor("Root") : nullptr);
+ return pRef ? pRef->GetRefObjNum() : last_root_obj_num_;
+ }
+
private:
void ApplyTrailer(const CPDF_Dictionary* dict) {
// The most recent Info object number contained in last added trailer.
@@ -90,10 +111,15 @@ class CPDF_Parser::TrailerData {
const auto* pRef = ToReference(dict->GetObjectFor("Info"));
if (pRef)
last_info_obj_num_ = pRef->GetRefObjNum();
+
+ const auto* pRoot = ToReference(dict->GetObjectFor("Root"));
+ if (pRoot)
+ last_root_obj_num_ = pRoot->GetRefObjNum();
}
std::unique_ptr<CPDF_Dictionary> main_trailer_;
uint32_t last_info_obj_num_ = 0;
+ uint32_t last_root_obj_num_ = 0;
};
CPDF_Parser::CPDF_Parser()
@@ -1145,20 +1171,22 @@ const CPDF_Array* CPDF_Parser::GetIDArray() const {
return GetTrailer() ? GetTrailer()->GetArrayFor("ID") : nullptr;
}
-uint32_t CPDF_Parser::GetRootObjNum() {
- CPDF_Reference* pRef =
- ToReference(GetTrailer() ? GetTrailer()->GetObjectFor("Root") : nullptr);
- return pRef ? pRef->GetRefObjNum() : 0;
-}
-
CPDF_Dictionary* CPDF_Parser::GetTrailer() const {
return m_TrailerData->GetMainTrailer();
}
+std::unique_ptr<CPDF_Dictionary> CPDF_Parser::GetCombinedTrailer() const {
+ return m_TrailerData->GetCombinedTrailer();
+}
+
uint32_t CPDF_Parser::GetInfoObjNum() {
return m_TrailerData->GetInfoObjNum();
}
+uint32_t CPDF_Parser::GetRootObjNum() {
+ return m_TrailerData->GetRootObjNum();
+}
+
std::unique_ptr<CPDF_Object> CPDF_Parser::ParseIndirectObject(
CPDF_IndirectObjectHolder* pObjList,
uint32_t objnum) {
diff --git a/core/fpdfapi/parser/cpdf_parser.h b/core/fpdfapi/parser/cpdf_parser.h
index 375bc01621..45b8cb9f2e 100644
--- a/core/fpdfapi/parser/cpdf_parser.h
+++ b/core/fpdfapi/parser/cpdf_parser.h
@@ -57,7 +57,13 @@ class CPDF_Parser {
void SetPassword(const char* password) { m_Password = password; }
ByteString GetPassword() { return m_Password; }
+
CPDF_Dictionary* GetTrailer() const;
+
+ // Returns a new trailer which combines the last read trailer with the /Root
+ // and /Info from previous ones.
+ std::unique_ptr<CPDF_Dictionary> GetCombinedTrailer() const;
+
FX_FILESIZE GetLastXRefOffset() const { return m_LastXRefOffset; }
uint32_t GetPermissions() const;