Home | History | Annotate | Download | only in fpdfdoc
      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