Example #1
0
// Check circular bookmarks will not cause infinite loop.
TEST_F(FPDFDocEmbedderTest, FindBookmarks_bug420) {
  // Open a file with circular bookmarks.
  EXPECT_TRUE(OpenDocument("bookmarks_circular.pdf"));

  // Try to find a title.
  std::unique_ptr<unsigned short, pdfium::FreeDeleter> title =
      GetFPDFWideString(L"anything");
  EXPECT_EQ(nullptr, FPDFBookmark_Find(document(), title.get()));
}
Example #2
0
TEST_F(FPDFDocEmbedderTest, FindBookmarks) {
  // Open a file with two bookmarks.
  EXPECT_TRUE(OpenDocument("bookmarks.pdf"));

  // Find the first one, based on its known title.
  std::unique_ptr<unsigned short, pdfium::FreeDeleter> title =
      GetFPDFWideString(L"A Good Beginning");
  FPDF_BOOKMARK child = FPDFBookmark_Find(document(), title.get());
  EXPECT_TRUE(child);

  // Check that the string matches.
  unsigned short buf[128];
  EXPECT_EQ(34u, FPDFBookmark_GetTitle(child, buf, sizeof(buf)));
  EXPECT_EQ(WideString(L"A Good Beginning"), WideString::FromUTF16LE(buf, 16));

  // Check that it is them same as the one returned by GetFirstChild.
  EXPECT_EQ(child, FPDFBookmark_GetFirstChild(document(), nullptr));

  // Try to find one using a non-existent title.
  std::unique_ptr<unsigned short, pdfium::FreeDeleter> bad_title =
      GetFPDFWideString(L"A BAD Beginning");
  EXPECT_EQ(nullptr, FPDFBookmark_Find(document(), bad_title.get()));
}
TEST_F(PDFDocTest, FindBookmark) {
  {
    // No bookmark information.
    std::unique_ptr<unsigned short, pdfium::FreeDeleter> title =
        GetFPDFWideString(L"");
    EXPECT_EQ(nullptr, FPDFBookmark_Find(m_pDoc.get(), title.get()));

    title = GetFPDFWideString(L"Preface");
    EXPECT_EQ(nullptr, FPDFBookmark_Find(m_pDoc.get(), title.get()));
  }
  {
    // Empty bookmark tree.
    m_pRootObj->SetNewFor<CPDF_Dictionary>("Outlines");
    std::unique_ptr<unsigned short, pdfium::FreeDeleter> title =
        GetFPDFWideString(L"");
    EXPECT_EQ(nullptr, FPDFBookmark_Find(m_pDoc.get(), title.get()));

    title = GetFPDFWideString(L"Preface");
    EXPECT_EQ(nullptr, FPDFBookmark_Find(m_pDoc.get(), title.get()));
  }
  {
    // Check on a regular bookmark tree.
    auto bookmarks = CreateDictObjs(3);

    bookmarks[1].obj->SetNewFor<CPDF_String>("Title", L"Chapter 1");
    bookmarks[1].obj->SetNewFor<CPDF_Reference>("Parent", m_pIndirectObjs,
                                                bookmarks[0].num);
    bookmarks[1].obj->SetNewFor<CPDF_Reference>("Next", m_pIndirectObjs,
                                                bookmarks[2].num);

    bookmarks[2].obj->SetNewFor<CPDF_String>("Title", L"Chapter 2");
    bookmarks[2].obj->SetNewFor<CPDF_Reference>("Parent", m_pIndirectObjs,
                                                bookmarks[0].num);
    bookmarks[2].obj->SetNewFor<CPDF_Reference>("Prev", m_pIndirectObjs,
                                                bookmarks[1].num);

    bookmarks[0].obj->SetNewFor<CPDF_Name>("Type", "Outlines");
    bookmarks[0].obj->SetNewFor<CPDF_Number>("Count", 2);
    bookmarks[0].obj->SetNewFor<CPDF_Reference>("First", m_pIndirectObjs,
                                                bookmarks[1].num);
    bookmarks[0].obj->SetNewFor<CPDF_Reference>("Last", m_pIndirectObjs,
                                                bookmarks[2].num);

    m_pRootObj->SetNewFor<CPDF_Reference>("Outlines", m_pIndirectObjs,
                                          bookmarks[0].num);

    // Title with no match.
    std::unique_ptr<unsigned short, pdfium::FreeDeleter> title =
        GetFPDFWideString(L"Chapter 3");
    EXPECT_EQ(nullptr, FPDFBookmark_Find(m_pDoc.get(), title.get()));

    // Title with partial match only.
    title = GetFPDFWideString(L"Chapter");
    EXPECT_EQ(nullptr, FPDFBookmark_Find(m_pDoc.get(), title.get()));

    // Title with a match.
    title = GetFPDFWideString(L"Chapter 2");
    EXPECT_EQ(bookmarks[2].obj, FPDFBookmark_Find(m_pDoc.get(), title.get()));

    // Title match is case insensitive.
    title = GetFPDFWideString(L"cHaPter 2");
    EXPECT_EQ(bookmarks[2].obj, FPDFBookmark_Find(m_pDoc.get(), title.get()));
  }
  {
    // Circular bookmarks in depth.
    auto bookmarks = CreateDictObjs(3);

    bookmarks[1].obj->SetNewFor<CPDF_String>("Title", L"Chapter 1");
    bookmarks[1].obj->SetNewFor<CPDF_Reference>("Parent", m_pIndirectObjs,
                                                bookmarks[0].num);
    bookmarks[1].obj->SetNewFor<CPDF_Reference>("First", m_pIndirectObjs,
                                                bookmarks[2].num);

    bookmarks[2].obj->SetNewFor<CPDF_String>("Title", L"Chapter 2");
    bookmarks[2].obj->SetNewFor<CPDF_Reference>("Parent", m_pIndirectObjs,
                                                bookmarks[1].num);
    bookmarks[2].obj->SetNewFor<CPDF_Reference>("First", m_pIndirectObjs,
                                                bookmarks[1].num);

    bookmarks[0].obj->SetNewFor<CPDF_Name>("Type", "Outlines");
    bookmarks[0].obj->SetNewFor<CPDF_Number>("Count", 2);
    bookmarks[0].obj->SetNewFor<CPDF_Reference>("First", m_pIndirectObjs,
                                                bookmarks[1].num);
    bookmarks[0].obj->SetNewFor<CPDF_Reference>("Last", m_pIndirectObjs,
                                                bookmarks[2].num);

    m_pRootObj->SetNewFor<CPDF_Reference>("Outlines", m_pIndirectObjs,
                                          bookmarks[0].num);

    // Title with no match.
    std::unique_ptr<unsigned short, pdfium::FreeDeleter> title =
        GetFPDFWideString(L"Chapter 3");
    EXPECT_EQ(nullptr, FPDFBookmark_Find(m_pDoc.get(), title.get()));

    // Title with a match.
    title = GetFPDFWideString(L"Chapter 2");
    EXPECT_EQ(bookmarks[2].obj, FPDFBookmark_Find(m_pDoc.get(), title.get()));
  }
  {
    // Circular bookmarks in breadth.
    auto bookmarks = CreateDictObjs(4);

    bookmarks[1].obj->SetNewFor<CPDF_String>("Title", L"Chapter 1");
    bookmarks[1].obj->SetNewFor<CPDF_Reference>("Parent", m_pIndirectObjs,
                                                bookmarks[0].num);
    bookmarks[1].obj->SetNewFor<CPDF_Reference>("Next", m_pIndirectObjs,
                                                bookmarks[2].num);

    bookmarks[2].obj->SetNewFor<CPDF_String>("Title", L"Chapter 2");
    bookmarks[2].obj->SetNewFor<CPDF_Reference>("Parent", m_pIndirectObjs,
                                                bookmarks[0].num);
    bookmarks[2].obj->SetNewFor<CPDF_Reference>("Next", m_pIndirectObjs,
                                                bookmarks[3].num);

    bookmarks[3].obj->SetNewFor<CPDF_String>("Title", L"Chapter 3");
    bookmarks[3].obj->SetNewFor<CPDF_Reference>("Parent", m_pIndirectObjs,
                                                bookmarks[0].num);
    bookmarks[3].obj->SetNewFor<CPDF_Reference>("Next", m_pIndirectObjs,
                                                bookmarks[1].num);

    bookmarks[0].obj->SetNewFor<CPDF_Name>("Type", "Outlines");
    bookmarks[0].obj->SetNewFor<CPDF_Number>("Count", 2);
    bookmarks[0].obj->SetNewFor<CPDF_Reference>("First", m_pIndirectObjs,
                                                bookmarks[1].num);
    bookmarks[0].obj->SetNewFor<CPDF_Reference>("Last", m_pIndirectObjs,
                                                bookmarks[2].num);

    m_pRootObj->SetNewFor<CPDF_Reference>("Outlines", m_pIndirectObjs,
                                          bookmarks[0].num);

    // Title with no match.
    std::unique_ptr<unsigned short, pdfium::FreeDeleter> title =
        GetFPDFWideString(L"Chapter 8");
    EXPECT_EQ(nullptr, FPDFBookmark_Find(m_pDoc.get(), title.get()));

    // Title with a match.
    title = GetFPDFWideString(L"Chapter 3");
    EXPECT_EQ(bookmarks[3].obj, FPDFBookmark_Find(m_pDoc.get(), title.get()));
  }
}
TEST_F(FPDFTextEmbeddertest, TextSearch) {
  EXPECT_TRUE(OpenDocument("hello_world.pdf"));
  FPDF_PAGE page = LoadPage(0);
  EXPECT_TRUE(page);

  FPDF_TEXTPAGE textpage = FPDFText_LoadPage(page);
  EXPECT_TRUE(textpage);

  std::unique_ptr<unsigned short, pdfium::FreeDeleter> nope =
      GetFPDFWideString(L"nope");
  std::unique_ptr<unsigned short, pdfium::FreeDeleter> world =
      GetFPDFWideString(L"world");
  std::unique_ptr<unsigned short, pdfium::FreeDeleter> world_caps =
      GetFPDFWideString(L"WORLD");
  std::unique_ptr<unsigned short, pdfium::FreeDeleter> world_substr =
      GetFPDFWideString(L"orld");

  // No occurences of "nope" in test page.
  FPDF_SCHHANDLE search = FPDFText_FindStart(textpage, nope.get(), 0, 0);
  EXPECT_TRUE(search);
  EXPECT_EQ(0, FPDFText_GetSchResultIndex(search));
  EXPECT_EQ(0, FPDFText_GetSchCount(search));

  // Advancing finds nothing.
  EXPECT_FALSE(FPDFText_FindNext(search));
  EXPECT_EQ(0, FPDFText_GetSchResultIndex(search));
  EXPECT_EQ(0, FPDFText_GetSchCount(search));

  // Retreating finds nothing.
  EXPECT_FALSE(FPDFText_FindPrev(search));
  EXPECT_EQ(0, FPDFText_GetSchResultIndex(search));
  EXPECT_EQ(0, FPDFText_GetSchCount(search));
  FPDFText_FindClose(search);

  // Two occurences of "world" in test page.
  search = FPDFText_FindStart(textpage, world.get(), 0, 2);
  EXPECT_TRUE(search);

  // Remains not found until advanced.
  EXPECT_EQ(0, FPDFText_GetSchResultIndex(search));
  EXPECT_EQ(0, FPDFText_GetSchCount(search));

  // First occurence of "world" in this test page.
  EXPECT_TRUE(FPDFText_FindNext(search));
  EXPECT_EQ(7, FPDFText_GetSchResultIndex(search));
  EXPECT_EQ(5, FPDFText_GetSchCount(search));

  // Last occurence of "world" in this test page.
  EXPECT_TRUE(FPDFText_FindNext(search));
  EXPECT_EQ(24, FPDFText_GetSchResultIndex(search));
  EXPECT_EQ(5, FPDFText_GetSchCount(search));

  // Found position unchanged when fails to advance.
  EXPECT_FALSE(FPDFText_FindNext(search));
  EXPECT_EQ(24, FPDFText_GetSchResultIndex(search));
  EXPECT_EQ(5, FPDFText_GetSchCount(search));

  // Back to first occurence.
  EXPECT_TRUE(FPDFText_FindPrev(search));
  EXPECT_EQ(7, FPDFText_GetSchResultIndex(search));
  EXPECT_EQ(5, FPDFText_GetSchCount(search));

  // Found position unchanged when fails to retreat.
  EXPECT_FALSE(FPDFText_FindPrev(search));
  EXPECT_EQ(7, FPDFText_GetSchResultIndex(search));
  EXPECT_EQ(5, FPDFText_GetSchCount(search));
  FPDFText_FindClose(search);

  // Exact search unaffected by case sensitiity and whole word flags.
  search = FPDFText_FindStart(textpage, world.get(),
                              FPDF_MATCHCASE | FPDF_MATCHWHOLEWORD, 0);
  EXPECT_TRUE(search);
  EXPECT_TRUE(FPDFText_FindNext(search));
  EXPECT_EQ(7, FPDFText_GetSchResultIndex(search));
  EXPECT_EQ(5, FPDFText_GetSchCount(search));
  FPDFText_FindClose(search);

  // Default is case-insensitive, so matching agaist caps works.
  search = FPDFText_FindStart(textpage, world_caps.get(), 0, 0);
  EXPECT_TRUE(search);
  EXPECT_TRUE(FPDFText_FindNext(search));
  EXPECT_EQ(7, FPDFText_GetSchResultIndex(search));
  EXPECT_EQ(5, FPDFText_GetSchCount(search));
  FPDFText_FindClose(search);

  // But can be made case sensitive, in which case this fails.
  search = FPDFText_FindStart(textpage, world_caps.get(), FPDF_MATCHCASE, 0);
  EXPECT_FALSE(FPDFText_FindNext(search));
  EXPECT_EQ(0, FPDFText_GetSchResultIndex(search));
  EXPECT_EQ(0, FPDFText_GetSchCount(search));
  FPDFText_FindClose(search);

  // Default is match anywhere within word, so matching substirng works.
  search = FPDFText_FindStart(textpage, world_substr.get(), 0, 0);
  EXPECT_TRUE(FPDFText_FindNext(search));
  EXPECT_EQ(8, FPDFText_GetSchResultIndex(search));
  EXPECT_EQ(4, FPDFText_GetSchCount(search));
  FPDFText_FindClose(search);

  // But can be made to mach word boundaries, in which case this fails.
  search =
      FPDFText_FindStart(textpage, world_substr.get(), FPDF_MATCHWHOLEWORD, 0);
  EXPECT_FALSE(FPDFText_FindNext(search));
  // TODO(tsepez): investigate strange index/count values in this state.
  FPDFText_FindClose(search);

  FPDFText_ClosePage(textpage);
  UnloadPage(page);
}