blob: 337ab35e0f148af5d3143c3fd5c13487f9e1c8fa [file] [log] [blame]
// 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<size_t>(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;
}