From 18ae06d9ae493276b3ddcd37eb19de7aeba1a0e8 Mon Sep 17 00:00:00 2001 From: Jane Liu Date: Tue, 18 Jul 2017 10:15:16 -0400 Subject: Basic APIs and tests for extracting attachments 1. Added API for extracting attachment properties and data. * Expanded the embedder test to cover all the new APIs. Bug=pdfium:174 Change-Id: I09bffd412410e9aea45faca442d2b72eefafef4e Reviewed-on: https://pdfium-review.googlesource.com/7790 Reviewed-by: dsinclair Commit-Queue: dsinclair --- fpdfsdk/fpdfattachment.cpp | 120 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 107 insertions(+), 13 deletions(-) (limited to 'fpdfsdk/fpdfattachment.cpp') diff --git a/fpdfsdk/fpdfattachment.cpp b/fpdfsdk/fpdfattachment.cpp index e07d15b0c8..337ab35e0f 100644 --- a/fpdfsdk/fpdfattachment.cpp +++ b/fpdfsdk/fpdfattachment.cpp @@ -4,7 +4,10 @@ #include "public/fpdf_attachment.h" +#include "core/fpdfapi/page/cpdf_streamparser.h" #include "core/fpdfapi/parser/cpdf_document.h" +#include "core/fpdfapi/parser/cpdf_string.h" +#include "core/fpdfapi/parser/fpdf_parser_decode.h" #include "core/fpdfdoc/cpdf_filespec.h" #include "core/fpdfdoc/cpdf_nametree.h" #include "fpdfsdk/fsdk_define.h" @@ -17,28 +20,119 @@ DLLEXPORT int STDCALL FPDFDoc_GetAttachmentCount(FPDF_DOCUMENT document) { return CPDF_NameTree(pDoc, "EmbeddedFiles").GetCount(); } -DLLEXPORT unsigned long STDCALL -FPDFDoc_GetAttachmentName(FPDF_DOCUMENT document, - int index, - void* buffer, - unsigned long buflen) { +DLLEXPORT FPDF_ATTACHMENT STDCALL FPDFDoc_GetAttachment(FPDF_DOCUMENT document, + int index) { CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document); if (!pDoc || index < 0) - return 0; + return nullptr; CPDF_NameTree nameTree(pDoc, "EmbeddedFiles"); if (static_cast(index) >= nameTree.GetCount()) - return 0; + return nullptr; CFX_ByteString csName; - CPDF_Object* pFile = nameTree.LookupValueAndName(index, &csName); + return nameTree.LookupValueAndName(index, &csName); +} + +DLLEXPORT unsigned long STDCALL +FPDFAttachment_GetName(FPDF_ATTACHMENT attachment, + void* buffer, + unsigned long buflen) { + CPDF_Object* pFile = CPDFObjectFromFPDFAttachment(attachment); + if (!pFile) + return 0; + + return Utf16EncodeMaybeCopyAndReturnLength(CPDF_FileSpec(pFile).GetFileName(), + buffer, buflen); +} + +DLLEXPORT FPDF_BOOL STDCALL FPDFAttachment_HasKey(FPDF_ATTACHMENT attachment, + FPDF_WIDESTRING key) { + CPDF_Object* pFile = CPDFObjectFromFPDFAttachment(attachment); + if (!pFile) + return 0; + + CPDF_Dictionary* pParamsDict = CPDF_FileSpec(pFile).GetParamsDict(); + if (!pParamsDict) + return 0; + + return pParamsDict->KeyExist(CFXByteStringFromFPDFWideString(key)); +} + +DLLEXPORT FPDF_OBJECT_TYPE STDCALL +FPDFAttachment_GetValueType(FPDF_ATTACHMENT attachment, FPDF_WIDESTRING key) { + if (!FPDFAttachment_HasKey(attachment, key)) + return FPDF_OBJECT_UNKNOWN; + + CPDF_Object* pObj = CPDF_FileSpec(CPDFObjectFromFPDFAttachment(attachment)) + .GetParamsDict() + ->GetObjectFor(CFXByteStringFromFPDFWideString(key)); + if (!pObj) + return FPDF_OBJECT_UNKNOWN; + + return pObj->GetType(); +} + +DLLEXPORT unsigned long STDCALL +FPDFAttachment_GetStringValue(FPDF_ATTACHMENT attachment, + FPDF_WIDESTRING key, + void* buffer, + unsigned long buflen) { + CPDF_Object* pFile = CPDFObjectFromFPDFAttachment(attachment); + if (!pFile) + return 0; + + CPDF_Dictionary* pParamsDict = CPDF_FileSpec(pFile).GetParamsDict(); + if (!pParamsDict) + return 0; + + CFX_ByteString bsKey = CFXByteStringFromFPDFWideString(key); + CFX_WideString value = pParamsDict->GetUnicodeTextFor(bsKey); + if (bsKey == "CheckSum") { + CPDF_String* stringValue = pParamsDict->GetObjectFor(bsKey)->AsString(); + if (stringValue->IsHex()) { + value = + CPDF_String(nullptr, PDF_EncodeString(stringValue->GetString(), true), + false) + .GetUnicodeText(); + } + } + + return Utf16EncodeMaybeCopyAndReturnLength(value, buffer, buflen); +} + +DLLEXPORT unsigned long STDCALL +FPDFAttachment_GetFile(FPDF_ATTACHMENT attachment, + void* buffer, + unsigned long buflen) { + CPDF_Object* pFile = CPDFObjectFromFPDFAttachment(attachment); if (!pFile) return 0; - CFX_ByteString name = CPDF_FileSpec(pFile).GetFileName().UTF16LE_Encode(); - unsigned long len = name.GetLength(); - if (buffer && buflen >= len) - memcpy(buffer, name.c_str(), len); + CPDF_Stream* pFileStream = CPDF_FileSpec(pFile).GetFileStream(); + if (!pFileStream) + return 0; + + uint8_t* data = pFileStream->GetRawData(); + uint32_t len = pFileStream->GetRawSize(); + CPDF_Dictionary* pFileDict = pFileStream->GetDict(); + if (!pFileDict || pFileDict->GetStringFor("Filter").IsEmpty()) { + if (buffer && buflen >= len) + memcpy(buffer, data, len); + + return len; + } + + // Decode the stream if a stream filter is specified. + uint8_t* decodedData = nullptr; + uint32_t decodedLen = 0; + CPDF_StreamParser::DecodeInlineStream( + data, len, pFileDict->GetIntegerFor("Width"), + pFileDict->GetIntegerFor("Height"), pFileDict->GetStringFor("Filter"), + pFileDict->GetDictFor("DecodeParms"), &decodedData, &decodedLen); + if (buffer && buflen >= decodedLen) + memcpy(buffer, decodedData, decodedLen); - return len; + FX_Free(decodedData); + return decodedLen; } -- cgit v1.2.3