From 2bfa78540c375916ec9973f0ae11271b098180bd Mon Sep 17 00:00:00 2001 From: Artem Strygin Date: Mon, 23 Jul 2018 19:54:34 +0000 Subject: Rework of CPDF_Object writing. Move writing logic into implementation of related clases. Change-Id: If70dc418b352b562ee681ea34fa6595d6f52eee3 Reviewed-on: https://pdfium-review.googlesource.com/36350 Commit-Queue: Art Snake Reviewed-by: Tom Sepez --- core/fpdfapi/parser/cpdf_array.cpp | 5 ++-- core/fpdfapi/parser/cpdf_array.h | 3 ++- core/fpdfapi/parser/cpdf_boolean.cpp | 3 ++- core/fpdfapi/parser/cpdf_boolean.h | 3 ++- core/fpdfapi/parser/cpdf_dictionary.cpp | 11 +++++--- core/fpdfapi/parser/cpdf_dictionary.h | 3 ++- core/fpdfapi/parser/cpdf_name.cpp | 3 ++- core/fpdfapi/parser/cpdf_name.h | 3 ++- core/fpdfapi/parser/cpdf_null.cpp | 3 ++- core/fpdfapi/parser/cpdf_null.h | 3 ++- core/fpdfapi/parser/cpdf_number.cpp | 3 ++- core/fpdfapi/parser/cpdf_number.h | 3 ++- core/fpdfapi/parser/cpdf_object.h | 4 ++- core/fpdfapi/parser/cpdf_reference.cpp | 3 ++- core/fpdfapi/parser/cpdf_reference.h | 3 ++- core/fpdfapi/parser/cpdf_stream.cpp | 45 ++++++++++++++++++++++++++++----- core/fpdfapi/parser/cpdf_stream.h | 3 ++- core/fpdfapi/parser/cpdf_string.cpp | 16 +++++++++--- core/fpdfapi/parser/cpdf_string.h | 3 ++- 19 files changed, 94 insertions(+), 29 deletions(-) (limited to 'core/fpdfapi/parser') diff --git a/core/fpdfapi/parser/cpdf_array.cpp b/core/fpdfapi/parser/cpdf_array.cpp index d53476d1c2..68b301e283 100644 --- a/core/fpdfapi/parser/cpdf_array.cpp +++ b/core/fpdfapi/parser/cpdf_array.cpp @@ -230,12 +230,13 @@ CPDF_Object* CPDF_Array::Add(std::unique_ptr pObj) { return pRet; } -bool CPDF_Array::WriteTo(IFX_ArchiveStream* archive) const { +bool CPDF_Array::WriteTo(IFX_ArchiveStream* archive, + const CPDF_Encryptor* encryptor) const { if (!archive->WriteString("[")) return false; for (size_t i = 0; i < GetCount(); ++i) { - if (!GetObjectAt(i)->WriteTo(archive)) + if (!GetObjectAt(i)->WriteTo(archive, encryptor)) return false; } return archive->WriteString("]"); diff --git a/core/fpdfapi/parser/cpdf_array.h b/core/fpdfapi/parser/cpdf_array.h index d980b14507..1e63983d51 100644 --- a/core/fpdfapi/parser/cpdf_array.h +++ b/core/fpdfapi/parser/cpdf_array.h @@ -33,7 +33,8 @@ class CPDF_Array : public CPDF_Object { bool IsArray() const override; CPDF_Array* AsArray() override; const CPDF_Array* AsArray() const override; - bool WriteTo(IFX_ArchiveStream* archive) const override; + bool WriteTo(IFX_ArchiveStream* archive, + const CPDF_Encryptor* encryptor) const override; bool IsEmpty() const { return m_Objects.empty(); } size_t GetCount() const { return m_Objects.size(); } diff --git a/core/fpdfapi/parser/cpdf_boolean.cpp b/core/fpdfapi/parser/cpdf_boolean.cpp index a1dc450519..a26110116b 100644 --- a/core/fpdfapi/parser/cpdf_boolean.cpp +++ b/core/fpdfapi/parser/cpdf_boolean.cpp @@ -46,7 +46,8 @@ const CPDF_Boolean* CPDF_Boolean::AsBoolean() const { return this; } -bool CPDF_Boolean::WriteTo(IFX_ArchiveStream* archive) const { +bool CPDF_Boolean::WriteTo(IFX_ArchiveStream* archive, + const CPDF_Encryptor* encryptor) const { return archive->WriteString(" ") && archive->WriteString(GetString().AsStringView()); } diff --git a/core/fpdfapi/parser/cpdf_boolean.h b/core/fpdfapi/parser/cpdf_boolean.h index c0a69d8932..61c213bdb9 100644 --- a/core/fpdfapi/parser/cpdf_boolean.h +++ b/core/fpdfapi/parser/cpdf_boolean.h @@ -28,7 +28,8 @@ class CPDF_Boolean : public CPDF_Object { bool IsBoolean() const override; CPDF_Boolean* AsBoolean() override; const CPDF_Boolean* AsBoolean() const override; - bool WriteTo(IFX_ArchiveStream* archive) const override; + bool WriteTo(IFX_ArchiveStream* archive, + const CPDF_Encryptor* encryptor) const override; protected: bool m_bValue; diff --git a/core/fpdfapi/parser/cpdf_dictionary.cpp b/core/fpdfapi/parser/cpdf_dictionary.cpp index 78227ae70a..585930427c 100644 --- a/core/fpdfapi/parser/cpdf_dictionary.cpp +++ b/core/fpdfapi/parser/cpdf_dictionary.cpp @@ -269,10 +269,13 @@ ByteString CPDF_Dictionary::MaybeIntern(const ByteString& str) { return m_pPool ? m_pPool->Intern(str) : str; } -bool CPDF_Dictionary::WriteTo(IFX_ArchiveStream* archive) const { +bool CPDF_Dictionary::WriteTo(IFX_ArchiveStream* archive, + const CPDF_Encryptor* encryptor) const { if (!archive->WriteString("<<")) return false; + const bool is_signature = CPDF_CryptoHandler::IsSignatureDictionary(this); + for (const auto& it : *this) { const ByteString& key = it.first; CPDF_Object* pValue = it.second.get(); @@ -280,9 +283,11 @@ bool CPDF_Dictionary::WriteTo(IFX_ArchiveStream* archive) const { !archive->WriteString(PDF_NameEncode(key).AsStringView())) { return false; } - - if (!pValue->WriteTo(archive)) + if (!pValue->WriteTo(archive, !is_signature || key != "Contents" + ? encryptor + : nullptr)) { return false; + } } return archive->WriteString(">>"); } diff --git a/core/fpdfapi/parser/cpdf_dictionary.h b/core/fpdfapi/parser/cpdf_dictionary.h index 569baedb0b..5cd0e8be22 100644 --- a/core/fpdfapi/parser/cpdf_dictionary.h +++ b/core/fpdfapi/parser/cpdf_dictionary.h @@ -38,7 +38,8 @@ class CPDF_Dictionary : public CPDF_Object { bool IsDictionary() const override; CPDF_Dictionary* AsDictionary() override; const CPDF_Dictionary* AsDictionary() const override; - bool WriteTo(IFX_ArchiveStream* archive) const override; + bool WriteTo(IFX_ArchiveStream* archive, + const CPDF_Encryptor* encryptor) const override; size_t GetCount() const { return m_Map.size(); } const CPDF_Object* GetObjectFor(const ByteString& key) const; diff --git a/core/fpdfapi/parser/cpdf_name.cpp b/core/fpdfapi/parser/cpdf_name.cpp index 59a014208b..d35a76c8a0 100644 --- a/core/fpdfapi/parser/cpdf_name.cpp +++ b/core/fpdfapi/parser/cpdf_name.cpp @@ -51,7 +51,8 @@ WideString CPDF_Name::GetUnicodeText() const { return PDF_DecodeText(m_Name); } -bool CPDF_Name::WriteTo(IFX_ArchiveStream* archive) const { +bool CPDF_Name::WriteTo(IFX_ArchiveStream* archive, + const CPDF_Encryptor* encryptor) const { return archive->WriteString("/") && archive->WriteString(PDF_NameEncode(GetString()).AsStringView()); } diff --git a/core/fpdfapi/parser/cpdf_name.h b/core/fpdfapi/parser/cpdf_name.h index 880c10aedb..eef6bca715 100644 --- a/core/fpdfapi/parser/cpdf_name.h +++ b/core/fpdfapi/parser/cpdf_name.h @@ -27,7 +27,8 @@ class CPDF_Name : public CPDF_Object { bool IsName() const override; CPDF_Name* AsName() override; const CPDF_Name* AsName() const override; - bool WriteTo(IFX_ArchiveStream* archive) const override; + bool WriteTo(IFX_ArchiveStream* archive, + const CPDF_Encryptor* encryptor) const override; protected: ByteString m_Name; diff --git a/core/fpdfapi/parser/cpdf_null.cpp b/core/fpdfapi/parser/cpdf_null.cpp index 1074efd863..f94b46778b 100644 --- a/core/fpdfapi/parser/cpdf_null.cpp +++ b/core/fpdfapi/parser/cpdf_null.cpp @@ -18,7 +18,8 @@ std::unique_ptr CPDF_Null::Clone() const { return pdfium::MakeUnique(); } -bool CPDF_Null::WriteTo(IFX_ArchiveStream* archive) const { +bool CPDF_Null::WriteTo(IFX_ArchiveStream* archive, + const CPDF_Encryptor* encryptor) const { return archive->WriteString(" null"); } diff --git a/core/fpdfapi/parser/cpdf_null.h b/core/fpdfapi/parser/cpdf_null.h index 2ec05ec82c..003ad2feee 100644 --- a/core/fpdfapi/parser/cpdf_null.h +++ b/core/fpdfapi/parser/cpdf_null.h @@ -18,7 +18,8 @@ class CPDF_Null : public CPDF_Object { // CPDF_Object. Type GetType() const override; std::unique_ptr Clone() const override; - bool WriteTo(IFX_ArchiveStream* archive) const override; + bool WriteTo(IFX_ArchiveStream* archive, + const CPDF_Encryptor* encryptor) const override; bool IsNull() const override; }; diff --git a/core/fpdfapi/parser/cpdf_number.cpp b/core/fpdfapi/parser/cpdf_number.cpp index dac1f40b7f..b75ce0766a 100644 --- a/core/fpdfapi/parser/cpdf_number.cpp +++ b/core/fpdfapi/parser/cpdf_number.cpp @@ -57,7 +57,8 @@ ByteString CPDF_Number::GetString() const { : ByteString::FormatFloat(m_Float); } -bool CPDF_Number::WriteTo(IFX_ArchiveStream* archive) const { +bool CPDF_Number::WriteTo(IFX_ArchiveStream* archive, + const CPDF_Encryptor* encryptor) const { return archive->WriteString(" ") && archive->WriteString(GetString().AsStringView()); } diff --git a/core/fpdfapi/parser/cpdf_number.h b/core/fpdfapi/parser/cpdf_number.h index 661177363b..4681bb216a 100644 --- a/core/fpdfapi/parser/cpdf_number.h +++ b/core/fpdfapi/parser/cpdf_number.h @@ -31,7 +31,8 @@ class CPDF_Number : public CPDF_Object { bool IsNumber() const override; CPDF_Number* AsNumber() override; const CPDF_Number* AsNumber() const override; - bool WriteTo(IFX_ArchiveStream* archive) const override; + bool WriteTo(IFX_ArchiveStream* archive, + const CPDF_Encryptor* encryptor) const override; bool IsInteger() const { return m_bInteger; } diff --git a/core/fpdfapi/parser/cpdf_object.h b/core/fpdfapi/parser/cpdf_object.h index 5ff028e9e0..6c6b583963 100644 --- a/core/fpdfapi/parser/cpdf_object.h +++ b/core/fpdfapi/parser/cpdf_object.h @@ -17,6 +17,7 @@ class CPDF_Array; class CPDF_Boolean; class CPDF_Dictionary; +class CPDF_Encryptor; class CPDF_IndirectObjectHolder; class CPDF_Name; class CPDF_Null; @@ -95,7 +96,8 @@ class CPDF_Object { virtual CPDF_String* AsString(); virtual const CPDF_String* AsString() const; - virtual bool WriteTo(IFX_ArchiveStream* archive) const = 0; + virtual bool WriteTo(IFX_ArchiveStream* archive, + const CPDF_Encryptor* encryptor) const = 0; // Create a deep copy of the object with the option to either // copy a reference object or directly copy the object it refers to diff --git a/core/fpdfapi/parser/cpdf_reference.cpp b/core/fpdfapi/parser/cpdf_reference.cpp index 0f3b7627d6..5a4d58a0e2 100644 --- a/core/fpdfapi/parser/cpdf_reference.cpp +++ b/core/fpdfapi/parser/cpdf_reference.cpp @@ -99,7 +99,8 @@ const CPDF_Object* CPDF_Reference::GetDirect() const { : nullptr; } -bool CPDF_Reference::WriteTo(IFX_ArchiveStream* archive) const { +bool CPDF_Reference::WriteTo(IFX_ArchiveStream* archive, + const CPDF_Encryptor* encryptor) const { return archive->WriteString(" ") && archive->WriteDWord(GetRefObjNum()) && archive->WriteString(" 0 R "); } diff --git a/core/fpdfapi/parser/cpdf_reference.h b/core/fpdfapi/parser/cpdf_reference.h index d1e0a07e4b..cdb5d5e674 100644 --- a/core/fpdfapi/parser/cpdf_reference.h +++ b/core/fpdfapi/parser/cpdf_reference.h @@ -33,7 +33,8 @@ class CPDF_Reference : public CPDF_Object { bool IsReference() const override; CPDF_Reference* AsReference() override; const CPDF_Reference* AsReference() const override; - bool WriteTo(IFX_ArchiveStream* archive) const override; + bool WriteTo(IFX_ArchiveStream* archive, + const CPDF_Encryptor* encryptor) const override; std::unique_ptr MakeReference( CPDF_IndirectObjectHolder* holder) const override; diff --git a/core/fpdfapi/parser/cpdf_stream.cpp b/core/fpdfapi/parser/cpdf_stream.cpp index fdbe308878..64478996a8 100644 --- a/core/fpdfapi/parser/cpdf_stream.cpp +++ b/core/fpdfapi/parser/cpdf_stream.cpp @@ -7,8 +7,11 @@ #include "core/fpdfapi/parser/cpdf_stream.h" #include +#include #include "constants/stream_dict_common.h" +#include "core/fpdfapi/edit/cpdf_encryptor.h" +#include "core/fpdfapi/edit/cpdf_flateencoder.h" #include "core/fpdfapi/parser/cpdf_dictionary.h" #include "core/fpdfapi/parser/cpdf_number.h" #include "core/fpdfapi/parser/cpdf_stream_acc.h" @@ -18,6 +21,15 @@ #include "third_party/base/ptr_util.h" #include "third_party/base/stl_util.h" +namespace { + +bool IsMetaDataStreamDictionary(const CPDF_Dictionary* dict) { + return dict && dict->GetStringFor("Type") == "Metadata" && + dict->GetStringFor("Subtype") == "XML"; +} + +} // namespace + CPDF_Stream::CPDF_Stream() {} CPDF_Stream::CPDF_Stream(std::unique_ptr pData, @@ -167,12 +179,33 @@ WideString CPDF_Stream::GetUnicodeText() const { return PDF_DecodeText(pAcc->GetData(), pAcc->GetSize()); } -bool CPDF_Stream::WriteTo(IFX_ArchiveStream* archive) const { - if (!GetDict()->WriteTo(archive) || !archive->WriteString("stream\r\n")) +bool CPDF_Stream::WriteTo(IFX_ArchiveStream* archive, + const CPDF_Encryptor* encryptor) const { + const bool is_metadata = IsMetaDataStreamDictionary(GetDict()); + CPDF_FlateEncoder encoder(this, !is_metadata); + + std::vector encrypted_data; + pdfium::span data = encoder.GetSpan(); + + if (encryptor && !is_metadata) { + encrypted_data = encryptor->Encrypt(data); + data = encrypted_data; + } + + if (static_cast(encoder.GetDict()->GetIntegerFor("Length")) != + data.size()) { + encoder.CloneDict(); + encoder.GetClonedDict()->SetNewFor( + "Length", static_cast(data.size())); + } + + if (!encoder.GetDict()->WriteTo(archive, encryptor)) return false; - auto pAcc = pdfium::MakeRetain(this); - pAcc->LoadAllDataRaw(); - return archive->WriteBlock(pAcc->GetData(), pAcc->GetSize()) && - archive->WriteString("\r\nendstream"); + if (!archive->WriteString("stream\r\n") || + !archive->WriteBlock(data.data(), data.size()) || + !archive->WriteString("\r\nendstream")) { + return false; + } + return true; } diff --git a/core/fpdfapi/parser/cpdf_stream.h b/core/fpdfapi/parser/cpdf_stream.h index 7e98f300ba..4a5ac61011 100644 --- a/core/fpdfapi/parser/cpdf_stream.h +++ b/core/fpdfapi/parser/cpdf_stream.h @@ -34,7 +34,8 @@ class CPDF_Stream : public CPDF_Object { bool IsStream() const override; CPDF_Stream* AsStream() override; const CPDF_Stream* AsStream() const override; - bool WriteTo(IFX_ArchiveStream* archive) const override; + bool WriteTo(IFX_ArchiveStream* archive, + const CPDF_Encryptor* encryptor) const override; uint32_t GetRawSize() const { return m_dwSize; } // Will be null in case when stream is not memory based. diff --git a/core/fpdfapi/parser/cpdf_string.cpp b/core/fpdfapi/parser/cpdf_string.cpp index 851442e8b4..e7f2a9dcd6 100644 --- a/core/fpdfapi/parser/cpdf_string.cpp +++ b/core/fpdfapi/parser/cpdf_string.cpp @@ -7,7 +7,9 @@ #include "core/fpdfapi/parser/cpdf_string.h" #include +#include +#include "core/fpdfapi/edit/cpdf_encryptor.h" #include "core/fpdfapi/parser/fpdf_parser_decode.h" #include "core/fxcrt/fx_stream.h" #include "third_party/base/ptr_util.h" @@ -65,7 +67,15 @@ WideString CPDF_String::GetUnicodeText() const { return PDF_DecodeText(m_String); } -bool CPDF_String::WriteTo(IFX_ArchiveStream* archive) const { - return archive->WriteString( - PDF_EncodeString(GetString(), IsHex()).AsStringView()); +bool CPDF_String::WriteTo(IFX_ArchiveStream* archive, + const CPDF_Encryptor* encryptor) const { + std::vector encrypted_data; + pdfium::span data = m_String.AsRawSpan(); + if (encryptor) { + encrypted_data = encryptor->Encrypt(data); + data = encrypted_data; + } + const ByteString content = + PDF_EncodeString(ByteString(data.data(), data.size()), IsHex()); + return archive->WriteString(content.AsStringView()); } diff --git a/core/fpdfapi/parser/cpdf_string.h b/core/fpdfapi/parser/cpdf_string.h index b6aaacb043..144fe64cba 100644 --- a/core/fpdfapi/parser/cpdf_string.h +++ b/core/fpdfapi/parser/cpdf_string.h @@ -31,7 +31,8 @@ class CPDF_String : public CPDF_Object { bool IsString() const override; CPDF_String* AsString() override; const CPDF_String* AsString() const override; - bool WriteTo(IFX_ArchiveStream* archive) const override; + bool WriteTo(IFX_ArchiveStream* archive, + const CPDF_Encryptor* encryptor) const override; bool IsHex() const { return m_bHex; } -- cgit v1.2.3