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 #include <memory>
6 #include <vector>
7
8 #include "core/fpdfapi/parser/cpdf_dictionary.h"
9 #include "core/fpdfapi/parser/cpdf_name.h"
10 #include "core/fpdfapi/parser/cpdf_string.h"
11 #include "core/fpdfdoc/cpdf_filespec.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13 #include "testing/test_support.h"
14
TEST(cpdf_filespec,EncodeDecodeFileName)15 TEST(cpdf_filespec, EncodeDecodeFileName) {
16 std::vector<pdfium::NullTermWstrFuncTestData> test_data = {
17 // Empty src string.
18 {L"", L""},
19 // only file name.
20 {L"test.pdf", L"test.pdf"},
21 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
22 // With drive identifier.
23 {L"r:\\pdfdocs\\spec.pdf", L"/r/pdfdocs/spec.pdf"},
24 // Relative path.
25 {L"My Document\\test.pdf", L"My Document/test.pdf"},
26 // Absolute path without drive identifier.
27 {L"\\pdfdocs\\spec.pdf", L"//pdfdocs/spec.pdf"},
28 // Absolute path with double backslashes.
29 {L"\\\\pdfdocs\\spec.pdf", L"/pdfdocs/spec.pdf"},
30 // Network resource name. It is not supported yet.
31 // {L"pclib/eng:\\pdfdocs\\spec.pdf", L"/pclib/eng/pdfdocs/spec.pdf"},
32 #elif _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
33 // Absolute path with colon separator.
34 {L"Mac HD:PDFDocs:spec.pdf", L"/Mac HD/PDFDocs/spec.pdf"},
35 // Relative path with colon separator.
36 {L"PDFDocs:spec.pdf", L"PDFDocs/spec.pdf"},
37 #else
38 // Relative path.
39 {L"./docs/test.pdf", L"./docs/test.pdf"},
40 // Relative path with parent dir.
41 {L"../test_docs/test.pdf", L"../test_docs/test.pdf"},
42 // Absolute path.
43 {L"/usr/local/home/test.pdf", L"/usr/local/home/test.pdf"},
44 #endif
45 };
46 for (const auto& data : test_data) {
47 CFX_WideString encoded_str = CPDF_FileSpec::EncodeFileName(data.input);
48 EXPECT_TRUE(encoded_str == data.expected);
49 // DecodeFileName is the reverse procedure of EncodeFileName.
50 CFX_WideString decoded_str = CPDF_FileSpec::DecodeFileName(data.expected);
51 EXPECT_TRUE(decoded_str == data.input);
52 }
53 }
54
TEST(cpdf_filespec,GetFileName)55 TEST(cpdf_filespec, GetFileName) {
56 {
57 // String object.
58 pdfium::NullTermWstrFuncTestData test_data = {
59 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
60 L"/C/docs/test.pdf",
61 L"C:\\docs\\test.pdf"
62 #elif _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
63 L"/Mac HD/docs/test.pdf",
64 L"Mac HD:docs:test.pdf"
65 #else
66 L"/docs/test.pdf",
67 L"/docs/test.pdf"
68 #endif
69 };
70 std::unique_ptr<CPDF_Object> str_obj(
71 new CPDF_String(nullptr, test_data.input));
72 CPDF_FileSpec file_spec(str_obj.get());
73 CFX_WideString file_name;
74 EXPECT_TRUE(file_spec.GetFileName(&file_name));
75 EXPECT_TRUE(file_name == test_data.expected);
76 }
77 {
78 // Dictionary object.
79 pdfium::NullTermWstrFuncTestData test_data[5] = {
80 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
81 {L"/C/docs/test.pdf", L"C:\\docs\\test.pdf"},
82 {L"/D/docs/test.pdf", L"D:\\docs\\test.pdf"},
83 {L"/E/docs/test.pdf", L"E:\\docs\\test.pdf"},
84 {L"/F/docs/test.pdf", L"F:\\docs\\test.pdf"},
85 {L"/G/docs/test.pdf", L"G:\\docs\\test.pdf"},
86 #elif _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
87 {L"/Mac HD/docs1/test.pdf", L"Mac HD:docs1:test.pdf"},
88 {L"/Mac HD/docs2/test.pdf", L"Mac HD:docs2:test.pdf"},
89 {L"/Mac HD/docs3/test.pdf", L"Mac HD:docs3:test.pdf"},
90 {L"/Mac HD/docs4/test.pdf", L"Mac HD:docs4:test.pdf"},
91 {L"/Mac HD/docs5/test.pdf", L"Mac HD:docs5:test.pdf"},
92 #else
93 {L"/docs/a/test.pdf", L"/docs/a/test.pdf"},
94 {L"/docs/b/test.pdf", L"/docs/b/test.pdf"},
95 {L"/docs/c/test.pdf", L"/docs/c/test.pdf"},
96 {L"/docs/d/test.pdf", L"/docs/d/test.pdf"},
97 {L"/docs/e/test.pdf", L"/docs/e/test.pdf"},
98 #endif
99 };
100 // Keyword fields in reverse order of precedence to retrieve the file name.
101 const char* const keywords[5] = {"Unix", "Mac", "DOS", "F", "UF"};
102 std::unique_ptr<CPDF_Dictionary> dict_obj(new CPDF_Dictionary());
103 CPDF_FileSpec file_spec(dict_obj.get());
104 CFX_WideString file_name;
105 for (int i = 0; i < 5; ++i) {
106 dict_obj->SetNewFor<CPDF_String>(keywords[i], test_data[i].input);
107 EXPECT_TRUE(file_spec.GetFileName(&file_name));
108 EXPECT_TRUE(file_name == test_data[i].expected);
109 }
110
111 // With all the former fields and 'FS' field suggests 'URL' type.
112 dict_obj->SetNewFor<CPDF_String>("FS", "URL", false);
113 EXPECT_TRUE(file_spec.GetFileName(&file_name));
114 // Url string is not decoded.
115 EXPECT_TRUE(file_name == test_data[4].input);
116 }
117 {
118 // Invalid object.
119 std::unique_ptr<CPDF_Object> name_obj(new CPDF_Name(nullptr, "test.pdf"));
120 CPDF_FileSpec file_spec(name_obj.get());
121 CFX_WideString file_name;
122 EXPECT_FALSE(file_spec.GetFileName(&file_name));
123 }
124 }
125
TEST(cpdf_filespec,SetFileName)126 TEST(cpdf_filespec, SetFileName) {
127 pdfium::NullTermWstrFuncTestData test_data = {
128 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
129 L"C:\\docs\\test.pdf",
130 L"/C/docs/test.pdf"
131 #elif _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
132 L"Mac HD:docs:test.pdf",
133 L"/Mac HD/docs/test.pdf"
134 #else
135 L"/docs/test.pdf",
136 L"/docs/test.pdf"
137 #endif
138 };
139 // String object.
140 std::unique_ptr<CPDF_Object> str_obj(new CPDF_String(nullptr, L"babababa"));
141 CPDF_FileSpec file_spec1(str_obj.get());
142 file_spec1.SetFileName(test_data.input);
143 // Check internal object value.
144 CFX_ByteString str = CFX_ByteString::FromUnicode(test_data.expected);
145 EXPECT_TRUE(str == str_obj->GetString());
146 // Check we can get the file name back.
147 CFX_WideString file_name;
148 EXPECT_TRUE(file_spec1.GetFileName(&file_name));
149 EXPECT_TRUE(file_name == test_data.input);
150
151 // Dictionary object.
152 std::unique_ptr<CPDF_Dictionary> dict_obj(new CPDF_Dictionary());
153 CPDF_FileSpec file_spec2(dict_obj.get());
154 file_spec2.SetFileName(test_data.input);
155 // Check internal object value.
156 file_name = dict_obj->GetUnicodeTextFor("F");
157 EXPECT_TRUE(file_name == test_data.expected);
158 file_name = dict_obj->GetUnicodeTextFor("UF");
159 EXPECT_TRUE(file_name == test_data.expected);
160 // Check we can get the file name back.
161 EXPECT_TRUE(file_spec2.GetFileName(&file_name));
162 EXPECT_TRUE(file_name == test_data.input);
163 }
164