summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJane Liu <janeliulwq@google.com>2017-07-11 15:16:08 -0400
committerChromium commit bot <commit-bot@chromium.org>2017-07-12 20:12:44 +0000
commitdc1aa325c22a3d6cd240efa9d35f9e175fe8455b (patch)
treeccaec7e2305811fc68e34091370dcb17221aab14
parentd79ac21b7595442bce82ec93f59cda9f8fb3cb24 (diff)
downloadpdfium-dc1aa325c22a3d6cd240efa9d35f9e175fe8455b.tar.xz
Added helper functions in the class CPDF_FileSpec
1. Added two helper functions in CPDF_FileSpec, which will be useful when adding support for embedded files: CPDF_FileSpec::GetFileStream() - useful because the stream object contains the file's data CPDF_FileSpec::GetParamsDict() - useful because the params dictionary contains parameters of the file, such as creation date, size, etc. * Added two unit tests testing both functions. Bug=pdfium:174 Change-Id: I33ea21ddb621434007f94767f281ead0b00ecb8a Reviewed-on: https://pdfium-review.googlesource.com/7355 Reviewed-by: dsinclair <dsinclair@chromium.org> Reviewed-by: Lei Zhang <thestig@chromium.org> Commit-Queue: Jane Liu <janeliulwq@google.com>
-rw-r--r--core/fpdfdoc/cpdf_filespec.cpp49
-rw-r--r--core/fpdfdoc/cpdf_filespec.h4
-rw-r--r--core/fpdfdoc/cpdf_filespec_unittest.cpp98
3 files changed, 146 insertions, 5 deletions
diff --git a/core/fpdfdoc/cpdf_filespec.cpp b/core/fpdfdoc/cpdf_filespec.cpp
index 59915eaa05..7d1f0e68b9 100644
--- a/core/fpdfdoc/cpdf_filespec.cpp
+++ b/core/fpdfdoc/cpdf_filespec.cpp
@@ -6,9 +6,12 @@
#include "core/fpdfdoc/cpdf_filespec.h"
+#include <vector>
+
#include "core/fpdfapi/parser/cpdf_dictionary.h"
#include "core/fpdfapi/parser/cpdf_name.h"
#include "core/fpdfapi/parser/cpdf_object.h"
+#include "core/fpdfapi/parser/cpdf_stream.h"
#include "core/fpdfapi/parser/cpdf_string.h"
#include "core/fpdfapi/parser/fpdf_parser_decode.h"
#include "core/fxcrt/fx_system.h"
@@ -50,6 +53,12 @@ CFX_WideString ChangeSlashToPDF(const wchar_t* str) {
} // namespace
+CPDF_FileSpec::CPDF_FileSpec(CPDF_Object* pObj) : m_pObj(pObj) {
+ ASSERT(m_pObj);
+}
+
+CPDF_FileSpec::~CPDF_FileSpec() {}
+
CFX_WideString CPDF_FileSpec::DecodeFileName(const CFX_WideString& filepath) {
if (filepath.GetLength() <= 1)
return CFX_WideString();
@@ -112,9 +121,42 @@ bool CPDF_FileSpec::GetFileName(CFX_WideString* csFileName) const {
return true;
}
-CPDF_FileSpec::CPDF_FileSpec(CPDF_Object* pObj) : m_pObj(pObj) {}
+CPDF_Stream* CPDF_FileSpec::GetFileStream() const {
+ CPDF_Dictionary* pDict = m_pObj->AsDictionary();
+ if (!pDict)
+ return nullptr;
+
+ // Get the embedded files dictionary.
+ CPDF_Dictionary* pFiles = pDict->GetDictFor("EF");
+ if (!pFiles)
+ return nullptr;
+
+ // Get the file stream of the highest precedence with its file specification
+ // string available. Follows the same precedence order as GetFileName().
+ constexpr const char* keys[] = {"UF", "F", "DOS", "Mac", "Unix"};
+ size_t end = pDict->GetStringFor("FS") == "URL" ? 2 : FX_ArraySize(keys);
+ for (size_t i = 0; i < end; ++i) {
+ const CFX_ByteString& key = keys[i];
+ if (!pDict->GetUnicodeTextFor(key).IsEmpty()) {
+ CPDF_Stream* pStream = pFiles->GetStreamFor(key);
+ if (pStream)
+ return pStream;
+ }
+ }
+ return nullptr;
+}
-CPDF_FileSpec::~CPDF_FileSpec() {}
+CPDF_Dictionary* CPDF_FileSpec::GetParamsDict() const {
+ CPDF_Stream* pStream = GetFileStream();
+ if (!pStream)
+ return nullptr;
+
+ CPDF_Dictionary* pDict = pStream->GetDict();
+ if (!pDict)
+ return nullptr;
+
+ return pDict->GetDictFor("Params");
+}
CFX_WideString CPDF_FileSpec::EncodeFileName(const CFX_WideString& filepath) {
if (filepath.GetLength() <= 1)
@@ -146,9 +188,6 @@ CFX_WideString CPDF_FileSpec::EncodeFileName(const CFX_WideString& filepath) {
}
void CPDF_FileSpec::SetFileName(const CFX_WideString& wsFileName) {
- if (!m_pObj)
- return;
-
CFX_WideString wsStr = EncodeFileName(wsFileName);
if (m_pObj->IsString()) {
m_pObj->SetString(CFX_ByteString::FromUnicode(wsStr));
diff --git a/core/fpdfdoc/cpdf_filespec.h b/core/fpdfdoc/cpdf_filespec.h
index 04baf2e63f..2cef20b48a 100644
--- a/core/fpdfdoc/cpdf_filespec.h
+++ b/core/fpdfdoc/cpdf_filespec.h
@@ -12,7 +12,9 @@
#include "core/fxcrt/cfx_weak_ptr.h"
#include "core/fxcrt/fx_string.h"
+class CPDF_Dictionary;
class CPDF_Object;
+class CPDF_Stream;
class CPDF_FileSpec {
public:
@@ -27,6 +29,8 @@ class CPDF_FileSpec {
CPDF_Object* GetObj() const { return m_pObj.Get(); }
bool GetFileName(CFX_WideString* wsFileName) const;
+ CPDF_Stream* GetFileStream() const;
+ CPDF_Dictionary* GetParamsDict() const;
// Set this file spec to refer to a file name (not a url).
void SetFileName(const CFX_WideString& wsFileName);
diff --git a/core/fpdfdoc/cpdf_filespec_unittest.cpp b/core/fpdfdoc/cpdf_filespec_unittest.cpp
index e237aa5b6b..7e2975c5f0 100644
--- a/core/fpdfdoc/cpdf_filespec_unittest.cpp
+++ b/core/fpdfdoc/cpdf_filespec_unittest.cpp
@@ -3,10 +3,13 @@
// found in the LICENSE file.
#include <memory>
+#include <utility>
#include <vector>
#include "core/fpdfapi/parser/cpdf_dictionary.h"
#include "core/fpdfapi/parser/cpdf_name.h"
+#include "core/fpdfapi/parser/cpdf_number.h"
+#include "core/fpdfapi/parser/cpdf_stream.h"
#include "core/fpdfapi/parser/cpdf_string.h"
#include "core/fpdfdoc/cpdf_filespec.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -161,3 +164,98 @@ TEST(cpdf_filespec, SetFileName) {
EXPECT_TRUE(file_spec2.GetFileName(&file_name));
EXPECT_TRUE(file_name == test_data.input);
}
+
+TEST(cpdf_filespec, GetFileStream) {
+ {
+ // Invalid object.
+ auto name_obj = pdfium::MakeUnique<CPDF_Name>(nullptr, "test.pdf");
+ CPDF_FileSpec file_spec(name_obj.get());
+ EXPECT_FALSE(file_spec.GetFileStream());
+ }
+ {
+ // Dictionary object missing its embedded files dictionary.
+ auto dict_obj = pdfium::MakeUnique<CPDF_Dictionary>();
+ CPDF_FileSpec file_spec(dict_obj.get());
+ EXPECT_FALSE(file_spec.GetFileStream());
+ }
+ {
+ // Dictionary object with an empty embedded files dictionary.
+ auto dict_obj = pdfium::MakeUnique<CPDF_Dictionary>();
+ dict_obj->SetNewFor<CPDF_Dictionary>("EF");
+ CPDF_FileSpec file_spec(dict_obj.get());
+ EXPECT_FALSE(file_spec.GetFileStream());
+ }
+ {
+ // Dictionary object with a non-empty embedded files dictionary.
+ auto dict_obj = pdfium::MakeUnique<CPDF_Dictionary>();
+ dict_obj->SetNewFor<CPDF_Dictionary>("EF");
+ CPDF_FileSpec file_spec(dict_obj.get());
+
+ const char* const keys[5] = {"Unix", "Mac", "DOS", "F", "UF"};
+ const wchar_t file_name[] = L"test.pdf";
+ const char* const stream[5] = {"test1", "test2", "test3", "test4", "test5"};
+ CPDF_Dictionary* file_dict =
+ file_spec.GetObj()->AsDictionary()->GetDictFor("EF");
+
+ // Keys in reverse order of precedence to retrieve the file content stream.
+ for (size_t i = 0; i < FX_ArraySize(keys); ++i) {
+ // Set the file name.
+ dict_obj->SetNewFor<CPDF_String>(keys[i], file_name);
+
+ // Set the file stream.
+ auto pDict = pdfium::MakeUnique<CPDF_Dictionary>();
+ size_t buf_len = strlen(stream[i]) + 1;
+ std::unique_ptr<uint8_t, FxFreeDeleter> buf(FX_Alloc(uint8_t, buf_len));
+ memcpy(buf.get(), stream[i], buf_len);
+ file_dict->SetNewFor<CPDF_Stream>(keys[i], std::move(buf), buf_len,
+ std::move(pDict));
+
+ // Check that the file content stream is as expected.
+ EXPECT_STREQ(
+ stream[i],
+ file_spec.GetFileStream()->GetUnicodeText().UTF8Encode().c_str());
+
+ if (i == 2) {
+ dict_obj->SetNewFor<CPDF_String>("FS", "URL", false);
+ EXPECT_FALSE(file_spec.GetFileStream());
+ }
+ }
+ }
+}
+
+TEST(cpdf_filespec, GetParamsDict) {
+ {
+ // Invalid object.
+ auto name_obj = pdfium::MakeUnique<CPDF_Name>(nullptr, "test.pdf");
+ CPDF_FileSpec file_spec(name_obj.get());
+ EXPECT_FALSE(file_spec.GetParamsDict());
+ }
+ {
+ // Dictionary object.
+ auto dict_obj = pdfium::MakeUnique<CPDF_Dictionary>();
+ dict_obj->SetNewFor<CPDF_Dictionary>("EF");
+ dict_obj->SetNewFor<CPDF_String>("UF", L"test.pdf");
+ CPDF_FileSpec file_spec(dict_obj.get());
+ EXPECT_FALSE(file_spec.GetParamsDict());
+
+ // Add a file stream to the embedded files dictionary.
+ CPDF_Dictionary* file_dict =
+ file_spec.GetObj()->AsDictionary()->GetDictFor("EF");
+ auto pDict = pdfium::MakeUnique<CPDF_Dictionary>();
+ std::unique_ptr<uint8_t, FxFreeDeleter> buf(FX_Alloc(uint8_t, 6));
+ memcpy(buf.get(), "hello", 6);
+ file_dict->SetNewFor<CPDF_Stream>("UF", std::move(buf), 6,
+ std::move(pDict));
+
+ // Add a params dictionary to the file stream.
+ CPDF_Stream* stream = file_dict->GetStreamFor("UF");
+ CPDF_Dictionary* stream_dict = stream->GetDict();
+ stream_dict->SetNewFor<CPDF_Dictionary>("Params");
+ EXPECT_TRUE(file_spec.GetParamsDict());
+
+ // Add a parameter to the params dictionary.
+ CPDF_Dictionary* params_dict = stream_dict->GetDictFor("Params");
+ params_dict->SetNewFor<CPDF_Number>("Size", 6);
+ EXPECT_EQ(6, file_spec.GetParamsDict()->GetIntegerFor("Size"));
+ }
+}