Basic APIs and test for retrieving embedded attachment count and name

1. Added APIs for retrieving embedded attachment count and file name.
    * Added an embedder test testing them.

Bug=pdfium:174

Change-Id: I181b8e0b81495d8a7fd8c3f79dbbc0f907f5e3fd
Reviewed-on: https://pdfium-review.googlesource.com/7490
Commit-Queue: Jane Liu <janeliulwq@google.com>
Reviewed-by: dsinclair <dsinclair@chromium.org>
diff --git a/BUILD.gn b/BUILD.gn
index fff58b3..ff0d905 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -136,6 +136,7 @@
     "fpdfsdk/fpdf_sysfontinfo.cpp",
     "fpdfsdk/fpdf_transformpage.cpp",
     "fpdfsdk/fpdfannot.cpp",
+    "fpdfsdk/fpdfattachment.cpp",
     "fpdfsdk/fpdfdoc.cpp",
     "fpdfsdk/fpdfeditimg.cpp",
     "fpdfsdk/fpdfeditpage.cpp",
@@ -156,6 +157,7 @@
     "fpdfsdk/pdfsdk_fieldaction.h",
     "public/cpp/fpdf_deleters.h",
     "public/fpdf_annot.h",
+    "public/fpdf_attachment.h",
     "public/fpdf_dataavail.h",
     "public/fpdf_doc.h",
     "public/fpdf_edit.h",
@@ -2005,6 +2007,7 @@
     "fpdfsdk/fpdf_flatten_embeddertest.cpp",
     "fpdfsdk/fpdf_structtree_embeddertest.cpp",
     "fpdfsdk/fpdfannot_embeddertest.cpp",
+    "fpdfsdk/fpdfattachment_embeddertest.cpp",
     "fpdfsdk/fpdfdoc_embeddertest.cpp",
     "fpdfsdk/fpdfedit_embeddertest.cpp",
     "fpdfsdk/fpdfext_embeddertest.cpp",
diff --git a/fpdfsdk/fpdfattachment.cpp b/fpdfsdk/fpdfattachment.cpp
new file mode 100644
index 0000000..d8713bb
--- /dev/null
+++ b/fpdfsdk/fpdfattachment.cpp
@@ -0,0 +1,47 @@
+// Copyright 2017 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "public/fpdf_attachment.h"
+
+#include "core/fpdfapi/parser/cpdf_document.h"
+#include "core/fpdfdoc/cpdf_filespec.h"
+#include "core/fpdfdoc/cpdf_nametree.h"
+#include "fpdfsdk/fsdk_define.h"
+
+DLLEXPORT int STDCALL FPDFDoc_GetAttachmentCount(FPDF_DOCUMENT document) {
+  CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
+  if (!pDoc)
+    return 0;
+
+  return CPDF_NameTree(pDoc, "EmbeddedFiles").GetCount();
+}
+
+DLLEXPORT unsigned long STDCALL
+FPDFDoc_GetAttachmentName(FPDF_DOCUMENT document,
+                          int index,
+                          void* buffer,
+                          unsigned long buflen) {
+  CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
+  if (!pDoc || index < 0)
+    return 0;
+
+  CPDF_NameTree nameTree(pDoc, "EmbeddedFiles");
+  if (static_cast<size_t>(index) >= nameTree.GetCount())
+    return 0;
+
+  CFX_ByteString csName;
+  CPDF_Object* pFile = nameTree.LookupValueAndName(index, &csName);
+  if (!pFile)
+    return 0;
+
+  CFX_WideString name;
+  CPDF_FileSpec filespec(pFile);
+  filespec.GetFileName(&name);
+  CFX_ByteString encodedName = name.UTF16LE_Encode();
+  unsigned long len = encodedName.GetLength();
+  if (buffer && buflen >= len)
+    memcpy(buffer, encodedName.c_str(), len);
+
+  return len;
+}
diff --git a/fpdfsdk/fpdfattachment_embeddertest.cpp b/fpdfsdk/fpdfattachment_embeddertest.cpp
new file mode 100644
index 0000000..2cbda8a
--- /dev/null
+++ b/fpdfsdk/fpdfattachment_embeddertest.cpp
@@ -0,0 +1,22 @@
+// Copyright 2017 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "public/fpdf_attachment.h"
+#include "testing/embedder_test.h"
+
+class FPDFAttachmentEmbeddertest : public EmbedderTest {};
+
+TEST_F(FPDFAttachmentEmbeddertest, ExtractAttachments) {
+  // Open a file with two attachments.
+  ASSERT_TRUE(OpenDocument("embedded_attachments.pdf"));
+  EXPECT_EQ(2, FPDFDoc_GetAttachmentCount(document()));
+
+  // Check that the name of the first attachment is correct.
+  unsigned long len = FPDFDoc_GetAttachmentName(document(), 0, nullptr, 0);
+  std::vector<char> buf(len);
+  EXPECT_EQ(12u, FPDFDoc_GetAttachmentName(document(), 0, buf.data(), len));
+  EXPECT_STREQ(L"1.txt",
+               GetPlatformWString(reinterpret_cast<unsigned short*>(buf.data()))
+                   .c_str());
+}
diff --git a/fpdfsdk/fpdfview_c_api_test.c b/fpdfsdk/fpdfview_c_api_test.c
index 1c066dd..2fcaf74 100644
--- a/fpdfsdk/fpdfview_c_api_test.c
+++ b/fpdfsdk/fpdfview_c_api_test.c
@@ -10,6 +10,7 @@
 #include "fpdfsdk/fpdfview_c_api_test.h"
 
 #include "public/fpdf_annot.h"
+#include "public/fpdf_attachment.h"
 #include "public/fpdf_dataavail.h"
 #include "public/fpdf_doc.h"
 #include "public/fpdf_edit.h"
@@ -34,7 +35,7 @@
 
 // Function to call from gtest harness to ensure linker resolution.
 int CheckPDFiumCApi() {
-    //fpdf_annot.h
+    // fpdf_annot.h
     CHK(FPDFAnnot_IsSupportedSubtype);
     CHK(FPDFPage_CreateAnnot);
     CHK(FPDFPage_GetAnnotCount);
@@ -61,6 +62,10 @@
     CHK(FPDFAnnot_GetFlags);
     CHK(FPDFAnnot_SetFlags);
 
+    // fpdf_attachment.h
+    CHK(FPDFDoc_GetAttachmentCount);
+    CHK(FPDFDoc_GetAttachmentName);
+
     // fpdf_dataavail.h
     CHK(FPDFAvail_Create);
     CHK(FPDFAvail_Destroy);
diff --git a/public/fpdf_attachment.h b/public/fpdf_attachment.h
new file mode 100644
index 0000000..07fdff5
--- /dev/null
+++ b/public/fpdf_attachment.h
@@ -0,0 +1,44 @@
+// Copyright 2017 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PUBLIC_FPDF_ATTACHMENT_H_
+#define PUBLIC_FPDF_ATTACHMENT_H_
+
+// NOLINTNEXTLINE(build/include)
+#include "fpdfview.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif  // __cplusplus
+
+// Experimental API.
+// Get the number of embedded files in |document|.
+//
+//   document - handle to a document.
+//
+// Returns the number of embedded files in |document|.
+DLLEXPORT int STDCALL FPDFDoc_GetAttachmentCount(FPDF_DOCUMENT document);
+
+// Experimental API.
+// Get the name of the embedded file at |index| in |document|. |buffer| is
+// only modified if |buflen| is longer than the length of the file name. On
+// errors, |buffer| is unmodified and the returned length is 0.
+//
+//   document - handle to a document.
+//   index    - the index of the requested embedded file.
+//   buffer   - buffer for holding the file name, encoded in UTF16-LE.
+//   buflen   - length of the buffer.
+//
+// Returns the length of the file name.
+DLLEXPORT unsigned long STDCALL
+FPDFDoc_GetAttachmentName(FPDF_DOCUMENT document,
+                          int index,
+                          void* buffer,
+                          unsigned long buflen);
+
+#ifdef __cplusplus
+}  // extern "C"
+#endif  // __cplusplus
+
+#endif  // PUBLIC_FPDF_ATTACHMENT_H_
diff --git a/testing/resources/embedded_attachments.pdf b/testing/resources/embedded_attachments.pdf
new file mode 100644
index 0000000..1e8fecd
--- /dev/null
+++ b/testing/resources/embedded_attachments.pdf
Binary files differ