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_filespec.h"
      8 
      9 #include "core/fpdfapi/parser/cpdf_dictionary.h"
     10 #include "core/fpdfapi/parser/cpdf_name.h"
     11 #include "core/fpdfapi/parser/cpdf_object.h"
     12 #include "core/fpdfapi/parser/cpdf_string.h"
     13 #include "core/fpdfapi/parser/fpdf_parser_decode.h"
     14 #include "core/fxcrt/fx_system.h"
     15 
     16 namespace {
     17 
     18 #if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ || \
     19     _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
     20 CFX_WideString ChangeSlashToPlatform(const FX_WCHAR* str) {
     21   CFX_WideString result;
     22   while (*str) {
     23     if (*str == '/') {
     24 #if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
     25       result += ':';
     26 #else
     27       result += '\\';
     28 #endif
     29     } else {
     30       result += *str;
     31     }
     32     str++;
     33   }
     34   return result;
     35 }
     36 
     37 CFX_WideString ChangeSlashToPDF(const FX_WCHAR* str) {
     38   CFX_WideString result;
     39   while (*str) {
     40     if (*str == '\\' || *str == ':')
     41       result += '/';
     42     else
     43       result += *str;
     44 
     45     str++;
     46   }
     47   return result;
     48 }
     49 #endif  // _FXM_PLATFORM_APPLE_ || _FXM_PLATFORM_WINDOWS_
     50 
     51 }  // namespace
     52 
     53 CFX_WideString CPDF_FileSpec::DecodeFileName(const CFX_WideStringC& filepath) {
     54   if (filepath.GetLength() <= 1)
     55     return CFX_WideString();
     56 
     57 #if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
     58   if (filepath.Left(sizeof("/Mac") - 1) == CFX_WideStringC(L"/Mac"))
     59     return ChangeSlashToPlatform(filepath.c_str() + 1);
     60   return ChangeSlashToPlatform(filepath.c_str());
     61 #elif _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
     62 
     63   if (filepath.GetAt(0) != '/')
     64     return ChangeSlashToPlatform(filepath.c_str());
     65   if (filepath.GetAt(1) == '/')
     66     return ChangeSlashToPlatform(filepath.c_str() + 1);
     67   if (filepath.GetAt(2) == '/') {
     68     CFX_WideString result;
     69     result += filepath.GetAt(1);
     70     result += ':';
     71     result += ChangeSlashToPlatform(filepath.c_str() + 2);
     72     return result;
     73   }
     74   CFX_WideString result;
     75   result += '\\';
     76   result += ChangeSlashToPlatform(filepath.c_str());
     77   return result;
     78 #else
     79   return CFX_WideString(filepath);
     80 #endif
     81 }
     82 
     83 bool CPDF_FileSpec::GetFileName(CFX_WideString* csFileName) const {
     84   if (CPDF_Dictionary* pDict = m_pObj->AsDictionary()) {
     85     *csFileName = pDict->GetUnicodeTextFor("UF");
     86     if (csFileName->IsEmpty()) {
     87       *csFileName =
     88           CFX_WideString::FromLocal(pDict->GetStringFor("F").AsStringC());
     89     }
     90     if (pDict->GetStringFor("FS") == "URL")
     91       return true;
     92     if (csFileName->IsEmpty()) {
     93       if (pDict->KeyExist("DOS")) {
     94         *csFileName =
     95             CFX_WideString::FromLocal(pDict->GetStringFor("DOS").AsStringC());
     96       } else if (pDict->KeyExist("Mac")) {
     97         *csFileName =
     98             CFX_WideString::FromLocal(pDict->GetStringFor("Mac").AsStringC());
     99       } else if (pDict->KeyExist("Unix")) {
    100         *csFileName =
    101             CFX_WideString::FromLocal(pDict->GetStringFor("Unix").AsStringC());
    102       } else {
    103         return false;
    104       }
    105     }
    106   } else if (m_pObj->IsString()) {
    107     *csFileName = CFX_WideString::FromLocal(m_pObj->GetString().AsStringC());
    108   } else {
    109     return false;
    110   }
    111   *csFileName = DecodeFileName(csFileName->AsStringC());
    112   return true;
    113 }
    114 
    115 CPDF_FileSpec::CPDF_FileSpec(const CFX_WeakPtr<CFX_ByteStringPool>& pPool) {
    116   m_pObj = new CPDF_Dictionary(pPool);
    117   m_pObj->AsDictionary()->SetNewFor<CPDF_Name>("Type", "Filespec");
    118 }
    119 
    120 CFX_WideString CPDF_FileSpec::EncodeFileName(const CFX_WideStringC& filepath) {
    121   if (filepath.GetLength() <= 1)
    122     return CFX_WideString();
    123 
    124 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
    125   if (filepath.GetAt(1) == ':') {
    126     CFX_WideString result;
    127     result = '/';
    128     result += filepath.GetAt(0);
    129     if (filepath.GetAt(2) != '\\')
    130       result += '/';
    131 
    132     result += ChangeSlashToPDF(filepath.c_str() + 2);
    133     return result;
    134   }
    135   if (filepath.GetAt(0) == '\\' && filepath.GetAt(1) == '\\')
    136     return ChangeSlashToPDF(filepath.c_str() + 1);
    137 
    138   if (filepath.GetAt(0) == '\\') {
    139     CFX_WideString result;
    140     result = '/';
    141     result += ChangeSlashToPDF(filepath.c_str());
    142     return result;
    143   }
    144   return ChangeSlashToPDF(filepath.c_str());
    145 #elif _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
    146   if (filepath.Left(sizeof("Mac") - 1) == L"Mac") {
    147     CFX_WideString result;
    148     result = '/';
    149     result += ChangeSlashToPDF(filepath.c_str());
    150     return result;
    151   }
    152   return ChangeSlashToPDF(filepath.c_str());
    153 #else
    154   return CFX_WideString(filepath);
    155 #endif
    156 }
    157 
    158 void CPDF_FileSpec::SetFileName(const CFX_WideStringC& wsFileName) {
    159   if (!m_pObj)
    160     return;
    161 
    162   CFX_WideString wsStr = EncodeFileName(wsFileName);
    163   if (m_pObj->IsString()) {
    164     m_pObj->SetString(CFX_ByteString::FromUnicode(wsStr));
    165   } else if (CPDF_Dictionary* pDict = m_pObj->AsDictionary()) {
    166     pDict->SetNewFor<CPDF_String>("F", CFX_ByteString::FromUnicode(wsStr),
    167                                   false);
    168     pDict->SetNewFor<CPDF_String>("UF", PDF_EncodeText(wsStr), false);
    169   }
    170 }
    171