Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
cpdf_filespec.cpp
Go to the documentation of this file.
1// Copyright 2016 The PDFium Authors
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 <iterator>
10#include <utility>
11
12#include "build/build_config.h"
13#include "constants/stream_dict_common.h"
14#include "core/fpdfapi/parser/cpdf_dictionary.h"
15#include "core/fpdfapi/parser/cpdf_name.h"
16#include "core/fpdfapi/parser/cpdf_object.h"
17#include "core/fpdfapi/parser/cpdf_stream.h"
18#include "core/fpdfapi/parser/cpdf_string.h"
19#include "core/fpdfapi/parser/fpdf_parser_decode.h"
20#include "core/fxcrt/fx_system.h"
21#include "third_party/base/check.h"
22#include "third_party/base/notreached.h"
23
24namespace {
25
26#if BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_WIN)
27WideString ChangeSlashToPlatform(const wchar_t* str) {
28 WideString result;
29 while (*str) {
30 if (*str == '/') {
31#if BUILDFLAG(IS_APPLE)
32 result += L':';
33#else
34 result += L'\\';
35#endif
36 } else {
37 result += *str;
38 }
39 str++;
40 }
41 return result;
42}
43
44WideString ChangeSlashToPDF(const wchar_t* str) {
45 WideString result;
46 while (*str) {
47 if (*str == '\\' || *str == ':')
48 result += L'/';
49 else
50 result += *str;
51
52 str++;
53 }
54 return result;
55}
56#endif // BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_WIN)
57
58} // namespace
59
61 : m_pObj(std::move(pObj)) {
62 DCHECK(m_pObj);
63}
64
65CPDF_FileSpec::~CPDF_FileSpec() = default;
66
67WideString CPDF_FileSpec::DecodeFileName(const WideString& filepath) {
68 if (filepath.GetLength() <= 1)
69 return WideString();
70
71#if BUILDFLAG(IS_APPLE)
72 if (filepath.First(sizeof("/Mac") - 1) == WideStringView(L"/Mac"))
73 return ChangeSlashToPlatform(filepath.c_str() + 1);
74 return ChangeSlashToPlatform(filepath.c_str());
75#elif BUILDFLAG(IS_WIN)
76
77 if (filepath[0] != L'/')
78 return ChangeSlashToPlatform(filepath.c_str());
79 if (filepath[1] == L'/')
80 return ChangeSlashToPlatform(filepath.c_str() + 1);
81 if (filepath[2] == L'/') {
82 WideString result;
83 result += filepath[1];
84 result += L':';
85 result += ChangeSlashToPlatform(filepath.c_str() + 2);
86 return result;
87 }
88 WideString result;
89 result += L'\\';
90 result += ChangeSlashToPlatform(filepath.c_str());
91 return result;
92#else
93 return WideString(filepath);
94#endif
95}
96
97WideString CPDF_FileSpec::GetFileName() const {
98 WideString csFileName;
99 if (const CPDF_Dictionary* pDict = m_pObj->AsDictionary()) {
100 RetainPtr<const CPDF_String> pUF =
101 ToString(pDict->GetDirectObjectFor("UF"));
102 if (pUF)
103 csFileName = pUF->GetUnicodeText();
104 if (csFileName.IsEmpty()) {
105 RetainPtr<const CPDF_String> pK =
106 ToString(pDict->GetDirectObjectFor(pdfium::stream::kF));
107 if (pK)
108 csFileName = WideString::FromDefANSI(pK->GetString().AsStringView());
109 }
110 if (pDict->GetByteStringFor("FS") == "URL")
111 return csFileName;
112
113 if (csFileName.IsEmpty()) {
114 for (const auto* key : {"DOS", "Mac", "Unix"}) {
115 RetainPtr<const CPDF_String> pValue =
116 ToString(pDict->GetDirectObjectFor(key));
117 if (pValue) {
118 csFileName =
119 WideString::FromDefANSI(pValue->GetString().AsStringView());
120 break;
121 }
122 }
123 }
124 } else if (const CPDF_String* pString = m_pObj->AsString()) {
125 csFileName = WideString::FromDefANSI(pString->GetString().AsStringView());
126 }
127 return DecodeFileName(csFileName);
128}
129
130RetainPtr<const CPDF_Stream> CPDF_FileSpec::GetFileStream() const {
131 const CPDF_Dictionary* pDict = m_pObj->AsDictionary();
132 if (!pDict)
133 return nullptr;
134
135 // Get the embedded files dictionary.
136 RetainPtr<const CPDF_Dictionary> pFiles = pDict->GetDictFor("EF");
137 if (!pFiles)
138 return nullptr;
139
140 // List of keys to check for the file specification string.
141 // Follows the same precedence order as GetFileName().
142 static constexpr const char* kKeys[] = {"UF", "F", "DOS", "Mac", "Unix"};
143 size_t end = pDict->GetByteStringFor("FS") == "URL" ? 2 : std::size(kKeys);
144 for (size_t i = 0; i < end; ++i) {
145 ByteString key = kKeys[i];
146 if (!pDict->GetUnicodeTextFor(key).IsEmpty()) {
147 RetainPtr<const CPDF_Stream> pStream = pFiles->GetStreamFor(key);
148 if (pStream)
149 return pStream;
150 }
151 }
152 return nullptr;
153}
154
155RetainPtr<const CPDF_Dictionary> CPDF_FileSpec::GetParamsDict() const {
156 RetainPtr<const CPDF_Stream> pStream = GetFileStream();
157 if (!pStream)
158 return nullptr;
159
160 RetainPtr<const CPDF_Dictionary> pDict = pStream->GetDict();
161 return pDict ? pDict->GetDictFor("Params") : nullptr;
162}
163
165 return pdfium::WrapRetain(
166 const_cast<CPDF_Dictionary*>(GetParamsDict().Get()));
167}
168
169WideString CPDF_FileSpec::EncodeFileName(const WideString& filepath) {
170 if (filepath.GetLength() <= 1)
171 return WideString();
172
173#if BUILDFLAG(IS_WIN)
174 if (filepath[1] == L':') {
175 WideString result(L'/');
176 result += filepath[0];
177 if (filepath[2] != L'\\')
178 result += L'/';
179
180 result += ChangeSlashToPDF(filepath.c_str() + 2);
181 return result;
182 }
183 if (filepath[0] == L'\\' && filepath[1] == L'\\')
184 return ChangeSlashToPDF(filepath.c_str() + 1);
185
186 if (filepath[0] == L'\\')
187 return L'/' + ChangeSlashToPDF(filepath.c_str());
188 return ChangeSlashToPDF(filepath.c_str());
189#elif BUILDFLAG(IS_APPLE)
190 if (filepath.First(sizeof("Mac") - 1).EqualsASCII("Mac"))
191 return L'/' + ChangeSlashToPDF(filepath.c_str());
192 return ChangeSlashToPDF(filepath.c_str());
193#else
194 return WideString(filepath);
195#endif
196}
WideString GetUnicodeTextFor(const ByteString &key) const
ByteString GetByteStringFor(const ByteString &key) const
RetainPtr< CPDF_Dictionary > GetMutableParamsDict()
RetainPtr< const CPDF_Dictionary > GetParamsDict() const
WideString GetFileName() const
static WideString DecodeFileName(const WideString &filepath)
CPDF_FileSpec(RetainPtr< const CPDF_Object > pObj)
RetainPtr< const CPDF_Stream > GetFileStream() const
static WideString EncodeFileName(const WideString &filepath)
ByteString GetString() const override
bool operator==(const char *ptr) const
bool IsEmpty() const
Definition widestring.h:118
static WideString FromDefANSI(ByteStringView str)
WideString(const WideString &other)