• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6 
7 #include "core/fpdfapi/parser/cpdf_dictionary.h"
8 
9 #include <set>
10 #include <utility>
11 
12 #include "core/fpdfapi/parser/cpdf_array.h"
13 #include "core/fpdfapi/parser/cpdf_boolean.h"
14 #include "core/fpdfapi/parser/cpdf_name.h"
15 #include "core/fpdfapi/parser/cpdf_number.h"
16 #include "core/fpdfapi/parser/cpdf_reference.h"
17 #include "core/fpdfapi/parser/cpdf_stream.h"
18 #include "core/fpdfapi/parser/cpdf_string.h"
19 #include "third_party/base/logging.h"
20 #include "third_party/base/stl_util.h"
21 
CPDF_Dictionary()22 CPDF_Dictionary::CPDF_Dictionary()
23     : CPDF_Dictionary(CFX_WeakPtr<CFX_ByteStringPool>()) {}
24 
CPDF_Dictionary(const CFX_WeakPtr<CFX_ByteStringPool> & pPool)25 CPDF_Dictionary::CPDF_Dictionary(const CFX_WeakPtr<CFX_ByteStringPool>& pPool)
26     : m_pPool(pPool) {}
27 
~CPDF_Dictionary()28 CPDF_Dictionary::~CPDF_Dictionary() {
29   // Mark the object as deleted so that it will not be deleted again,
30   // and break cyclic references.
31   m_ObjNum = kInvalidObjNum;
32   for (auto& it : m_Map) {
33     if (it.second && it.second->GetObjNum() == kInvalidObjNum)
34       it.second.release();
35   }
36 }
37 
GetType() const38 CPDF_Object::Type CPDF_Dictionary::GetType() const {
39   return DICTIONARY;
40 }
41 
GetDict() const42 CPDF_Dictionary* CPDF_Dictionary::GetDict() const {
43   // The method should be made non-const if we want to not be const.
44   // See bug #234.
45   return const_cast<CPDF_Dictionary*>(this);
46 }
47 
IsDictionary() const48 bool CPDF_Dictionary::IsDictionary() const {
49   return true;
50 }
51 
AsDictionary()52 CPDF_Dictionary* CPDF_Dictionary::AsDictionary() {
53   return this;
54 }
55 
AsDictionary() const56 const CPDF_Dictionary* CPDF_Dictionary::AsDictionary() const {
57   return this;
58 }
59 
Clone() const60 std::unique_ptr<CPDF_Object> CPDF_Dictionary::Clone() const {
61   return CloneObjectNonCyclic(false);
62 }
63 
CloneNonCyclic(bool bDirect,std::set<const CPDF_Object * > * pVisited) const64 std::unique_ptr<CPDF_Object> CPDF_Dictionary::CloneNonCyclic(
65     bool bDirect,
66     std::set<const CPDF_Object*>* pVisited) const {
67   pVisited->insert(this);
68   auto pCopy = pdfium::MakeUnique<CPDF_Dictionary>(m_pPool);
69   for (const auto& it : *this) {
70     if (!pdfium::ContainsKey(*pVisited, it.second.get())) {
71       pCopy->m_Map.insert(std::make_pair(
72           it.first, it.second->CloneNonCyclic(bDirect, pVisited)));
73     }
74   }
75   return std::move(pCopy);
76 }
77 
GetObjectFor(const CFX_ByteString & key) const78 CPDF_Object* CPDF_Dictionary::GetObjectFor(const CFX_ByteString& key) const {
79   auto it = m_Map.find(key);
80   return it != m_Map.end() ? it->second.get() : nullptr;
81 }
82 
GetDirectObjectFor(const CFX_ByteString & key) const83 CPDF_Object* CPDF_Dictionary::GetDirectObjectFor(
84     const CFX_ByteString& key) const {
85   CPDF_Object* p = GetObjectFor(key);
86   return p ? p->GetDirect() : nullptr;
87 }
88 
GetStringFor(const CFX_ByteString & key) const89 CFX_ByteString CPDF_Dictionary::GetStringFor(const CFX_ByteString& key) const {
90   CPDF_Object* p = GetObjectFor(key);
91   return p ? p->GetString() : CFX_ByteString();
92 }
93 
GetUnicodeTextFor(const CFX_ByteString & key) const94 CFX_WideString CPDF_Dictionary::GetUnicodeTextFor(
95     const CFX_ByteString& key) const {
96   CPDF_Object* p = GetObjectFor(key);
97   if (CPDF_Reference* pRef = ToReference(p))
98     p = pRef->GetDirect();
99   return p ? p->GetUnicodeText() : CFX_WideString();
100 }
101 
GetStringFor(const CFX_ByteString & key,const CFX_ByteString & def) const102 CFX_ByteString CPDF_Dictionary::GetStringFor(const CFX_ByteString& key,
103                                              const CFX_ByteString& def) const {
104   CPDF_Object* p = GetObjectFor(key);
105   return p ? p->GetString() : CFX_ByteString(def);
106 }
107 
GetIntegerFor(const CFX_ByteString & key) const108 int CPDF_Dictionary::GetIntegerFor(const CFX_ByteString& key) const {
109   CPDF_Object* p = GetObjectFor(key);
110   return p ? p->GetInteger() : 0;
111 }
112 
GetIntegerFor(const CFX_ByteString & key,int def) const113 int CPDF_Dictionary::GetIntegerFor(const CFX_ByteString& key, int def) const {
114   CPDF_Object* p = GetObjectFor(key);
115   return p ? p->GetInteger() : def;
116 }
117 
GetNumberFor(const CFX_ByteString & key) const118 FX_FLOAT CPDF_Dictionary::GetNumberFor(const CFX_ByteString& key) const {
119   CPDF_Object* p = GetObjectFor(key);
120   return p ? p->GetNumber() : 0;
121 }
122 
GetBooleanFor(const CFX_ByteString & key,bool bDefault) const123 bool CPDF_Dictionary::GetBooleanFor(const CFX_ByteString& key,
124                                     bool bDefault) const {
125   CPDF_Object* p = GetObjectFor(key);
126   return ToBoolean(p) ? p->GetInteger() != 0 : bDefault;
127 }
128 
GetDictFor(const CFX_ByteString & key) const129 CPDF_Dictionary* CPDF_Dictionary::GetDictFor(const CFX_ByteString& key) const {
130   CPDF_Object* p = GetDirectObjectFor(key);
131   if (!p)
132     return nullptr;
133   if (CPDF_Dictionary* pDict = p->AsDictionary())
134     return pDict;
135   if (CPDF_Stream* pStream = p->AsStream())
136     return pStream->GetDict();
137   return nullptr;
138 }
139 
GetArrayFor(const CFX_ByteString & key) const140 CPDF_Array* CPDF_Dictionary::GetArrayFor(const CFX_ByteString& key) const {
141   return ToArray(GetDirectObjectFor(key));
142 }
143 
GetStreamFor(const CFX_ByteString & key) const144 CPDF_Stream* CPDF_Dictionary::GetStreamFor(const CFX_ByteString& key) const {
145   return ToStream(GetDirectObjectFor(key));
146 }
147 
GetRectFor(const CFX_ByteString & key) const148 CFX_FloatRect CPDF_Dictionary::GetRectFor(const CFX_ByteString& key) const {
149   CFX_FloatRect rect;
150   CPDF_Array* pArray = GetArrayFor(key);
151   if (pArray)
152     rect = pArray->GetRect();
153   return rect;
154 }
155 
GetMatrixFor(const CFX_ByteString & key) const156 CFX_Matrix CPDF_Dictionary::GetMatrixFor(const CFX_ByteString& key) const {
157   CFX_Matrix matrix;
158   CPDF_Array* pArray = GetArrayFor(key);
159   if (pArray)
160     matrix = pArray->GetMatrix();
161   return matrix;
162 }
163 
KeyExist(const CFX_ByteString & key) const164 bool CPDF_Dictionary::KeyExist(const CFX_ByteString& key) const {
165   return pdfium::ContainsKey(m_Map, key);
166 }
167 
IsSignatureDict() const168 bool CPDF_Dictionary::IsSignatureDict() const {
169   CPDF_Object* pType = GetDirectObjectFor("Type");
170   if (!pType)
171     pType = GetDirectObjectFor("FT");
172   return pType && pType->GetString() == "Sig";
173 }
174 
SetFor(const CFX_ByteString & key,std::unique_ptr<CPDF_Object> pObj)175 CPDF_Object* CPDF_Dictionary::SetFor(const CFX_ByteString& key,
176                                      std::unique_ptr<CPDF_Object> pObj) {
177   if (!pObj) {
178     m_Map.erase(key);
179     return nullptr;
180   }
181   ASSERT(pObj->IsInline());
182   CPDF_Object* pRet = pObj.get();
183   m_Map[MaybeIntern(key)] = std::move(pObj);
184   return pRet;
185 }
186 
ConvertToIndirectObjectFor(const CFX_ByteString & key,CPDF_IndirectObjectHolder * pHolder)187 void CPDF_Dictionary::ConvertToIndirectObjectFor(
188     const CFX_ByteString& key,
189     CPDF_IndirectObjectHolder* pHolder) {
190   auto it = m_Map.find(key);
191   if (it == m_Map.end() || it->second->IsReference())
192     return;
193 
194   CPDF_Object* pObj = pHolder->AddIndirectObject(std::move(it->second));
195   it->second = pdfium::MakeUnique<CPDF_Reference>(pHolder, pObj->GetObjNum());
196 }
197 
RemoveFor(const CFX_ByteString & key)198 void CPDF_Dictionary::RemoveFor(const CFX_ByteString& key) {
199   m_Map.erase(key);
200 }
201 
ReplaceKey(const CFX_ByteString & oldkey,const CFX_ByteString & newkey)202 void CPDF_Dictionary::ReplaceKey(const CFX_ByteString& oldkey,
203                                  const CFX_ByteString& newkey) {
204   auto old_it = m_Map.find(oldkey);
205   if (old_it == m_Map.end())
206     return;
207 
208   auto new_it = m_Map.find(newkey);
209   if (new_it == old_it)
210     return;
211 
212   m_Map[MaybeIntern(newkey)] = std::move(old_it->second);
213   m_Map.erase(old_it);
214 }
215 
SetRectFor(const CFX_ByteString & key,const CFX_FloatRect & rect)216 void CPDF_Dictionary::SetRectFor(const CFX_ByteString& key,
217                                  const CFX_FloatRect& rect) {
218   CPDF_Array* pArray = SetNewFor<CPDF_Array>(key);
219   pArray->AddNew<CPDF_Number>(rect.left);
220   pArray->AddNew<CPDF_Number>(rect.bottom);
221   pArray->AddNew<CPDF_Number>(rect.right);
222   pArray->AddNew<CPDF_Number>(rect.top);
223 }
224 
SetMatrixFor(const CFX_ByteString & key,const CFX_Matrix & matrix)225 void CPDF_Dictionary::SetMatrixFor(const CFX_ByteString& key,
226                                    const CFX_Matrix& matrix) {
227   CPDF_Array* pArray = SetNewFor<CPDF_Array>(key);
228   pArray->AddNew<CPDF_Number>(matrix.a);
229   pArray->AddNew<CPDF_Number>(matrix.b);
230   pArray->AddNew<CPDF_Number>(matrix.c);
231   pArray->AddNew<CPDF_Number>(matrix.d);
232   pArray->AddNew<CPDF_Number>(matrix.e);
233   pArray->AddNew<CPDF_Number>(matrix.f);
234 }
235 
MaybeIntern(const CFX_ByteString & str)236 CFX_ByteString CPDF_Dictionary::MaybeIntern(const CFX_ByteString& str) {
237   return m_pPool ? m_pPool->Intern(str) : str;
238 }
239