// 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/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" DLLEXPORT int STDCALL FPDFDoc_GetAttachmentCount(FPDF_DOCUMENT document) { CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document); if (!pDoc) return 0; return CPDF_NameTree(pDoc, "EmbeddedFiles").GetCount(); } DLLEXPORT FPDF_ATTACHMENT STDCALL FPDFDoc_GetAttachment(FPDF_DOCUMENT document, int index) { CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document); if (!pDoc || index < 0) return nullptr; CPDF_NameTree nameTree(pDoc, "EmbeddedFiles"); if (static_cast(index) >= nameTree.GetCount()) return nullptr; CFX_ByteString 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; 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); FX_Free(decodedData); return decodedLen; }