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 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 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 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