Move name tree internal structure creation code into CPDF_NameTree.
The code to do so is non-trivial, so better to centralize it in
CPDF_NameTree, instead of relying on CPDF_NameTree users will get it
right.
Change-Id: I3704ef8ea30a21079a7de0c285bfcd8253cd496e
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/68194
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Tom Sepez <tsepez@chromium.org>
diff --git a/core/fpdfdoc/cpdf_nametree.cpp b/core/fpdfdoc/cpdf_nametree.cpp
index 549fccb..a0fc935 100644
--- a/core/fpdfdoc/cpdf_nametree.cpp
+++ b/core/fpdfdoc/cpdf_nametree.cpp
@@ -12,6 +12,7 @@
#include "core/fpdfapi/parser/cpdf_array.h"
#include "core/fpdfapi/parser/cpdf_dictionary.h"
#include "core/fpdfapi/parser/cpdf_document.h"
+#include "core/fpdfapi/parser/cpdf_reference.h"
#include "core/fpdfapi/parser/cpdf_string.h"
#include "core/fpdfapi/parser/fpdf_parser_decode.h"
@@ -317,6 +318,31 @@
CPDF_NameTree::~CPDF_NameTree() = default;
// static
+std::unique_ptr<CPDF_NameTree> CPDF_NameTree::CreateWithRootNameArray(
+ CPDF_Document* pDoc,
+ const ByteString& category) {
+ CPDF_Dictionary* pRoot = pDoc->GetRoot();
+ if (!pRoot)
+ return nullptr;
+
+ // Retrieve the document's Names dictionary; create it if missing.
+ CPDF_Dictionary* pNames = pRoot->GetDictFor("Names");
+ if (!pNames) {
+ pNames = pDoc->NewIndirect<CPDF_Dictionary>();
+ pRoot->SetNewFor<CPDF_Reference>("Names", pDoc, pNames->GetObjNum());
+ }
+
+ // Create the |category| dictionary if missing.
+ if (!pNames->GetDictFor(category)) {
+ CPDF_Dictionary* pFiles = pDoc->NewIndirect<CPDF_Dictionary>();
+ pFiles->SetNewFor<CPDF_Array>("Names");
+ pNames->SetNewFor<CPDF_Reference>(category, pDoc, pFiles->GetObjNum());
+ }
+
+ return pdfium::MakeUnique<CPDF_NameTree>(pDoc, category);
+}
+
+// static
std::unique_ptr<CPDF_NameTree> CPDF_NameTree::CreateForTesting(
CPDF_Dictionary* pRoot) {
return pdfium::WrapUnique(new CPDF_NameTree(pRoot)); // Private ctor.
diff --git a/core/fpdfdoc/cpdf_nametree.h b/core/fpdfdoc/cpdf_nametree.h
index 01d85aa..043a2dc 100644
--- a/core/fpdfdoc/cpdf_nametree.h
+++ b/core/fpdfdoc/cpdf_nametree.h
@@ -24,6 +24,13 @@
CPDF_NameTree& operator=(const CPDF_NameTree&) = delete;
~CPDF_NameTree();
+ // If necessary, create missing Names dictionary in |pDoc|, and/or missing
+ // Names array in the dictionary that corresponds to |category|, if necessary.
+ // Returns nullptr on failure.
+ static std::unique_ptr<CPDF_NameTree> CreateWithRootNameArray(
+ CPDF_Document* pDoc,
+ const ByteString& category);
+
static std::unique_ptr<CPDF_NameTree> CreateForTesting(
CPDF_Dictionary* pRoot);
diff --git a/fpdfsdk/fpdf_attachment.cpp b/fpdfsdk/fpdf_attachment.cpp
index 18c12df..a8d4eeb 100644
--- a/fpdfsdk/fpdf_attachment.cpp
+++ b/fpdfsdk/fpdf_attachment.cpp
@@ -64,28 +64,14 @@
if (!pDoc)
return nullptr;
- CPDF_Dictionary* pRoot = pDoc->GetRoot();
- if (!pRoot)
- return nullptr;
-
WideString wsName = WideStringFromFPDFWideString(name);
if (wsName.IsEmpty())
return nullptr;
- // Retrieve the document's Names dictionary; create it if missing.
- CPDF_Dictionary* pNames = pRoot->GetDictFor("Names");
- if (!pNames) {
- pNames = pDoc->NewIndirect<CPDF_Dictionary>();
- pRoot->SetNewFor<CPDF_Reference>("Names", pDoc, pNames->GetObjNum());
- }
-
- // Create the EmbeddedFiles dictionary if missing.
- if (!pNames->GetDictFor("EmbeddedFiles")) {
- CPDF_Dictionary* pFiles = pDoc->NewIndirect<CPDF_Dictionary>();
- pFiles->SetNewFor<CPDF_Array>("Names");
- pNames->SetNewFor<CPDF_Reference>("EmbeddedFiles", pDoc,
- pFiles->GetObjNum());
- }
+ auto name_tree =
+ CPDF_NameTree::CreateWithRootNameArray(pDoc, "EmbeddedFiles");
+ if (!name_tree)
+ return nullptr;
// Set up the basic entries in the filespec dictionary.
CPDF_Dictionary* pFile = pDoc->NewIndirect<CPDF_Dictionary>();
@@ -94,10 +80,8 @@
pFile->SetNewFor<CPDF_String>(pdfium::stream::kF, wsName);
// Add the new attachment name and filespec into the document's EmbeddedFiles.
- CPDF_NameTree name_tree(pDoc, "EmbeddedFiles");
- if (!name_tree.AddValueAndName(pFile->MakeReference(pDoc), wsName)) {
+ if (!name_tree->AddValueAndName(pFile->MakeReference(pDoc), wsName))
return nullptr;
- }
return FPDFAttachmentFromCPDFObject(pFile);
}