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
14namespace {
15
16const FX_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
24CPDF_Dest CPDF_Action::GetDest(CPDF_Document* pDoc) const {
25  if (!m_pDict)
26    return CPDF_Dest();
27
28  CFX_ByteString type = m_pDict->GetStringFor("S");
29  if (type != "GoTo" && type != "GoToR")
30    return CPDF_Dest();
31
32  CPDF_Object* pDest = m_pDict->GetDirectObjectFor("D");
33  if (!pDest)
34    return CPDF_Dest();
35  if (pDest->IsString() || pDest->IsName()) {
36    CPDF_NameTree name_tree(pDoc, "Dests");
37    return CPDF_Dest(name_tree.LookupNamedDest(pDoc, pDest->GetString()));
38  }
39  if (CPDF_Array* pArray = pDest->AsArray())
40    return CPDF_Dest(pArray);
41
42  return CPDF_Dest();
43}
44
45CPDF_Action::ActionType CPDF_Action::GetType() const {
46  if (!m_pDict)
47    return Unknown;
48
49  CFX_ByteString csType = m_pDict->GetStringFor("S");
50  if (csType.IsEmpty())
51    return Unknown;
52
53  for (int i = 0; g_sATypes[i]; ++i) {
54    if (csType == g_sATypes[i])
55      return static_cast<ActionType>(i);
56  }
57  return Unknown;
58}
59
60CFX_WideString CPDF_Action::GetFilePath() const {
61  CFX_ByteString type = m_pDict->GetStringFor("S");
62  if (type != "GoToR" && type != "Launch" && type != "SubmitForm" &&
63      type != "ImportData") {
64    return CFX_WideString();
65  }
66
67  CPDF_Object* pFile = m_pDict->GetDirectObjectFor("F");
68  CFX_WideString path;
69  if (!pFile) {
70    if (type == "Launch") {
71      CPDF_Dictionary* pWinDict = m_pDict->GetDictFor("Win");
72      if (pWinDict) {
73        return CFX_WideString::FromLocal(
74            pWinDict->GetStringFor("F").AsStringC());
75      }
76    }
77    return path;
78  }
79
80  CPDF_FileSpec filespec(pFile);
81  filespec.GetFileName(&path);
82  return path;
83}
84
85CFX_ByteString CPDF_Action::GetURI(CPDF_Document* pDoc) const {
86  CFX_ByteString csURI;
87  if (!m_pDict)
88    return csURI;
89  if (m_pDict->GetStringFor("S") != "URI")
90    return csURI;
91
92  csURI = m_pDict->GetStringFor("URI");
93  CPDF_Dictionary* pRoot = pDoc->GetRoot();
94  CPDF_Dictionary* pURI = pRoot->GetDictFor("URI");
95  if (pURI) {
96    if (csURI.Find(":", 0) < 1)
97      csURI = pURI->GetStringFor("Base") + csURI;
98  }
99  return csURI;
100}
101
102CFX_WideString CPDF_Action::GetJavaScript() const {
103  CFX_WideString csJS;
104  if (!m_pDict)
105    return csJS;
106
107  CPDF_Object* pJS = m_pDict->GetDirectObjectFor("JS");
108  return pJS ? pJS->GetUnicodeText() : csJS;
109}
110
111size_t CPDF_Action::GetSubActionsCount() const {
112  if (!m_pDict || !m_pDict->KeyExist("Next"))
113    return 0;
114
115  CPDF_Object* pNext = m_pDict->GetDirectObjectFor("Next");
116  if (!pNext)
117    return 0;
118  if (pNext->IsDictionary())
119    return 1;
120  if (CPDF_Array* pArray = pNext->AsArray())
121    return pArray->GetCount();
122  return 0;
123}
124
125CPDF_Action CPDF_Action::GetSubAction(size_t iIndex) const {
126  if (!m_pDict || !m_pDict->KeyExist("Next"))
127    return CPDF_Action();
128
129  CPDF_Object* pNext = m_pDict->GetDirectObjectFor("Next");
130  if (CPDF_Dictionary* pDict = ToDictionary(pNext)) {
131    if (iIndex == 0)
132      return CPDF_Action(pDict);
133  } else if (CPDF_Array* pArray = ToArray(pNext)) {
134    return CPDF_Action(pArray->GetDictAt(iIndex));
135  }
136  return CPDF_Action();
137}
138