1 /*
2  * Copyright (C) 2009-2011, Pino Toscano <pino@kde.org>
3  * Copyright (C) 2016 Jakub Alba <jakubalba@gmail.com>
4  * Copyright (C) 2018, 2020 Albert Astals Cid <aacid@kde.org>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2, or (at your option)
9  * any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
19  */
20 
21 /**
22  \file poppler-embedded-file.h
23  */
24 #include "poppler-embedded-file.h"
25 
26 #include "poppler-embedded-file-private.h"
27 #include "poppler-private.h"
28 
29 #include "Object.h"
30 #include "Stream.h"
31 #include "Catalog.h"
32 #include "FileSpec.h"
33 #include "DateInfo.h"
34 
35 using namespace poppler;
36 
embedded_file_private(FileSpec * fs)37 embedded_file_private::embedded_file_private(FileSpec *fs) : file_spec(fs) { }
38 
~embedded_file_private()39 embedded_file_private::~embedded_file_private()
40 {
41     delete file_spec;
42 }
43 
create(FileSpec * fs)44 embedded_file *embedded_file_private::create(FileSpec *fs)
45 {
46     return new embedded_file(*new embedded_file_private(fs));
47 }
48 
49 /**
50  \class poppler::embedded_file poppler-embedded-file.h "poppler/cpp/poppler-embedded-file.h"
51 
52  Represents a file embedded in a PDF %document.
53  */
54 
embedded_file(embedded_file_private & dd)55 embedded_file::embedded_file(embedded_file_private &dd) : d(&dd) { }
56 
57 /**
58  Destroys the embedded file.
59  */
~embedded_file()60 embedded_file::~embedded_file()
61 {
62     delete d;
63 }
64 
65 /**
66  \returns whether the embedded file is valid
67  */
is_valid() const68 bool embedded_file::is_valid() const
69 {
70     return d->file_spec->isOk();
71 }
72 
73 /**
74  \returns the name of the embedded file
75  */
name() const76 std::string embedded_file::name() const
77 {
78     const GooString *goo = d->file_spec->getFileName();
79     return goo ? std::string(goo->c_str()) : std::string();
80 }
81 
82 /**
83  \returns the description of the embedded file
84  */
description() const85 ustring embedded_file::description() const
86 {
87     const GooString *goo = d->file_spec->getDescription();
88     return goo ? detail::unicode_GooString_to_ustring(goo) : ustring();
89 }
90 
91 /**
92  \note this is not always available in the PDF %document, in that case this
93        will return \p -1.
94 
95  \returns the size of the embedded file, if known
96  */
size() const97 int embedded_file::size() const
98 {
99     const EmbFile *ef = d->file_spec->getEmbeddedFile();
100     return ef ? ef->size() : -1;
101 }
102 
103 /**
104  \returns the time_t representing the modification date of the embedded file,
105           if available
106  */
modification_date() const107 time_type embedded_file::modification_date() const
108 {
109     const EmbFile *ef = d->file_spec->getEmbeddedFile();
110     const GooString *goo = ef ? ef->modDate() : nullptr;
111     return goo ? dateStringToTime(goo) : time_type(-1);
112 }
113 
114 /**
115  \returns the time_t representing the creation date of the embedded file,
116           if available
117  */
creation_date() const118 time_type embedded_file::creation_date() const
119 {
120     const EmbFile *ef = d->file_spec->getEmbeddedFile();
121     const GooString *goo = ef ? ef->createDate() : nullptr;
122     return goo ? dateStringToTime(goo) : time_type(-1);
123 }
124 
125 /**
126  \returns the checksum of the embedded file
127  */
checksum() const128 byte_array embedded_file::checksum() const
129 {
130     const EmbFile *ef = d->file_spec->getEmbeddedFile();
131     const GooString *cs = ef ? ef->checksum() : nullptr;
132     if (!cs) {
133         return byte_array();
134     }
135     const char *ccs = cs->c_str();
136     byte_array data(cs->getLength());
137     for (int i = 0; i < cs->getLength(); ++i) {
138         data[i] = ccs[i];
139     }
140     return data;
141 }
142 
143 /**
144  \returns the MIME type of the embedded file, if available
145  */
mime_type() const146 std::string embedded_file::mime_type() const
147 {
148     const EmbFile *ef = d->file_spec->getEmbeddedFile();
149     const GooString *goo = ef ? ef->mimeType() : nullptr;
150     return goo ? std::string(goo->c_str()) : std::string();
151 }
152 
153 /**
154  Reads all the data of the embedded file.
155 
156  \returns the data of the embedded file
157  */
data() const158 byte_array embedded_file::data() const
159 {
160     if (!is_valid()) {
161         return byte_array();
162     }
163     EmbFile *ef = d->file_spec->getEmbeddedFile();
164     Stream *stream = ef ? ef->stream() : nullptr;
165     if (!stream) {
166         return byte_array();
167     }
168 
169     stream->reset();
170     byte_array ret(1024);
171     size_t data_len = 0;
172     int i;
173     while ((i = stream->getChar()) != EOF) {
174         if (data_len == ret.size()) {
175             ret.resize(ret.size() * 2);
176         }
177         ret[data_len] = (char)i;
178         ++data_len;
179     }
180     ret.resize(data_len);
181     return ret;
182 }
183