blob: 7d8cce736bfa13c588b5e518e2ac78ba519a7dab [file] [log] [blame]
Jane Liu53aafa92017-07-12 19:55:02 -04001// Copyright 2017 PDFium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "public/fpdf_attachment.h"
6
Jane Liu18ae06d2017-07-18 10:15:16 -04007#include "core/fpdfapi/page/cpdf_streamparser.h"
Jane Liu53aafa92017-07-12 19:55:02 -04008#include "core/fpdfapi/parser/cpdf_document.h"
Jane Liu18ae06d2017-07-18 10:15:16 -04009#include "core/fpdfapi/parser/cpdf_string.h"
10#include "core/fpdfapi/parser/fpdf_parser_decode.h"
Jane Liu53aafa92017-07-12 19:55:02 -040011#include "core/fpdfdoc/cpdf_filespec.h"
12#include "core/fpdfdoc/cpdf_nametree.h"
13#include "fpdfsdk/fsdk_define.h"
14
15DLLEXPORT int STDCALL FPDFDoc_GetAttachmentCount(FPDF_DOCUMENT document) {
16 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
17 if (!pDoc)
18 return 0;
19
20 return CPDF_NameTree(pDoc, "EmbeddedFiles").GetCount();
21}
22
Jane Liu18ae06d2017-07-18 10:15:16 -040023DLLEXPORT FPDF_ATTACHMENT STDCALL FPDFDoc_GetAttachment(FPDF_DOCUMENT document,
24 int index) {
Jane Liu53aafa92017-07-12 19:55:02 -040025 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
26 if (!pDoc || index < 0)
Jane Liu18ae06d2017-07-18 10:15:16 -040027 return nullptr;
Jane Liu53aafa92017-07-12 19:55:02 -040028
29 CPDF_NameTree nameTree(pDoc, "EmbeddedFiles");
30 if (static_cast<size_t>(index) >= nameTree.GetCount())
Jane Liu18ae06d2017-07-18 10:15:16 -040031 return nullptr;
Jane Liu53aafa92017-07-12 19:55:02 -040032
Jane Liu67ccef72017-07-19 13:10:50 -040033 CFX_WideString csName;
Jane Liu18ae06d2017-07-18 10:15:16 -040034 return nameTree.LookupValueAndName(index, &csName);
35}
36
37DLLEXPORT unsigned long STDCALL
38FPDFAttachment_GetName(FPDF_ATTACHMENT attachment,
39 void* buffer,
40 unsigned long buflen) {
41 CPDF_Object* pFile = CPDFObjectFromFPDFAttachment(attachment);
Jane Liu53aafa92017-07-12 19:55:02 -040042 if (!pFile)
43 return 0;
44
Jane Liu18ae06d2017-07-18 10:15:16 -040045 return Utf16EncodeMaybeCopyAndReturnLength(CPDF_FileSpec(pFile).GetFileName(),
46 buffer, buflen);
47}
Jane Liu53aafa92017-07-12 19:55:02 -040048
Jane Liu18ae06d2017-07-18 10:15:16 -040049DLLEXPORT FPDF_BOOL STDCALL FPDFAttachment_HasKey(FPDF_ATTACHMENT attachment,
50 FPDF_WIDESTRING key) {
51 CPDF_Object* pFile = CPDFObjectFromFPDFAttachment(attachment);
52 if (!pFile)
53 return 0;
54
55 CPDF_Dictionary* pParamsDict = CPDF_FileSpec(pFile).GetParamsDict();
56 if (!pParamsDict)
57 return 0;
58
59 return pParamsDict->KeyExist(CFXByteStringFromFPDFWideString(key));
60}
61
62DLLEXPORT FPDF_OBJECT_TYPE STDCALL
63FPDFAttachment_GetValueType(FPDF_ATTACHMENT attachment, FPDF_WIDESTRING key) {
64 if (!FPDFAttachment_HasKey(attachment, key))
65 return FPDF_OBJECT_UNKNOWN;
66
67 CPDF_Object* pObj = CPDF_FileSpec(CPDFObjectFromFPDFAttachment(attachment))
68 .GetParamsDict()
69 ->GetObjectFor(CFXByteStringFromFPDFWideString(key));
70 if (!pObj)
71 return FPDF_OBJECT_UNKNOWN;
72
73 return pObj->GetType();
74}
75
76DLLEXPORT unsigned long STDCALL
77FPDFAttachment_GetStringValue(FPDF_ATTACHMENT attachment,
78 FPDF_WIDESTRING key,
79 void* buffer,
80 unsigned long buflen) {
81 CPDF_Object* pFile = CPDFObjectFromFPDFAttachment(attachment);
82 if (!pFile)
83 return 0;
84
85 CPDF_Dictionary* pParamsDict = CPDF_FileSpec(pFile).GetParamsDict();
86 if (!pParamsDict)
87 return 0;
88
89 CFX_ByteString bsKey = CFXByteStringFromFPDFWideString(key);
90 CFX_WideString value = pParamsDict->GetUnicodeTextFor(bsKey);
91 if (bsKey == "CheckSum") {
92 CPDF_String* stringValue = pParamsDict->GetObjectFor(bsKey)->AsString();
93 if (stringValue->IsHex()) {
94 value =
95 CPDF_String(nullptr, PDF_EncodeString(stringValue->GetString(), true),
96 false)
97 .GetUnicodeText();
98 }
99 }
100
101 return Utf16EncodeMaybeCopyAndReturnLength(value, buffer, buflen);
102}
103
104DLLEXPORT unsigned long STDCALL
105FPDFAttachment_GetFile(FPDF_ATTACHMENT attachment,
106 void* buffer,
107 unsigned long buflen) {
108 CPDF_Object* pFile = CPDFObjectFromFPDFAttachment(attachment);
109 if (!pFile)
110 return 0;
111
112 CPDF_Stream* pFileStream = CPDF_FileSpec(pFile).GetFileStream();
113 if (!pFileStream)
114 return 0;
115
116 uint8_t* data = pFileStream->GetRawData();
117 uint32_t len = pFileStream->GetRawSize();
118 CPDF_Dictionary* pFileDict = pFileStream->GetDict();
119 if (!pFileDict || pFileDict->GetStringFor("Filter").IsEmpty()) {
120 if (buffer && buflen >= len)
121 memcpy(buffer, data, len);
122
123 return len;
124 }
125
126 // Decode the stream if a stream filter is specified.
127 uint8_t* decodedData = nullptr;
128 uint32_t decodedLen = 0;
129 CPDF_StreamParser::DecodeInlineStream(
130 data, len, pFileDict->GetIntegerFor("Width"),
131 pFileDict->GetIntegerFor("Height"), pFileDict->GetStringFor("Filter"),
132 pFileDict->GetDictFor("DecodeParms"), &decodedData, &decodedLen);
133 if (buffer && buflen >= decodedLen)
134 memcpy(buffer, decodedData, decodedLen);
135
136 FX_Free(decodedData);
137 return decodedLen;
Jane Liu53aafa92017-07-12 19:55:02 -0400138}