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