Fixing metadata not read from linearized file. This still won't work if the info dict is not on the first page without first calling FPDFAvail_IsFormAvail or FPDFAvail_IsPageAvail, as these are the methods that trigger parsing the rest of the data. Bug: pdfium:664 Change-Id: I0b0193e415a1153dcfb8bfba0e0482da6b6ba53c Reviewed-on: https://pdfium-review.googlesource.com/6610 Commit-Queue: Henrique Nakashima <hnakashima@chromium.org> Reviewed-by: dsinclair <dsinclair@chromium.org> Reviewed-by: Nicolás Peña <npm@chromium.org>
diff --git a/core/fpdfapi/parser/cpdf_document.cpp b/core/fpdfapi/parser/cpdf_document.cpp index 1fdd59e..9bfb16b 100644 --- a/core/fpdfapi/parser/cpdf_document.cpp +++ b/core/fpdfapi/parser/cpdf_document.cpp
@@ -374,6 +374,10 @@ if (!m_pRootDict) return; + LoadDocumentInfo(); +} + +void CPDF_Document::LoadDocumentInfo() { CPDF_Object* pInfoObj = GetOrParseIndirectObject(m_pParser->GetInfoObjNum()); if (pInfoObj) m_pInfoDict = pInfoObj->GetDict();
diff --git a/core/fpdfapi/parser/cpdf_document.h b/core/fpdfapi/parser/cpdf_document.h index 493c1ed..e6107e1 100644 --- a/core/fpdfapi/parser/cpdf_document.h +++ b/core/fpdfapi/parser/cpdf_document.h
@@ -87,6 +87,7 @@ void LoadDoc(); void LoadLinearizedDoc(const CPDF_LinearizedHeader* pLinearizationParams); void LoadPages(); + void LoadDocumentInfo(); void CreateNewDoc(); CPDF_Dictionary* CreateNewPage(int iPage);
diff --git a/core/fpdfapi/parser/cpdf_parser.cpp b/core/fpdfapi/parser/cpdf_parser.cpp index 01c3b8c..b2bde8d 100644 --- a/core/fpdfapi/parser/cpdf_parser.cpp +++ b/core/fpdfapi/parser/cpdf_parser.cpp
@@ -360,6 +360,9 @@ if (!LoadLinearizedCrossRefV4(xrefpos, dwObjCount)) return false; + if (m_pTrailer) + m_Trailers.push_back(std::move(m_pTrailer)); + m_pTrailer = LoadTrailerV4(); if (!m_pTrailer) return false; @@ -1084,7 +1087,18 @@ uint32_t CPDF_Parser::GetInfoObjNum() { CPDF_Reference* pRef = ToReference(m_pTrailer ? m_pTrailer->GetObjectFor("Info") : nullptr); - return pRef ? pRef->GetRefObjNum() : 0; + if (pRef) + return pRef->GetRefObjNum(); + + // Search trailers array from latest to earliest revision, as we want the + // most recent Info object number. + // See PDF 1.7 spec, section 3.4.5 - Incremental Updates. + for (auto it = m_Trailers.rbegin(); it != m_Trailers.rend(); ++it) { + pRef = ToReference(it->get()->GetObjectFor("Info")); + if (pRef) + return pRef->GetRefObjNum(); + } + return 0; } std::unique_ptr<CPDF_Object> CPDF_Parser::ParseIndirectObject( @@ -1545,7 +1559,8 @@ CPDF_Parser::Error CPDF_Parser::LoadLinearizedMainXRefTable() { uint32_t dwSaveMetadataObjnum = m_pSyntax->m_MetadataObjnum; m_pSyntax->m_MetadataObjnum = 0; - m_pTrailer.reset(); + if (m_pTrailer) + m_Trailers.push_back(std::move(m_pTrailer)); m_pSyntax->SetPos(m_LastXRefOffset - m_pSyntax->m_HeaderOffset); uint8_t ch = 0;
diff --git a/fpdfsdk/fpdfdoc.cpp b/fpdfsdk/fpdfdoc.cpp index 1c445e6..7be53a6 100644 --- a/fpdfsdk/fpdfdoc.cpp +++ b/fpdfsdk/fpdfdoc.cpp
@@ -394,6 +394,7 @@ CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document); if (!pDoc) return 0; + pDoc->LoadDocumentInfo(); CPDF_Dictionary* pInfo = pDoc->GetInfo(); if (!pInfo) return 0;
diff --git a/samples/pdfium_test.cc b/samples/pdfium_test.cc index 86f6f89..14aa6c1 100644 --- a/samples/pdfium_test.cc +++ b/samples/pdfium_test.cc
@@ -74,12 +74,14 @@ struct Options { Options() : show_config(false), + show_metadata(false), send_events(false), pages(false), md5(false), output_format(OUTPUT_NONE) {} bool show_config; + bool show_metadata; bool send_events; bool pages; bool md5; @@ -625,6 +627,8 @@ const std::string& cur_arg = args[cur_idx]; if (cur_arg == "--show-config") { options->show_config = true; + } else if (cur_arg == "--show-metadata") { + options->show_metadata = true; } else if (cur_arg == "--send-events") { options->send_events = true; } else if (cur_arg == "--ppm") { @@ -1108,6 +1112,19 @@ (void)FPDF_GetDocPermissions(doc.get()); + if (options.show_metadata) { + const char* metaTags[] = {"Title", "Author", "Subject", "Keywords", + "Creator", "Producer", "CreationDate", "ModDate"}; + for (const char* metaTag : metaTags) { + char metaBuffer[4096]; + int len = FPDF_GetMetaText(doc.get(), metaTag, metaBuffer, 4096); + printf("%-12s = %ls (%d bytes)\n", metaTag, + GetPlatformWString(reinterpret_cast<unsigned short*>(metaBuffer)) + .c_str(), + len); + } + } + std::unique_ptr<void, FPDFFormHandleDeleter> form( FPDFDOC_InitFormFillEnvironment(doc.get(), &form_callbacks)); form_callbacks.form_handle = form.get();