1 // Copyright 2014 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/include/fpdfdoc/fpdf_doc.h" 8 9 CPDF_Dest CPDF_Action::GetDest(CPDF_Document* pDoc) const { 10 if (!m_pDict) { 11 return CPDF_Dest(); 12 } 13 CFX_ByteString type = m_pDict->GetString("S"); 14 if (type != "GoTo" && type != "GoToR") { 15 return CPDF_Dest(); 16 } 17 CPDF_Object* pDest = m_pDict->GetElementValue("D"); 18 if (!pDest) { 19 return CPDF_Dest(); 20 } 21 if (pDest->IsString() || pDest->IsName()) { 22 CPDF_NameTree name_tree(pDoc, "Dests"); 23 CFX_ByteStringC name = pDest->GetString(); 24 return CPDF_Dest(name_tree.LookupNamedDest(pDoc, name)); 25 } 26 if (CPDF_Array* pArray = pDest->AsArray()) 27 return CPDF_Dest(pArray); 28 return CPDF_Dest(); 29 } 30 const FX_CHAR* g_sATypes[] = { 31 "Unknown", "GoTo", "GoToR", "GoToE", "Launch", 32 "Thread", "URI", "Sound", "Movie", "Hide", 33 "Named", "SubmitForm", "ResetForm", "ImportData", "JavaScript", 34 "SetOCGState", "Rendition", "Trans", "GoTo3DView", ""}; 35 CPDF_Action::ActionType CPDF_Action::GetType() const { 36 ActionType eType = Unknown; 37 if (m_pDict) { 38 CFX_ByteString csType = m_pDict->GetString("S"); 39 if (!csType.IsEmpty()) { 40 int i = 0; 41 while (g_sATypes[i][0] != '\0') { 42 if (csType == g_sATypes[i]) { 43 return (ActionType)i; 44 } 45 i++; 46 } 47 } 48 } 49 return eType; 50 } 51 CFX_WideString CPDF_Action::GetFilePath() const { 52 CFX_ByteString type = m_pDict->GetString("S"); 53 if (type != "GoToR" && type != "Launch" && type != "SubmitForm" && 54 type != "ImportData") { 55 return CFX_WideString(); 56 } 57 CPDF_Object* pFile = m_pDict->GetElementValue("F"); 58 CFX_WideString path; 59 if (!pFile) { 60 if (type == "Launch") { 61 CPDF_Dictionary* pWinDict = m_pDict->GetDict("Win"); 62 if (pWinDict) { 63 return CFX_WideString::FromLocal(pWinDict->GetString("F")); 64 } 65 } 66 return path; 67 } 68 CPDF_FileSpec filespec(pFile); 69 filespec.GetFileName(path); 70 return path; 71 } 72 CFX_ByteString CPDF_Action::GetURI(CPDF_Document* pDoc) const { 73 CFX_ByteString csURI; 74 if (!m_pDict) { 75 return csURI; 76 } 77 if (m_pDict->GetString("S") != "URI") { 78 return csURI; 79 } 80 csURI = m_pDict->GetString("URI"); 81 CPDF_Dictionary* pRoot = pDoc->GetRoot(); 82 CPDF_Dictionary* pURI = pRoot->GetDict("URI"); 83 if (pURI) { 84 if (csURI.Find(":", 0) < 1) { 85 csURI = pURI->GetString("Base") + csURI; 86 } 87 } 88 return csURI; 89 } 90 FX_DWORD CPDF_ActionFields::GetFieldsCount() const { 91 if (!m_pAction) { 92 return 0; 93 } 94 CPDF_Dictionary* pDict = m_pAction->GetDict(); 95 if (!pDict) { 96 return 0; 97 } 98 CFX_ByteString csType = pDict->GetString("S"); 99 CPDF_Object* pFields = NULL; 100 if (csType == "Hide") { 101 pFields = pDict->GetElementValue("T"); 102 } else { 103 pFields = pDict->GetArray("Fields"); 104 } 105 if (!pFields) 106 return 0; 107 if (pFields->IsDictionary()) 108 return 1; 109 if (pFields->IsString()) 110 return 1; 111 if (CPDF_Array* pArray = pFields->AsArray()) 112 return pArray->GetCount(); 113 return 0; 114 } 115 116 std::vector<CPDF_Object*> CPDF_ActionFields::GetAllFields() const { 117 std::vector<CPDF_Object*> fields; 118 if (!m_pAction) 119 return fields; 120 121 CPDF_Dictionary* pDict = m_pAction->GetDict(); 122 if (!pDict) 123 return fields; 124 125 CFX_ByteString csType = pDict->GetString("S"); 126 CPDF_Object* pFields; 127 if (csType == "Hide") 128 pFields = pDict->GetElementValue("T"); 129 else 130 pFields = pDict->GetArray("Fields"); 131 if (!pFields) 132 return fields; 133 134 if (pFields->IsDictionary() || pFields->IsString()) { 135 fields.push_back(pFields); 136 } else if (CPDF_Array* pArray = pFields->AsArray()) { 137 FX_DWORD iCount = pArray->GetCount(); 138 for (FX_DWORD i = 0; i < iCount; ++i) { 139 CPDF_Object* pObj = pArray->GetElementValue(i); 140 if (pObj) { 141 fields.push_back(pObj); 142 } 143 } 144 } 145 return fields; 146 } 147 148 CPDF_Object* CPDF_ActionFields::GetField(FX_DWORD iIndex) const { 149 if (!m_pAction) { 150 return NULL; 151 } 152 CPDF_Dictionary* pDict = m_pAction->GetDict(); 153 if (!pDict) { 154 return NULL; 155 } 156 CFX_ByteString csType = pDict->GetString("S"); 157 CPDF_Object* pFields = NULL; 158 if (csType == "Hide") { 159 pFields = pDict->GetElementValue("T"); 160 } else { 161 pFields = pDict->GetArray("Fields"); 162 } 163 if (!pFields) { 164 return NULL; 165 } 166 CPDF_Object* pFindObj = NULL; 167 if (pFields->IsDictionary() || pFields->IsString()) { 168 if (iIndex == 0) 169 pFindObj = pFields; 170 } else if (CPDF_Array* pArray = pFields->AsArray()) { 171 pFindObj = pArray->GetElementValue(iIndex); 172 } 173 return pFindObj; 174 } 175 176 CFX_WideString CPDF_Action::GetJavaScript() const { 177 CFX_WideString csJS; 178 if (!m_pDict) { 179 return csJS; 180 } 181 CPDF_Object* pJS = m_pDict->GetElementValue("JS"); 182 return pJS ? pJS->GetUnicodeText() : csJS; 183 } 184 CPDF_Dictionary* CPDF_Action::GetAnnot() const { 185 if (!m_pDict) { 186 return nullptr; 187 } 188 CFX_ByteString csType = m_pDict->GetString("S"); 189 if (csType == "Rendition") { 190 return m_pDict->GetDict("AN"); 191 } 192 if (csType == "Movie") { 193 return m_pDict->GetDict("Annotation"); 194 } 195 return nullptr; 196 } 197 int32_t CPDF_Action::GetOperationType() const { 198 if (!m_pDict) { 199 return 0; 200 } 201 CFX_ByteString csType = m_pDict->GetString("S"); 202 if (csType == "Rendition") { 203 return m_pDict->GetInteger("OP"); 204 } 205 if (csType == "Movie") { 206 CFX_ByteString csOP = m_pDict->GetString("Operation"); 207 if (csOP == "Play") { 208 return 0; 209 } 210 if (csOP == "Stop") { 211 return 1; 212 } 213 if (csOP == "Pause") { 214 return 2; 215 } 216 if (csOP == "Resume") { 217 return 3; 218 } 219 } 220 return 0; 221 } 222 FX_DWORD CPDF_Action::GetSubActionsCount() const { 223 if (!m_pDict || !m_pDict->KeyExist("Next")) 224 return 0; 225 226 CPDF_Object* pNext = m_pDict->GetElementValue("Next"); 227 if (!pNext) 228 return 0; 229 if (pNext->IsDictionary()) 230 return 1; 231 if (CPDF_Array* pArray = pNext->AsArray()) 232 return pArray->GetCount(); 233 return 0; 234 } 235 CPDF_Action CPDF_Action::GetSubAction(FX_DWORD iIndex) const { 236 if (!m_pDict || !m_pDict->KeyExist("Next")) { 237 return CPDF_Action(); 238 } 239 CPDF_Object* pNext = m_pDict->GetElementValue("Next"); 240 if (CPDF_Dictionary* pDict = ToDictionary(pNext)) { 241 if (iIndex == 0) 242 return CPDF_Action(pDict); 243 } else if (CPDF_Array* pArray = ToArray(pNext)) { 244 return CPDF_Action(pArray->GetDict(iIndex)); 245 } 246 return CPDF_Action(); 247 } 248 const FX_CHAR* g_sAATypes[] = {"E", "X", "D", "U", "Fo", "Bl", "PO", "PC", 249 "PV", "PI", "O", "C", "K", "F", "V", "C", 250 "WC", "WS", "DS", "WP", "DP", ""}; 251 FX_BOOL CPDF_AAction::ActionExist(AActionType eType) const { 252 return m_pDict && m_pDict->KeyExist(g_sAATypes[(int)eType]); 253 } 254 CPDF_Action CPDF_AAction::GetAction(AActionType eType) const { 255 if (!m_pDict) { 256 return CPDF_Action(); 257 } 258 return CPDF_Action(m_pDict->GetDict(g_sAATypes[(int)eType])); 259 } 260 261 CPDF_DocJSActions::CPDF_DocJSActions(CPDF_Document* pDoc) : m_pDocument(pDoc) {} 262 263 int CPDF_DocJSActions::CountJSActions() const { 264 ASSERT(m_pDocument); 265 CPDF_NameTree name_tree(m_pDocument, "JavaScript"); 266 return name_tree.GetCount(); 267 } 268 CPDF_Action CPDF_DocJSActions::GetJSAction(int index, 269 CFX_ByteString& csName) const { 270 ASSERT(m_pDocument); 271 CPDF_NameTree name_tree(m_pDocument, "JavaScript"); 272 CPDF_Object* pAction = name_tree.LookupValue(index, csName); 273 if (!ToDictionary(pAction)) { 274 return CPDF_Action(); 275 } 276 return CPDF_Action(pAction->GetDict()); 277 } 278 CPDF_Action CPDF_DocJSActions::GetJSAction(const CFX_ByteString& csName) const { 279 ASSERT(m_pDocument); 280 CPDF_NameTree name_tree(m_pDocument, "JavaScript"); 281 CPDF_Object* pAction = name_tree.LookupValue(csName); 282 if (!ToDictionary(pAction)) { 283 return CPDF_Action(); 284 } 285 return CPDF_Action(pAction->GetDict()); 286 } 287 int CPDF_DocJSActions::FindJSAction(const CFX_ByteString& csName) const { 288 ASSERT(m_pDocument); 289 CPDF_NameTree name_tree(m_pDocument, "JavaScript"); 290 return name_tree.GetIndex(csName); 291 } 292