Home | History | Annotate | Download | only in fpdfdoc
      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 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 
     24 CPDF_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 
     45 CPDF_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 
     60 CFX_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 
     85 CFX_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 
    102 CFX_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 
    111 size_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 
    125 CPDF_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