summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/fpdfapi/edit/cpdf_creator.cpp137
-rw-r--r--core/fpdfapi/edit/cpdf_creator.h3
-rw-r--r--core/fpdfapi/edit/cpdf_encryptor.cpp32
-rw-r--r--core/fpdfapi/edit/cpdf_encryptor.h12
-rw-r--r--core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp2
-rw-r--r--core/fpdfapi/parser/cpdf_array.cpp5
-rw-r--r--core/fpdfapi/parser/cpdf_array.h3
-rw-r--r--core/fpdfapi/parser/cpdf_boolean.cpp3
-rw-r--r--core/fpdfapi/parser/cpdf_boolean.h3
-rw-r--r--core/fpdfapi/parser/cpdf_dictionary.cpp11
-rw-r--r--core/fpdfapi/parser/cpdf_dictionary.h3
-rw-r--r--core/fpdfapi/parser/cpdf_name.cpp3
-rw-r--r--core/fpdfapi/parser/cpdf_name.h3
-rw-r--r--core/fpdfapi/parser/cpdf_null.cpp3
-rw-r--r--core/fpdfapi/parser/cpdf_null.h3
-rw-r--r--core/fpdfapi/parser/cpdf_number.cpp3
-rw-r--r--core/fpdfapi/parser/cpdf_number.h3
-rw-r--r--core/fpdfapi/parser/cpdf_object.h4
-rw-r--r--core/fpdfapi/parser/cpdf_reference.cpp3
-rw-r--r--core/fpdfapi/parser/cpdf_reference.h3
-rw-r--r--core/fpdfapi/parser/cpdf_stream.cpp45
-rw-r--r--core/fpdfapi/parser/cpdf_stream.h3
-rw-r--r--core/fpdfapi/parser/cpdf_string.cpp16
-rw-r--r--core/fpdfapi/parser/cpdf_string.h3
24 files changed, 125 insertions, 184 deletions
diff --git a/core/fpdfapi/edit/cpdf_creator.cpp b/core/fpdfapi/edit/cpdf_creator.cpp
index f5d8c0fe49..5d4fac478d 100644
--- a/core/fpdfapi/edit/cpdf_creator.cpp
+++ b/core/fpdfapi/edit/cpdf_creator.cpp
@@ -151,143 +151,20 @@ CPDF_Creator::CPDF_Creator(CPDF_Document* pDoc,
CPDF_Creator::~CPDF_Creator() {}
-bool CPDF_Creator::WriteStream(const CPDF_Object* pStream, uint32_t objnum) {
- CPDF_CryptoHandler* pCrypto =
- pStream != m_pMetadata ? GetCryptoHandler() : nullptr;
-
- CPDF_FlateEncoder encoder(pStream->AsStream(), pStream != m_pMetadata);
- CPDF_Encryptor encryptor(pCrypto, objnum, encoder.GetSpan());
- if (static_cast<uint32_t>(encoder.GetDict()->GetIntegerFor("Length")) !=
- encryptor.GetSpan().size()) {
- encoder.CloneDict();
- encoder.GetClonedDict()->SetNewFor<CPDF_Number>(
- "Length", static_cast<int>(encryptor.GetSpan().size()));
- }
-
- if (!WriteDirectObj(objnum, encoder.GetDict(), true) ||
- !m_Archive->WriteString("stream\r\n")) {
- return false;
- }
-
- // Allow for empty streams.
- if (encryptor.GetSpan().size() > 0 &&
- !m_Archive->WriteBlock(encryptor.GetSpan().data(),
- encryptor.GetSpan().size())) {
- return false;
- }
-
- return m_Archive->WriteString("\r\nendstream");
-}
-
bool CPDF_Creator::WriteIndirectObj(uint32_t objnum, const CPDF_Object* pObj) {
if (!m_Archive->WriteDWord(objnum) || !m_Archive->WriteString(" 0 obj\r\n"))
return false;
- if (pObj->IsStream()) {
- if (!WriteStream(pObj, objnum))
- return false;
- } else if (!WriteDirectObj(objnum, pObj, true)) {
+ std::unique_ptr<CPDF_Encryptor> encryptor;
+ if (GetCryptoHandler() && pObj != m_pEncryptDict)
+ encryptor = pdfium::MakeUnique<CPDF_Encryptor>(GetCryptoHandler(), objnum);
+
+ if (!pObj->WriteTo(m_Archive.get(), encryptor.get()))
return false;
- }
return m_Archive->WriteString("\r\nendobj\r\n");
}
-bool CPDF_Creator::WriteDirectObj(uint32_t objnum,
- const CPDF_Object* pObj,
- bool bEncrypt) {
- switch (pObj->GetType()) {
- case CPDF_Object::BOOLEAN:
- case CPDF_Object::NAME:
- case CPDF_Object::NULLOBJ:
- case CPDF_Object::NUMBER:
- case CPDF_Object::REFERENCE:
- if (!pObj->WriteTo(m_Archive.get()))
- return false;
- break;
-
- case CPDF_Object::STRING: {
- ByteString str = pObj->GetString();
- bool bHex = pObj->AsString()->IsHex();
- if (!GetCryptoHandler() || !bEncrypt) {
- if (!pObj->WriteTo(m_Archive.get()))
- return false;
- break;
- }
- CPDF_Encryptor encryptor(GetCryptoHandler(), objnum, str.AsRawSpan());
- ByteString content = PDF_EncodeString(
- ByteString(encryptor.GetSpan().data(), encryptor.GetSpan().size()),
- bHex);
- if (!m_Archive->WriteString(content.AsStringView()))
- return false;
- break;
- }
- case CPDF_Object::STREAM: {
- CPDF_FlateEncoder encoder(pObj->AsStream(), true);
- CPDF_Encryptor encryptor(GetCryptoHandler(), objnum, encoder.GetSpan());
- if (static_cast<uint32_t>(encoder.GetDict()->GetIntegerFor("Length")) !=
- encryptor.GetSpan().size()) {
- encoder.CloneDict();
- encoder.GetClonedDict()->SetNewFor<CPDF_Number>(
- "Length", static_cast<int>(encryptor.GetSpan().size()));
- }
- if (!WriteDirectObj(objnum, encoder.GetDict(), true) ||
- !m_Archive->WriteString("stream\r\n") ||
- !m_Archive->WriteBlock(encryptor.GetSpan().data(),
- encryptor.GetSpan().size()) ||
- !m_Archive->WriteString("\r\nendstream")) {
- return false;
- }
-
- break;
- }
- case CPDF_Object::ARRAY: {
- if (!m_Archive->WriteString("["))
- return false;
-
- const CPDF_Array* p = pObj->AsArray();
- for (size_t i = 0; i < p->GetCount(); i++) {
- if (!WriteDirectObj(objnum, p->GetObjectAt(i), true))
- return false;
- }
- if (!m_Archive->WriteString("]"))
- return false;
- break;
- }
- case CPDF_Object::DICTIONARY: {
- if (!GetCryptoHandler() || pObj == m_pEncryptDict) {
- if (!pObj->WriteTo(m_Archive.get()))
- return false;
- break;
- }
-
- if (!m_Archive->WriteString("<<"))
- return false;
-
- const CPDF_Dictionary* p = pObj->AsDictionary();
- bool bSignDict = p->IsSignatureDict();
- for (const auto& it : *p) {
- bool bSignValue = false;
- const ByteString& key = it.first;
- CPDF_Object* pValue = it.second.get();
- if (!m_Archive->WriteString("/") ||
- !m_Archive->WriteString(PDF_NameEncode(key).AsStringView())) {
- return false;
- }
-
- if (bSignDict && key == "Contents")
- bSignValue = true;
- if (!WriteDirectObj(objnum, pValue, !bSignValue))
- return false;
- }
- if (!m_Archive->WriteString(">>"))
- return false;
- break;
- }
- }
- return true;
-}
-
bool CPDF_Creator::WriteOldIndirectObject(uint32_t objnum) {
if (m_pParser->IsObjectFreeOrNull(objnum))
return true;
@@ -583,7 +460,7 @@ CPDF_Creator::Stage CPDF_Creator::WriteDoc_Stage4() {
!m_Archive->WriteString(PDF_NameEncode(key).AsStringView())) {
return Stage::kInvalid;
}
- if (!pValue->WriteTo(m_Archive.get()))
+ if (!pValue->WriteTo(m_Archive.get(), nullptr))
return Stage::kInvalid;
}
} else {
@@ -632,7 +509,7 @@ CPDF_Creator::Stage CPDF_Creator::WriteDoc_Stage4() {
}
if (m_pIDArray) {
if (!m_Archive->WriteString(("/ID")) ||
- !m_pIDArray->WriteTo(m_Archive.get())) {
+ !m_pIDArray->WriteTo(m_Archive.get(), nullptr)) {
return Stage::kInvalid;
}
}
diff --git a/core/fpdfapi/edit/cpdf_creator.h b/core/fpdfapi/edit/cpdf_creator.h
index a7261145e9..39e0950af6 100644
--- a/core/fpdfapi/edit/cpdf_creator.h
+++ b/core/fpdfapi/edit/cpdf_creator.h
@@ -69,11 +69,8 @@ class CPDF_Creator {
bool WriteOldIndirectObject(uint32_t objnum);
bool WriteOldObjs();
bool WriteNewObjs();
- bool WriteDirectObj(uint32_t objnum, const CPDF_Object* pObj, bool bEncrypt);
bool WriteIndirectObj(uint32_t objnum, const CPDF_Object* pObj);
- bool WriteStream(const CPDF_Object* pStream, uint32_t objnum);
-
CPDF_CryptoHandler* GetCryptoHandler();
UnownedPtr<CPDF_Document> const m_pDocument;
diff --git a/core/fpdfapi/edit/cpdf_encryptor.cpp b/core/fpdfapi/edit/cpdf_encryptor.cpp
index 8994b555ee..c74e53ed75 100644
--- a/core/fpdfapi/edit/cpdf_encryptor.cpp
+++ b/core/fpdfapi/edit/cpdf_encryptor.cpp
@@ -5,25 +5,27 @@
// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
#include "core/fpdfapi/edit/cpdf_encryptor.h"
+
#include "core/fpdfapi/parser/cpdf_crypto_handler.h"
+#include "third_party/base/ptr_util.h"
-CPDF_Encryptor::CPDF_Encryptor(CPDF_CryptoHandler* pHandler,
- int objnum,
- pdfium::span<const uint8_t> src_data) {
- if (src_data.empty())
- return;
+CPDF_Encryptor::CPDF_Encryptor(CPDF_CryptoHandler* pHandler, int objnum)
+ : m_pHandler(pHandler), m_ObjNum(objnum) {
+ ASSERT(m_pHandler);
+}
- if (!pHandler) {
- m_Span = src_data;
- return;
- }
+std::vector<uint8_t> CPDF_Encryptor::Encrypt(
+ pdfium::span<const uint8_t> src_data) const {
+ if (src_data.empty())
+ return std::vector<uint8_t>();
- uint32_t buf_size = pHandler->EncryptGetSize(src_data);
- m_NewBuf.resize(buf_size);
- pHandler->EncryptContent(objnum, 0, src_data, m_NewBuf.data(),
- buf_size); // Updates |buf_size| with actual.
- m_NewBuf.resize(buf_size);
- m_Span = m_NewBuf;
+ std::vector<uint8_t> result;
+ uint32_t buf_size = m_pHandler->EncryptGetSize(src_data);
+ result.resize(buf_size);
+ m_pHandler->EncryptContent(m_ObjNum, 0, src_data, result.data(),
+ buf_size); // Updates |buf_size| with actual.
+ result.resize(buf_size);
+ return result;
}
CPDF_Encryptor::~CPDF_Encryptor() {}
diff --git a/core/fpdfapi/edit/cpdf_encryptor.h b/core/fpdfapi/edit/cpdf_encryptor.h
index 67fd5c4f9b..5486c4f248 100644
--- a/core/fpdfapi/edit/cpdf_encryptor.h
+++ b/core/fpdfapi/edit/cpdf_encryptor.h
@@ -9,25 +9,25 @@
#include <stdint.h>
+#include <memory>
#include <vector>
#include "core/fxcrt/fx_memory.h"
+#include "core/fxcrt/unowned_ptr.h"
#include "third_party/base/span.h"
class CPDF_CryptoHandler;
class CPDF_Encryptor {
public:
- CPDF_Encryptor(CPDF_CryptoHandler* pHandler,
- int objnum,
- pdfium::span<const uint8_t> src_data);
+ CPDF_Encryptor(CPDF_CryptoHandler* pHandler, int objnum);
~CPDF_Encryptor();
- pdfium::span<const uint8_t> GetSpan() const { return m_Span; }
+ std::vector<uint8_t> Encrypt(pdfium::span<const uint8_t> src_data) const;
private:
- std::vector<uint8_t> m_NewBuf;
- pdfium::span<const uint8_t> m_Span;
+ UnownedPtr<CPDF_CryptoHandler> const m_pHandler;
+ const int m_ObjNum;
};
#endif // CORE_FPDFAPI_EDIT_CPDF_ENCRYPTOR_H_
diff --git a/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp b/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp
index f6a941d200..9693bc48ff 100644
--- a/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp
+++ b/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp
@@ -266,7 +266,7 @@ const CPDF_ContentMark* CPDF_PageContentGenerator::ProcessContentMarks(
// If there are parameters, write properties, direct or indirect.
if (item->GetParamType() == CPDF_ContentMarkItem::DirectDict) {
CPDF_StringArchiveStream archive_stream(buf);
- item->GetParam()->WriteTo(&archive_stream);
+ item->GetParam()->WriteTo(&archive_stream, nullptr);
*buf << " ";
} else {
ASSERT(item->GetParamType() == CPDF_ContentMarkItem::PropertiesDict);
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<CPDF_Object> 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_Object> CPDF_Null::Clone() const {
return pdfium::MakeUnique<CPDF_Null>();
}
-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<CPDF_Object> 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<CPDF_Object> 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 <utility>
+#include <vector>
#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<uint8_t, FxFreeDeleter> 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<uint8_t> encrypted_data;
+ pdfium::span<const uint8_t> data = encoder.GetSpan();
+
+ if (encryptor && !is_metadata) {
+ encrypted_data = encryptor->Encrypt(data);
+ data = encrypted_data;
+ }
+
+ if (static_cast<uint32_t>(encoder.GetDict()->GetIntegerFor("Length")) !=
+ data.size()) {
+ encoder.CloneDict();
+ encoder.GetClonedDict()->SetNewFor<CPDF_Number>(
+ "Length", static_cast<int>(data.size()));
+ }
+
+ if (!encoder.GetDict()->WriteTo(archive, encryptor))
return false;
- auto pAcc = pdfium::MakeRetain<CPDF_StreamAcc>(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 <utility>
+#include <vector>
+#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<uint8_t> encrypted_data;
+ pdfium::span<const uint8_t> 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; }