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_ ChangeSlashToPlatform(const FX_WCHAR * str)20CFX_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 ChangeSlashToPDF(const FX_WCHAR * str)37CFX_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 DecodeFileName(const CFX_WideStringC & filepath)53CFX_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 GetFileName(CFX_WideString * csFileName) const83bool 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 CPDF_FileSpec(const CFX_WeakPtr<CFX_ByteStringPool> & pPool)115CPDF_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 EncodeFileName(const CFX_WideStringC & filepath)120CFX_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 SetFileName(const CFX_WideStringC & wsFileName)158void 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