14d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann// Copyright 2016 PDFium Authors. All rights reserved. 24d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann// Use of this source code is governed by a BSD-style license that can be 34d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann// found in the LICENSE file. 44d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann 54d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com 64d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann 74d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#include "core/fpdfdoc/cpdf_filespec.h" 84d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann 9d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann#include <vector> 10d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann 114d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#include "core/fpdfapi/parser/cpdf_dictionary.h" 124d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#include "core/fpdfapi/parser/cpdf_name.h" 134d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#include "core/fpdfapi/parser/cpdf_object.h" 14d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann#include "core/fpdfapi/parser/cpdf_stream.h" 154d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#include "core/fpdfapi/parser/cpdf_string.h" 164d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#include "core/fpdfapi/parser/fpdf_parser_decode.h" 174d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#include "core/fxcrt/fx_system.h" 184d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann 194d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmannnamespace { 204d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann 21d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ || \ 22d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ 23d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. MoltmannWideString ChangeSlashToPlatform(const wchar_t* str) { 24d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann WideString result; 254d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann while (*str) { 264d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann if (*str == '/') { 27d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ 28d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann result += L':'; 294d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#else 30d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann result += L'\\'; 314d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif 324d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann } else { 334d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann result += *str; 344d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann } 354d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann str++; 364d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann } 374d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann return result; 384d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann} 394d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann 40d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. MoltmannWideString ChangeSlashToPDF(const wchar_t* str) { 41d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann WideString result; 424d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann while (*str) { 434d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann if (*str == '\\' || *str == ':') 44d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann result += L'/'; 454d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann else 464d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann result += *str; 474d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann 484d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann str++; 494d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann } 504d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann return result; 514d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann} 52d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann#endif // _FX_PLATFORM_APPLE_ || _FX_PLATFORM_WINDOWS_ 534d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann 544d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann} // namespace 554d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann 56d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. MoltmannCPDF_FileSpec::CPDF_FileSpec(CPDF_Object* pObj) : m_pObj(pObj) { 57d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann ASSERT(m_pObj); 58d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann} 59d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann 60d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. MoltmannCPDF_FileSpec::~CPDF_FileSpec() {} 61d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann 62d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. MoltmannWideString CPDF_FileSpec::DecodeFileName(const WideString& filepath) { 634d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann if (filepath.GetLength() <= 1) 64d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann return WideString(); 654d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann 66d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann#if _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ 67d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann if (filepath.Left(sizeof("/Mac") - 1) == WideStringView(L"/Mac")) 684d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann return ChangeSlashToPlatform(filepath.c_str() + 1); 694d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann return ChangeSlashToPlatform(filepath.c_str()); 70d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann#elif _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ 714d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann 72d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann if (filepath[0] != L'/') 734d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann return ChangeSlashToPlatform(filepath.c_str()); 74d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann if (filepath[1] == L'/') 754d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann return ChangeSlashToPlatform(filepath.c_str() + 1); 76d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann if (filepath[2] == L'/') { 77d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann WideString result; 78d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann result += filepath[1]; 79d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann result += L':'; 804d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann result += ChangeSlashToPlatform(filepath.c_str() + 2); 814d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann return result; 824d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann } 83d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann WideString result; 84d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann result += L'\\'; 854d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann result += ChangeSlashToPlatform(filepath.c_str()); 864d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann return result; 874d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#else 88d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann return WideString(filepath); 894d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif 904d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann} 914d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann 92d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. MoltmannWideString CPDF_FileSpec::GetFileName() const { 93d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann WideString csFileName; 944d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann if (CPDF_Dictionary* pDict = m_pObj->AsDictionary()) { 95d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann csFileName = pDict->GetUnicodeTextFor("UF"); 96d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann if (csFileName.IsEmpty()) { 97d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann csFileName = 98d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann WideString::FromLocal(pDict->GetStringFor("F").AsStringView()); 994d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann } 1004d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann if (pDict->GetStringFor("FS") == "URL") 101d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann return csFileName; 102d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann 103d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann if (csFileName.IsEmpty()) { 104d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann constexpr const char* keys[] = {"DOS", "Mac", "Unix"}; 105d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann for (const auto* key : keys) { 106d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann if (pDict->KeyExist(key)) { 107d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann csFileName = 108d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann WideString::FromLocal(pDict->GetStringFor(key).AsStringView()); 109d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann break; 110d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann } 1114d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann } 1124d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann } 1134d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann } else if (m_pObj->IsString()) { 114d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann csFileName = WideString::FromLocal(m_pObj->GetString().AsStringView()); 1154d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann } 116d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann return DecodeFileName(csFileName); 1174d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann} 1184d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann 119d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. MoltmannCPDF_Stream* CPDF_FileSpec::GetFileStream() const { 120d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann CPDF_Dictionary* pDict = m_pObj->AsDictionary(); 121d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann if (!pDict) 122d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann return nullptr; 123d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann 124d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann // Get the embedded files dictionary. 125d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann CPDF_Dictionary* pFiles = pDict->GetDictFor("EF"); 126d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann if (!pFiles) 127d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann return nullptr; 128d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann 129d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann // Get the file stream of the highest precedence with its file specification 130d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann // string available. Follows the same precedence order as GetFileName(). 131d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann constexpr const char* keys[] = {"UF", "F", "DOS", "Mac", "Unix"}; 132d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann size_t end = pDict->GetStringFor("FS") == "URL" ? 2 : FX_ArraySize(keys); 133d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann for (size_t i = 0; i < end; ++i) { 134d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann const ByteString& key = keys[i]; 135d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann if (!pDict->GetUnicodeTextFor(key).IsEmpty()) { 136d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann CPDF_Stream* pStream = pFiles->GetStreamFor(key); 137d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann if (pStream) 138d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann return pStream; 139d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann } 140d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann } 141d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann return nullptr; 1424d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann} 1434d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann 144d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. MoltmannCPDF_Dictionary* CPDF_FileSpec::GetParamsDict() const { 145d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann CPDF_Stream* pStream = GetFileStream(); 146d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann if (!pStream) 147d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann return nullptr; 148d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann 149d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann CPDF_Dictionary* pDict = pStream->GetDict(); 150d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann if (!pDict) 151d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann return nullptr; 152d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann 153d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann return pDict->GetDictFor("Params"); 154d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann} 155d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann 156d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. MoltmannWideString CPDF_FileSpec::EncodeFileName(const WideString& filepath) { 1574d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann if (filepath.GetLength() <= 1) 158d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann return WideString(); 1594d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann 160d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann#if _FX_PLATFORM_ == _FX_PLATFORM_WINDOWS_ 161d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann if (filepath[1] == L':') { 162d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann WideString result(L'/'); 163d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann result += filepath[0]; 164d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann if (filepath[2] != L'\\') 165d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann result += L'/'; 1664d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann 1674d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann result += ChangeSlashToPDF(filepath.c_str() + 2); 1684d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann return result; 1694d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann } 170d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann if (filepath[0] == L'\\' && filepath[1] == L'\\') 1714d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann return ChangeSlashToPDF(filepath.c_str() + 1); 1724d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann 173d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann if (filepath[0] == L'\\') 174d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann return L'/' + ChangeSlashToPDF(filepath.c_str()); 1754d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann return ChangeSlashToPDF(filepath.c_str()); 176d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann#elif _FX_PLATFORM_ == _FX_PLATFORM_APPLE_ 177d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann if (filepath.Left(sizeof("Mac") - 1) == L"Mac") 178d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann return L'/' + ChangeSlashToPDF(filepath.c_str()); 1794d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann return ChangeSlashToPDF(filepath.c_str()); 1804d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#else 181d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann return WideString(filepath); 1824d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann#endif 1834d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann} 1844d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann 185d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmannvoid CPDF_FileSpec::SetFileName(const WideString& wsFileName) { 186d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann WideString wsStr = EncodeFileName(wsFileName); 1874d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann if (m_pObj->IsString()) { 188d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann m_pObj->SetString(ByteString::FromUnicode(wsStr)); 1894d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann } else if (CPDF_Dictionary* pDict = m_pObj->AsDictionary()) { 190d904c1ec7e8d1d86ed56f0dd252435d12cd345aePhilip P. Moltmann pDict->SetNewFor<CPDF_String>("F", ByteString::FromUnicode(wsStr), false); 1914d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann pDict->SetNewFor<CPDF_String>("UF", PDF_EncodeText(wsStr), false); 1924d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann } 1934d3acf4ec42bf6e838f9060103aff98fbf170794Philip P. Moltmann} 194