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 22 CPDF_Dictionary::CPDF_Dictionary() 23 : CPDF_Dictionary(CFX_WeakPtr<CFX_ByteStringPool>()) {} 24 25 CPDF_Dictionary::CPDF_Dictionary(const CFX_WeakPtr<CFX_ByteStringPool>& pPool) 26 : m_pPool(pPool) {} 27 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 38 CPDF_Object::Type CPDF_Dictionary::GetType() const { 39 return DICTIONARY; 40 } 41 42 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 48 bool CPDF_Dictionary::IsDictionary() const { 49 return true; 50 } 51 52 CPDF_Dictionary* CPDF_Dictionary::AsDictionary() { 53 return this; 54 } 55 56 const CPDF_Dictionary* CPDF_Dictionary::AsDictionary() const { 57 return this; 58 } 59 60 std::unique_ptr<CPDF_Object> CPDF_Dictionary::Clone() const { 61 return CloneObjectNonCyclic(false); 62 } 63 64 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 78 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 83 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 89 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 94 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 102 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 108 int CPDF_Dictionary::GetIntegerFor(const CFX_ByteString& key) const { 109 CPDF_Object* p = GetObjectFor(key); 110 return p ? p->GetInteger() : 0; 111 } 112 113 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 118 FX_FLOAT CPDF_Dictionary::GetNumberFor(const CFX_ByteString& key) const { 119 CPDF_Object* p = GetObjectFor(key); 120 return p ? p->GetNumber() : 0; 121 } 122 123 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 129 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 140 CPDF_Array* CPDF_Dictionary::GetArrayFor(const CFX_ByteString& key) const { 141 return ToArray(GetDirectObjectFor(key)); 142 } 143 144 CPDF_Stream* CPDF_Dictionary::GetStreamFor(const CFX_ByteString& key) const { 145 return ToStream(GetDirectObjectFor(key)); 146 } 147 148 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 156 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 164 bool CPDF_Dictionary::KeyExist(const CFX_ByteString& key) const { 165 return pdfium::ContainsKey(m_Map, key); 166 } 167 168 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 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 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 198 void CPDF_Dictionary::RemoveFor(const CFX_ByteString& key) { 199 m_Map.erase(key); 200 } 201 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 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 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 236 CFX_ByteString CPDF_Dictionary::MaybeIntern(const CFX_ByteString& str) { 237 return m_pPool ? m_pPool->Intern(str) : str; 238 } 239