801c69fbb78e7e8addd8422769c9f5eb59042047
[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 = (CPDF_Dictionary*)(*m_pAction);
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 = (CPDF_Dictionary*)(*m_pAction);
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 = (CPDF_Dictionary*)(*m_pAction);
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 NULL;
264     }
265     CPDF_Object* pNext = m_pDict->GetElementValue("Next");
266     int iObjType = pNext->GetType();
267     if (iObjType == PDFOBJ_DICTIONARY) {
268         if (iIndex == 0) {
269             return (CPDF_Dictionary*)pNext;
270         }
271     }
272     if (iObjType == PDFOBJ_ARRAY) {
273         return ((CPDF_Array*)pNext)->GetDict(iIndex);
274     }
275     return NULL;
276 }
277 const FX_CHAR* g_sAATypes[] = {"E", "X", "D", "U", "Fo", "Bl", "PO", "PC", "PV", "PI",
278                                "O", "C",
279                                "K", "F", "V", "C",
280                                "WC", "WS", "DS", "WP", "DP",
281                                ""
282                               };
283 FX_BOOL CPDF_AAction::ActionExist(AActionType eType) const
284 {
285     if (m_pDict == NULL) {
286         return FALSE;
287     }
288     return m_pDict->KeyExist(g_sAATypes[(int)eType]);
289 }
290 CPDF_Action CPDF_AAction::GetAction(AActionType eType) const
291 {
292     if (m_pDict == NULL) {
293         return NULL;
294     }
295     return m_pDict->GetDict(g_sAATypes[(int)eType]);
296 }
297 FX_POSITION CPDF_AAction::GetStartPos() const
298 {
299     if (m_pDict == NULL) {
300         return NULL;
301     }
302     return m_pDict->GetStartPos();
303 }
304 CPDF_Action CPDF_AAction::GetNextAction(FX_POSITION& pos, AActionType& eType) const
305 {
306     if (m_pDict == NULL) {
307         return NULL;
308     }
309     CFX_ByteString csKey;
310     CPDF_Object* pObj = m_pDict->GetNextElement(pos, csKey);
311     if (pObj != NULL) {
312         CPDF_Object* pDirect = pObj->GetDirect();
313         if (pDirect != NULL && pDirect->GetType() == PDFOBJ_DICTIONARY) {
314             int i = 0;
315             while (g_sAATypes[i][0] != '\0') {
316                 if (csKey == g_sAATypes[i]) {
317                     break;
318                 }
319                 i ++;
320             }
321             eType = (AActionType)i;
322             return (CPDF_Dictionary*)pDirect;
323         }
324     }
325     return NULL;
326 }
327 CPDF_DocJSActions::CPDF_DocJSActions(CPDF_Document* pDoc)
328 {
329     m_pDocument = pDoc;
330 }
331 int CPDF_DocJSActions::CountJSActions() const
332 {
333     ASSERT(m_pDocument != NULL);
334     CPDF_NameTree name_tree(m_pDocument, FX_BSTRC("JavaScript"));
335     return name_tree.GetCount();
336 }
337 CPDF_Action CPDF_DocJSActions::GetJSAction(int index, CFX_ByteString& csName) const
338 {
339     ASSERT(m_pDocument != NULL);
340     CPDF_NameTree name_tree(m_pDocument, FX_BSTRC("JavaScript"));
341     CPDF_Object *pAction = name_tree.LookupValue(index, csName);
342     if (pAction == NULL || pAction->GetType() != PDFOBJ_DICTIONARY) {
343         return NULL;
344     }
345     return pAction->GetDict();
346 }
347 CPDF_Action CPDF_DocJSActions::GetJSAction(const CFX_ByteString& csName) const
348 {
349     ASSERT(m_pDocument != NULL);
350     CPDF_NameTree name_tree(m_pDocument, FX_BSTRC("JavaScript"));
351     CPDF_Object *pAction = name_tree.LookupValue(csName);
352     if (pAction == NULL || pAction->GetType() != PDFOBJ_DICTIONARY) {
353         return NULL;
354     }
355     return pAction->GetDict();
356 }
357 int CPDF_DocJSActions::FindJSAction(const CFX_ByteString& csName) const
358 {
359     ASSERT(m_pDocument != NULL);
360     CPDF_NameTree name_tree(m_pDocument, FX_BSTRC("JavaScript"));
361     return name_tree.GetIndex(csName);
362 }