e98d3af9e718164efe1a8c07c9f733d81fbf0959
[pdfium.git] / core / src / fpdfdoc / doc_action.cpp
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 "../../include/fpdfdoc/fpdf_doc.h"
8 CPDF_Dest CPDF_Action::GetDest(CPDF_Document* pDoc) const
9 {
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->GetType() == PDFOBJ_STRING || pDest->GetType() == PDFOBJ_NAME) {
22         CPDF_NameTree name_tree(pDoc, FX_BSTRC("Dests"));
23         CFX_ByteStringC name = pDest->GetString();
24         return CPDF_Dest(name_tree.LookupNamedDest(pDoc, name));
25     }
26     if (pDest->GetType() == PDFOBJ_ARRAY) {
27         return CPDF_Dest((CPDF_Array*)pDest);
28     }
29     return CPDF_Dest();
30 }
31 const FX_CHAR* g_sATypes[] = {"Unknown", "GoTo", "GoToR", "GoToE", "Launch", "Thread", "URI", "Sound", "Movie",
32                               "Hide",   "Named", "SubmitForm", "ResetForm", "ImportData", "JavaScript", "SetOCGState",
33                               "Rendition", "Trans", "GoTo3DView", ""
34                              };
35 CPDF_Action::ActionType CPDF_Action::GetType() const
36 {
37     ActionType eType = Unknown;
38     if (m_pDict != NULL) {
39         CFX_ByteString csType = m_pDict->GetString("S");
40         if (!csType.IsEmpty()) {
41             int i = 0;
42             while (g_sATypes[i][0] != '\0') {
43                 if (csType == g_sATypes[i]) {
44                     return (ActionType)i;
45                 }
46                 i ++;
47             }
48         }
49     }
50     return eType;
51 }
52 CFX_WideString CPDF_Action::GetFilePath() const
53 {
54     CFX_ByteString type = m_pDict->GetString("S");
55     if (type != "GoToR" && type != "Launch" &&
56             type != "SubmitForm" && type != "ImportData") {
57         return CFX_WideString();
58     }
59     CPDF_Object* pFile = m_pDict->GetElementValue("F");
60     CFX_WideString path;
61     if (pFile == NULL) {
62         if (type == "Launch") {
63             CPDF_Dictionary* pWinDict = m_pDict->GetDict(FX_BSTRC("Win"));
64             if (pWinDict) {
65                 return CFX_WideString::FromLocal(pWinDict->GetString(FX_BSTRC("F")));
66             }
67         }
68         return path;
69     }
70     CPDF_FileSpec filespec(pFile);
71     filespec.GetFileName(path);
72     return path;
73 }
74 CFX_ByteString CPDF_Action::GetURI(CPDF_Document* pDoc) const
75 {
76     CFX_ByteString csURI;
77     if (m_pDict == NULL) {
78         return csURI;
79     }
80     if (m_pDict->GetString("S") != "URI") {
81         return csURI;
82     }
83     csURI = m_pDict->GetString("URI");
84     CPDF_Dictionary* pRoot = pDoc->GetRoot();
85     CPDF_Dictionary* pURI = pRoot->GetDict("URI");
86     if (pURI != NULL) {
87         if (csURI.Find(FX_BSTRC(":"), 0) < 1) {
88             csURI = pURI->GetString("Base") + csURI;
89         }
90     }
91     return csURI;
92 }
93 FX_DWORD CPDF_ActionFields::GetFieldsCount() const
94 {
95     if (m_pAction == NULL) {
96         return 0;
97     }
98     CPDF_Dictionary* pDict = m_pAction->GetDict();
99     if (pDict == NULL) {
100         return 0;
101     }
102     CFX_ByteString csType = pDict->GetString("S");
103     CPDF_Object* pFields = NULL;
104     if (csType == "Hide") {
105         pFields = pDict->GetElementValue("T");
106     } else {
107         pFields = pDict->GetArray("Fields");
108     }
109     if (pFields == NULL) {
110         return 0;
111     }
112     int iType = pFields->GetType();
113     if (iType == PDFOBJ_DICTIONARY) {
114         return 1;
115     } else if (iType == PDFOBJ_STRING) {
116         return 1;
117     } else if (iType == PDFOBJ_ARRAY) {
118         return ((CPDF_Array*)pFields)->GetCount();
119     }
120     return 0;
121 }
122 void CPDF_ActionFields::GetAllFields(CFX_PtrArray& fieldObjects) const
123 {
124     fieldObjects.RemoveAll();
125     if (m_pAction == NULL) {
126         return;
127     }
128     CPDF_Dictionary* pDict = m_pAction->GetDict();
129     if (pDict == NULL) {
130         return;
131     }
132     CFX_ByteString csType = pDict->GetString("S");
133     CPDF_Object* pFields = NULL;
134     if (csType == "Hide") {
135         pFields = pDict->GetElementValue("T");
136     } else {
137         pFields = pDict->GetArray("Fields");
138     }
139     if (pFields == NULL) {
140         return;
141     }
142     int iType = pFields->GetType();
143     if (iType == PDFOBJ_DICTIONARY || iType == PDFOBJ_STRING) {
144         fieldObjects.Add(pFields);
145     } else if (iType == PDFOBJ_ARRAY) {
146         CPDF_Array* pArray = (CPDF_Array*)pFields;
147         FX_DWORD iCount = pArray->GetCount();
148         for (FX_DWORD i = 0; i < iCount; i ++) {
149             CPDF_Object* pObj = pArray->GetElementValue(i);
150             if (pObj != NULL) {
151                 fieldObjects.Add(pObj);
152             }
153         }
154     }
155 }
156 CPDF_Object* CPDF_ActionFields::GetField(FX_DWORD iIndex) const
157 {
158     if (m_pAction == NULL) {
159         return NULL;
160     }
161     CPDF_Dictionary* pDict = m_pAction->GetDict();
162     if (pDict == NULL) {
163         return NULL;
164     }
165     CFX_ByteString csType = pDict->GetString("S");
166     CPDF_Object* pFields = NULL;
167     if (csType == "Hide") {
168         pFields = pDict->GetElementValue("T");
169     } else {
170         pFields = pDict->GetArray("Fields");
171     }
172     if (pFields == NULL) {
173         return NULL;
174     }
175     CPDF_Object* pFindObj = NULL;
176     int iType = pFields->GetType();
177     if (iType == PDFOBJ_DICTIONARY || iType == PDFOBJ_STRING) {
178         if (iIndex == 0) {
179             pFindObj = pFields;
180         }
181     } else if (iType == PDFOBJ_ARRAY) {
182         pFindObj = ((CPDF_Array*)pFields)->GetElementValue(iIndex);
183     }
184     return pFindObj;
185 }
186 CPDF_LWinParam CPDF_Action::GetWinParam() const
187 {
188     if (m_pDict == NULL) {
189         return NULL;
190     }
191     if (m_pDict->GetString("S") != "Launch") {
192         return NULL;
193     }
194     return m_pDict->GetDict("Win");
195 }
196 CFX_WideString CPDF_Action::GetJavaScript() const
197 {
198     CFX_WideString csJS;
199     if (m_pDict == NULL) {
200         return csJS;
201     }
202     CPDF_Object* pJS = m_pDict->GetElementValue("JS");
203     if (pJS != NULL) {
204         return pJS->GetUnicodeText();
205     }
206     return csJS;
207 }
208 CPDF_Dictionary* CPDF_Action::GetAnnot() const
209 {
210     if (m_pDict == NULL) {
211         return NULL;
212     }
213     CFX_ByteString csType = m_pDict->GetString("S");
214     if (csType == FX_BSTRC("Rendition")) {
215         return m_pDict->GetDict("AN");
216     } else if (csType == FX_BSTRC("Movie")) {
217         return m_pDict->GetDict("Annotation");
218     }
219     return NULL;
220 }
221 int32_t CPDF_Action::GetOperationType() const
222 {
223     if (m_pDict == NULL) {
224         return 0;
225     }
226     CFX_ByteString csType = m_pDict->GetString("S");
227     if (csType == FX_BSTRC("Rendition")) {
228         return m_pDict->GetInteger("OP");
229     } else if (csType == FX_BSTRC("Movie")) {
230         CFX_ByteString csOP = m_pDict->GetString("Operation");
231         if (csOP == FX_BSTRC("Play")) {
232             return 0;
233         } else if (csOP == FX_BSTRC("Stop")) {
234             return 1;
235         } else if (csOP == FX_BSTRC("Pause")) {
236             return 2;
237         } else if (csOP == FX_BSTRC("Resume")) {
238             return 3;
239         }
240     }
241     return 0;
242 }
243 FX_DWORD CPDF_Action::GetSubActionsCount() const
244 {
245     if (m_pDict == NULL || !m_pDict->KeyExist("Next")) {
246         return 0;
247     }
248     CPDF_Object* pNext = m_pDict->GetElementValue("Next");
249     if (!pNext) {
250         return 0;
251     }
252     int iObjType = pNext->GetType();
253     if (iObjType == PDFOBJ_DICTIONARY) {
254         return 1;
255     }
256     if (iObjType == PDFOBJ_ARRAY) {
257         return ((CPDF_Array*)pNext)->GetCount();
258     }
259     return 0;
260 }
261 CPDF_Action CPDF_Action::GetSubAction(FX_DWORD iIndex) const
262 {
263     if (m_pDict == NULL || !m_pDict->KeyExist("Next")) {
264         return CPDF_Action();
265     }
266     CPDF_Object* pNext = m_pDict->GetElementValue("Next");
267     int iObjType = pNext->GetType();
268     if (iObjType == PDFOBJ_DICTIONARY) {
269         CPDF_Dictionary *pDict = static_cast<CPDF_Dictionary*>(pNext);
270         if (iIndex == 0) {
271             return CPDF_Action(pDict);
272         }
273     } else if (iObjType == PDFOBJ_ARRAY) {
274         CPDF_Array* pArray = static_cast<CPDF_Array*>(pNext);
275         return CPDF_Action(pArray->GetDict(iIndex));
276     }
277     return CPDF_Action();
278 }
279 const FX_CHAR* g_sAATypes[] = {"E", "X", "D", "U", "Fo", "Bl", "PO", "PC", "PV", "PI",
280                                "O", "C",
281                                "K", "F", "V", "C",
282                                "WC", "WS", "DS", "WP", "DP",
283                                ""
284                               };
285 FX_BOOL CPDF_AAction::ActionExist(AActionType eType) const
286 {
287     if (m_pDict == NULL) {
288         return FALSE;
289     }
290     return m_pDict->KeyExist(g_sAATypes[(int)eType]);
291 }
292 CPDF_Action CPDF_AAction::GetAction(AActionType eType) const
293 {
294     if (!m_pDict) {
295         return CPDF_Action();
296     }
297     return CPDF_Action(m_pDict->GetDict(g_sAATypes[(int)eType]));
298 }
299 FX_POSITION CPDF_AAction::GetStartPos() const
300 {
301     if (m_pDict == NULL) {
302         return NULL;
303     }
304     return m_pDict->GetStartPos();
305 }
306 CPDF_Action CPDF_AAction::GetNextAction(FX_POSITION& pos, AActionType& eType) const
307 {
308     if (m_pDict == NULL) {
309         return CPDF_Action();
310     }
311     CFX_ByteString csKey;
312     CPDF_Object* pObj = m_pDict->GetNextElement(pos, csKey);
313     if (!pObj) {
314         return CPDF_Action();
315     }
316     CPDF_Object* pDirect = pObj->GetDirect();
317     if (!pDirect || pDirect->GetType() != PDFOBJ_DICTIONARY) {
318         return CPDF_Action();
319     }
320     int i = 0;
321     while (g_sAATypes[i][0] != '\0') {
322         if (csKey == g_sAATypes[i]) {
323             break;
324         }
325         i++;
326     }
327     eType = (AActionType)i;
328     return CPDF_Action(static_cast<CPDF_Dictionary*>(pDirect));
329 }
330 CPDF_DocJSActions::CPDF_DocJSActions(CPDF_Document* pDoc)
331 {
332     m_pDocument = pDoc;
333 }
334 int CPDF_DocJSActions::CountJSActions() const
335 {
336     ASSERT(m_pDocument != NULL);
337     CPDF_NameTree name_tree(m_pDocument, FX_BSTRC("JavaScript"));
338     return name_tree.GetCount();
339 }
340 CPDF_Action CPDF_DocJSActions::GetJSAction(int index, CFX_ByteString& csName) const
341 {
342     ASSERT(m_pDocument != NULL);
343     CPDF_NameTree name_tree(m_pDocument, FX_BSTRC("JavaScript"));
344     CPDF_Object *pAction = name_tree.LookupValue(index, csName);
345     if (pAction == NULL || pAction->GetType() != PDFOBJ_DICTIONARY) {
346         return CPDF_Action();
347     }
348     return CPDF_Action(pAction->GetDict());
349 }
350 CPDF_Action CPDF_DocJSActions::GetJSAction(const CFX_ByteString& csName) const
351 {
352     ASSERT(m_pDocument != NULL);
353     CPDF_NameTree name_tree(m_pDocument, FX_BSTRC("JavaScript"));
354     CPDF_Object *pAction = name_tree.LookupValue(csName);
355     if (pAction == NULL || pAction->GetType() != PDFOBJ_DICTIONARY) {
356         return CPDF_Action();
357     }
358     return CPDF_Action(pAction->GetDict());
359 }
360 int CPDF_DocJSActions::FindJSAction(const CFX_ByteString& csName) const
361 {
362     ASSERT(m_pDocument != NULL);
363     CPDF_NameTree name_tree(m_pDocument, FX_BSTRC("JavaScript"));
364     return name_tree.GetIndex(csName);
365 }