• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 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/fpdfdoc/cpdf_action.h"
8 
9 #include "core/fpdfapi/parser/cpdf_array.h"
10 #include "core/fpdfapi/parser/cpdf_document.h"
11 #include "core/fpdfdoc/cpdf_filespec.h"
12 #include "core/fpdfdoc/cpdf_nametree.h"
13 
14 namespace {
15 
16 const char* const g_sATypes[] = {
17     "Unknown",     "GoTo",       "GoToR",     "GoToE",      "Launch",
18     "Thread",      "URI",        "Sound",     "Movie",      "Hide",
19     "Named",       "SubmitForm", "ResetForm", "ImportData", "JavaScript",
20     "SetOCGState", "Rendition",  "Trans",     "GoTo3DView", nullptr};
21 
22 }  // namespace
23 
CPDF_Action(CPDF_Dictionary * pDict)24 CPDF_Action::CPDF_Action(CPDF_Dictionary* pDict) : m_pDict(pDict) {}
25 
26 CPDF_Action::CPDF_Action(const CPDF_Action& that) = default;
27 
~CPDF_Action()28 CPDF_Action::~CPDF_Action() {}
29 
GetDest(CPDF_Document * pDoc) const30 CPDF_Dest CPDF_Action::GetDest(CPDF_Document* pDoc) const {
31   if (!m_pDict)
32     return CPDF_Dest();
33 
34   ByteString type = m_pDict->GetStringFor("S");
35   if (type != "GoTo" && type != "GoToR")
36     return CPDF_Dest();
37 
38   CPDF_Object* pDest = m_pDict->GetDirectObjectFor("D");
39   if (!pDest)
40     return CPDF_Dest();
41   if (pDest->IsString() || pDest->IsName()) {
42     CPDF_NameTree name_tree(pDoc, "Dests");
43     return CPDF_Dest(name_tree.LookupNamedDest(pDoc, pDest->GetUnicodeText()));
44   }
45   if (CPDF_Array* pArray = pDest->AsArray())
46     return CPDF_Dest(pArray);
47 
48   return CPDF_Dest();
49 }
50 
GetType() const51 CPDF_Action::ActionType CPDF_Action::GetType() const {
52   if (!m_pDict)
53     return Unknown;
54 
55   ByteString csType = m_pDict->GetStringFor("S");
56   if (csType.IsEmpty())
57     return Unknown;
58 
59   for (int i = 0; g_sATypes[i]; ++i) {
60     if (csType == g_sATypes[i])
61       return static_cast<ActionType>(i);
62   }
63   return Unknown;
64 }
65 
GetFilePath() const66 WideString CPDF_Action::GetFilePath() const {
67   ByteString type = m_pDict->GetStringFor("S");
68   if (type != "GoToR" && type != "Launch" && type != "SubmitForm" &&
69       type != "ImportData") {
70     return WideString();
71   }
72 
73   CPDF_Object* pFile = m_pDict->GetDirectObjectFor("F");
74   if (pFile)
75     return CPDF_FileSpec(pFile).GetFileName();
76 
77   if (type == "Launch") {
78     CPDF_Dictionary* pWinDict = m_pDict->GetDictFor("Win");
79     if (pWinDict) {
80       return WideString::FromLocal(pWinDict->GetStringFor("F").AsStringView());
81     }
82   }
83   return WideString();
84 }
85 
GetURI(const CPDF_Document * pDoc) const86 ByteString CPDF_Action::GetURI(const CPDF_Document* pDoc) const {
87   ByteString csURI;
88   if (!m_pDict)
89     return csURI;
90   if (m_pDict->GetStringFor("S") != "URI")
91     return csURI;
92 
93   csURI = m_pDict->GetStringFor("URI");
94   const CPDF_Dictionary* pRoot = pDoc->GetRoot();
95   CPDF_Dictionary* pURI = pRoot->GetDictFor("URI");
96   if (pURI) {
97     auto result = csURI.Find(":");
98     if (!result.has_value() || result.value() == 0)
99       csURI = pURI->GetStringFor("Base") + csURI;
100   }
101   return csURI;
102 }
103 
GetJavaScript() const104 WideString CPDF_Action::GetJavaScript() const {
105   WideString csJS;
106   if (!m_pDict)
107     return csJS;
108 
109   CPDF_Object* pJS = m_pDict->GetDirectObjectFor("JS");
110   return pJS ? pJS->GetUnicodeText() : csJS;
111 }
112 
GetSubActionsCount() const113 size_t CPDF_Action::GetSubActionsCount() const {
114   if (!m_pDict || !m_pDict->KeyExist("Next"))
115     return 0;
116 
117   CPDF_Object* pNext = m_pDict->GetDirectObjectFor("Next");
118   if (!pNext)
119     return 0;
120   if (pNext->IsDictionary())
121     return 1;
122   if (CPDF_Array* pArray = pNext->AsArray())
123     return pArray->GetCount();
124   return 0;
125 }
126 
GetSubAction(size_t iIndex) const127 CPDF_Action CPDF_Action::GetSubAction(size_t iIndex) const {
128   if (!m_pDict || !m_pDict->KeyExist("Next"))
129     return CPDF_Action(nullptr);
130 
131   CPDF_Object* pNext = m_pDict->GetDirectObjectFor("Next");
132   if (CPDF_Array* pArray = ToArray(pNext))
133     return CPDF_Action(pArray->GetDictAt(iIndex));
134   if (CPDF_Dictionary* pDict = ToDictionary(pNext)) {
135     if (iIndex == 0)
136       return CPDF_Action(pDict);
137   }
138   return CPDF_Action(nullptr);
139 }
140