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 
GetDest(CPDF_Document * pDoc) const9 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", ""};
GetType() const35 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 }
GetFilePath() const51 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 }
GetURI(CPDF_Document * pDoc) const72 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 }
GetFieldsCount() const90 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 
GetAllFields() const116 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 
GetField(FX_DWORD iIndex) const148 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 
GetJavaScript() const176 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 }
GetAnnot() const184 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 }
GetOperationType() const197 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 }
GetSubActionsCount() const222 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 }
GetSubAction(FX_DWORD iIndex) const235 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", ""};
ActionExist(AActionType eType) const251 FX_BOOL CPDF_AAction::ActionExist(AActionType eType) const {
252   return m_pDict && m_pDict->KeyExist(g_sAATypes[(int)eType]);
253 }
GetAction(AActionType eType) const254 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 
CPDF_DocJSActions(CPDF_Document * pDoc)261 CPDF_DocJSActions::CPDF_DocJSActions(CPDF_Document* pDoc) : m_pDocument(pDoc) {}
262 
CountJSActions() const263 int CPDF_DocJSActions::CountJSActions() const {
264   ASSERT(m_pDocument);
265   CPDF_NameTree name_tree(m_pDocument, "JavaScript");
266   return name_tree.GetCount();
267 }
GetJSAction(int index,CFX_ByteString & csName) const268 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 }
GetJSAction(const CFX_ByteString & csName) const278 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 }
FindJSAction(const CFX_ByteString & csName) const287 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