/src/poppler/cpp/poppler-global.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (C) 2009-2010, Pino Toscano <pino@kde.org> |
3 | | * Copyright (C) 2010, Hib Eris <hib@hiberis.nl> |
4 | | * Copyright (C) 2014, 2015 Hans-Peter Deifel <hpdeifel@gmx.de> |
5 | | * Copyright (C) 2015, Tamas Szekeres <szekerest@gmail.com> |
6 | | * Copyright (C) 2016 Jakub Alba <jakubalba@gmail.com> |
7 | | * Copyright (C) 2018, 2020-2022, Albert Astals Cid <aacid@kde.org> |
8 | | * Copyright (C) 2018 Suzuki Toshiya <mpsuzuki@hiroshima-u.ac.jp> |
9 | | * Copyright (C) 2018, 2020, Adam Reichold <adam.reichold@t-online.de> |
10 | | * Copyright (C) 2022, Oliver Sander <oliver.sander@tu-dresden.de> |
11 | | * |
12 | | * This program is free software; you can redistribute it and/or modify |
13 | | * it under the terms of the GNU General Public License as published by |
14 | | * the Free Software Foundation; either version 2, or (at your option) |
15 | | * any later version. |
16 | | * |
17 | | * This program is distributed in the hope that it will be useful, |
18 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
19 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
20 | | * GNU General Public License for more details. |
21 | | * |
22 | | * You should have received a copy of the GNU General Public License |
23 | | * along with this program; if not, write to the Free Software |
24 | | * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. |
25 | | */ |
26 | | |
27 | | /** |
28 | | \file poppler-global.h |
29 | | */ |
30 | | #include "poppler-global.h" |
31 | | |
32 | | #include "poppler-private.h" |
33 | | #include "poppler-document-private.h" |
34 | | |
35 | | #include "DateInfo.h" |
36 | | |
37 | | #include <algorithm> |
38 | | |
39 | | #include <cerrno> |
40 | | #include <cstring> |
41 | | #include <ios> |
42 | | #include <iostream> |
43 | | |
44 | | #include <iconv.h> |
45 | | |
46 | | #include "config.h" |
47 | | |
48 | | namespace { |
49 | | |
50 | | struct MiniIconv |
51 | | { |
52 | 1.54M | MiniIconv(const char *to_code, const char *from_code) : i_(iconv_open(to_code, from_code)) { } |
53 | | ~MiniIconv() |
54 | 1.54M | { |
55 | 1.54M | if (is_valid()) { |
56 | 1.54M | iconv_close(i_); |
57 | 1.54M | } |
58 | 1.54M | } |
59 | | MiniIconv(const MiniIconv &) = delete; |
60 | | MiniIconv &operator=(const MiniIconv &) = delete; |
61 | | bool is_valid() const |
62 | 3.08M | { |
63 | 3.08M | return i_ != (iconv_t)-1; // NOLINT(performance-no-int-to-ptr) |
64 | 3.08M | } |
65 | 1.54M | explicit operator iconv_t() const { return i_; } |
66 | | iconv_t i_; |
67 | | }; |
68 | | |
69 | | } |
70 | | |
71 | | using namespace poppler; |
72 | | |
73 | | /** |
74 | | \namespace poppler |
75 | | |
76 | | Single namespace containing all the classes and functions of poppler-cpp. |
77 | | */ |
78 | | |
79 | | /** |
80 | | \class poppler::noncopyable |
81 | | |
82 | | A class that cannot be copied. |
83 | | */ |
84 | | |
85 | | /** |
86 | | \enum poppler::rotation_enum |
87 | | |
88 | | The case sensitivity. |
89 | | */ |
90 | | /** |
91 | | \var poppler::rotation_enum poppler::rotate_0 |
92 | | |
93 | | A rotation of 0 degrees clockwise. |
94 | | */ |
95 | | /** |
96 | | \var poppler::rotation_enum poppler::rotate_90 |
97 | | |
98 | | A rotation of 90 degrees clockwise. |
99 | | */ |
100 | | /** |
101 | | \var poppler::rotation_enum poppler::rotate_180 |
102 | | |
103 | | A rotation of 180 degrees clockwise. |
104 | | */ |
105 | | /** |
106 | | \var poppler::rotation_enum poppler::rotate_270 |
107 | | |
108 | | A rotation of 270 degrees clockwise. |
109 | | */ |
110 | | |
111 | | /** |
112 | | \enum poppler::page_box_enum |
113 | | |
114 | | A possible box of a page in a PDF %document. |
115 | | */ |
116 | | /** |
117 | | \var poppler::page_box_enum poppler::media_box |
118 | | |
119 | | The "media" box. |
120 | | */ |
121 | | /** |
122 | | \var poppler::page_box_enum poppler::crop_box |
123 | | |
124 | | The "crop" box. |
125 | | */ |
126 | | /** |
127 | | \var poppler::page_box_enum poppler::bleed_box |
128 | | |
129 | | The "bleed" box. |
130 | | */ |
131 | | /** |
132 | | \var poppler::page_box_enum poppler::trim_box |
133 | | |
134 | | The "trim" box. |
135 | | */ |
136 | | /** |
137 | | \var poppler::page_box_enum poppler::art_box |
138 | | |
139 | | The "art" box. |
140 | | */ |
141 | | |
142 | | /** |
143 | | \enum poppler::permission_enum |
144 | | |
145 | | A possible permission in a PDF %document. |
146 | | */ |
147 | | /** |
148 | | \var poppler::permission_enum poppler::perm_print |
149 | | |
150 | | The permission to allow the print of a %document. |
151 | | */ |
152 | | /** |
153 | | \var poppler::permission_enum poppler::perm_change |
154 | | |
155 | | The permission to change a %document. |
156 | | |
157 | | This is a generic "change" permission, so other permissions could affect |
158 | | some types of changes. |
159 | | */ |
160 | | /** |
161 | | \var poppler::permission_enum poppler::perm_copy |
162 | | |
163 | | The permission to allow the copy or extraction of the text in a %document. |
164 | | */ |
165 | | /** |
166 | | \var poppler::permission_enum poppler::perm_add_notes |
167 | | |
168 | | The permission to allow the addition or editing of annotations, |
169 | | and the filling of interactive form fields (including signature fields). |
170 | | */ |
171 | | /** |
172 | | \var poppler::permission_enum poppler::perm_fill_forms |
173 | | |
174 | | The permission to allow the filling of interactive form fields |
175 | | (including signature fields). |
176 | | |
177 | | \note this permission can be set even when the \ref poppler::perm_add_notes "perm_add_notes" |
178 | | is not: this means that only the filling of forms is allowed. |
179 | | */ |
180 | | /** |
181 | | \var poppler::permission_enum poppler::perm_accessibility |
182 | | |
183 | | The permission to allow the extracting of content (for example, text) for |
184 | | accessibility usage (e.g. for a screen reader). |
185 | | */ |
186 | | /** |
187 | | \var poppler::permission_enum poppler::perm_assemble |
188 | | |
189 | | The permission to allow to "assemble" a %document. |
190 | | |
191 | | This implies operations such as the insertion, the rotation and the deletion |
192 | | of pages; the creation of bookmarks and thumbnail images. |
193 | | |
194 | | \note this permission can be set even when the \ref poppler::perm_change "perm_change" |
195 | | is not |
196 | | */ |
197 | | /** |
198 | | \var poppler::permission_enum poppler::perm_print_high_resolution |
199 | | |
200 | | The permission to allow the high resolution print of a %document. |
201 | | */ |
202 | | |
203 | | /** |
204 | | \enum poppler::case_sensitivity_enum |
205 | | |
206 | | The case sensitivity. |
207 | | */ |
208 | | |
209 | 286k | noncopyable::noncopyable() = default; |
210 | | |
211 | 1.09k | noncopyable &noncopyable::operator=(noncopyable &&other) noexcept = default; |
212 | | |
213 | 32.1k | ustring::ustring() = default; |
214 | | |
215 | 1.58M | ustring::ustring(size_type len, value_type ch) : std::basic_string<value_type>(len, ch) { } |
216 | | |
217 | 4.63M | ustring::~ustring() = default; |
218 | | |
219 | | byte_array ustring::to_utf8() const |
220 | 0 | { |
221 | 0 | if (empty()) { |
222 | 0 | return byte_array(); |
223 | 0 | } |
224 | | |
225 | | #ifdef WORDS_BIGENDIAN |
226 | | MiniIconv ic("UTF-8", "UTF-16BE"); |
227 | | #else |
228 | 0 | MiniIconv ic("UTF-8", "UTF-16LE"); |
229 | 0 | #endif |
230 | 0 | if (!ic.is_valid()) { |
231 | 0 | return byte_array(); |
232 | 0 | } |
233 | 0 | const value_type *me_data = data(); |
234 | 0 | byte_array str(size() * sizeof(value_type)); |
235 | 0 | char *str_data = &str[0]; |
236 | 0 | size_t me_len_char = size() * sizeof(value_type); |
237 | 0 | size_t str_len_left = str.size(); |
238 | 0 | size_t ir = iconv(static_cast<iconv_t>(ic), (ICONV_CONST char **)&me_data, &me_len_char, &str_data, &str_len_left); |
239 | 0 | if ((ir == (size_t)-1) && (errno == E2BIG)) { |
240 | 0 | const size_t delta = str_data - &str[0]; |
241 | 0 | str_len_left += str.size(); |
242 | 0 | str.resize(str.size() * 2); |
243 | 0 | str_data = &str[delta]; |
244 | 0 | ir = iconv(static_cast<iconv_t>(ic), (ICONV_CONST char **)&me_data, &me_len_char, &str_data, &str_len_left); |
245 | 0 | if (ir == (size_t)-1) { |
246 | 0 | return byte_array(); |
247 | 0 | } |
248 | 0 | } |
249 | 0 | str.resize(str.size() - str_len_left); |
250 | 0 | return str; |
251 | 0 | } |
252 | | |
253 | | std::string ustring::to_latin1() const |
254 | 0 | { |
255 | 0 | if (empty()) { |
256 | 0 | return std::string(); |
257 | 0 | } |
258 | | |
259 | 0 | const size_type mylength = size(); |
260 | 0 | std::string ret(mylength, '\0'); |
261 | 0 | const value_type *me = data(); |
262 | 0 | for (size_type i = 0; i < mylength; ++i) { |
263 | 0 | ret[i] = (char)*me++; |
264 | 0 | } |
265 | 0 | return ret; |
266 | 0 | } |
267 | | |
268 | | ustring ustring::from_utf8(const char *str, int len) |
269 | 1.56M | { |
270 | 1.56M | if (len <= 0) { |
271 | 1.56M | len = std::strlen(str); |
272 | 1.56M | if (len <= 0) { |
273 | 19.0k | return ustring(); |
274 | 19.0k | } |
275 | 1.56M | } |
276 | | |
277 | | #ifdef WORDS_BIGENDIAN |
278 | | MiniIconv ic("UTF-16BE", "UTF-8"); |
279 | | #else |
280 | 1.54M | MiniIconv ic("UTF-16LE", "UTF-8"); |
281 | 1.54M | #endif |
282 | 1.54M | if (!ic.is_valid()) { |
283 | 0 | return ustring(); |
284 | 0 | } |
285 | | |
286 | | // +1, because iconv inserts byte order marks |
287 | 1.54M | ustring ret(len + 1, 0); |
288 | 1.54M | char *ret_data = reinterpret_cast<char *>(&ret[0]); |
289 | 1.54M | char *str_data = const_cast<char *>(str); |
290 | 1.54M | size_t str_len_char = len; |
291 | 1.54M | size_t ret_len_left = ret.size() * sizeof(ustring::value_type); |
292 | 1.54M | size_t ir = iconv(static_cast<iconv_t>(ic), (ICONV_CONST char **)&str_data, &str_len_char, &ret_data, &ret_len_left); |
293 | 1.54M | if ((ir == (size_t)-1) && (errno == E2BIG)) { |
294 | 0 | const size_t delta = ret_data - reinterpret_cast<char *>(&ret[0]); |
295 | 0 | ret_len_left += ret.size() * sizeof(ustring::value_type); |
296 | 0 | ret.resize(ret.size() * 2); |
297 | 0 | ret_data = reinterpret_cast<char *>(&ret[0]) + delta; |
298 | 0 | ir = iconv(static_cast<iconv_t>(ic), (ICONV_CONST char **)&str_data, &str_len_char, &ret_data, &ret_len_left); |
299 | 0 | if (ir == (size_t)-1) { |
300 | 0 | return ustring(); |
301 | 0 | } |
302 | 0 | } |
303 | 1.54M | ret.resize(ret.size() - ret_len_left / sizeof(ustring::value_type)); |
304 | | |
305 | 1.54M | return ret; |
306 | 1.54M | } |
307 | | |
308 | | ustring ustring::from_latin1(const std::string &str) |
309 | 7.38k | { |
310 | 7.38k | const size_type l = str.size(); |
311 | 7.38k | if (!l) { |
312 | 0 | return ustring(); |
313 | 0 | } |
314 | 7.38k | const char *c = str.data(); |
315 | 7.38k | ustring ret(l, 0); |
316 | 243k | for (size_type i = 0; i < l; ++i) { |
317 | 236k | ret[i] = static_cast<unsigned char>(*c); |
318 | 236k | c++; |
319 | 236k | } |
320 | 7.38k | return ret; |
321 | 7.38k | } |
322 | | |
323 | | /** |
324 | | Converts a string representing a PDF date to a value compatible with time_type. |
325 | | */ |
326 | | time_type poppler::convert_date(const std::string &date) |
327 | 0 | { |
328 | 0 | GooString gooDateStr(date.c_str()); |
329 | 0 | return static_cast<time_type>(dateStringToTime(&gooDateStr)); |
330 | 0 | } |
331 | | |
332 | | /** |
333 | | Converts a string representing a PDF date to a value compatible with time_t. |
334 | | */ |
335 | | time_t poppler::convert_date_t(const std::string &date) |
336 | 0 | { |
337 | 0 | GooString gooDateStr(date.c_str()); |
338 | 0 | return dateStringToTime(&gooDateStr); |
339 | 0 | } |
340 | | |
341 | | std::ostream &poppler::operator<<(std::ostream &stream, const byte_array &array) |
342 | 0 | { |
343 | 0 | stream << "["; |
344 | 0 | const std::ios_base::fmtflags f = stream.flags(); |
345 | 0 | std::hex(stream); |
346 | 0 | const char *data = &array[0]; |
347 | 0 | const byte_array::size_type out_len = std::min<byte_array::size_type>(array.size(), 50); |
348 | 0 | for (byte_array::size_type i = 0; i < out_len; ++i) { |
349 | 0 | if (i != 0) { |
350 | 0 | stream << " "; |
351 | 0 | } |
352 | 0 | stream << ((data[i] & 0xf0) >> 4) << (data[i] & 0xf); |
353 | 0 | } |
354 | 0 | stream.flags(f); |
355 | 0 | if (out_len < array.size()) { |
356 | 0 | stream << " ..."; |
357 | 0 | } |
358 | 0 | stream << "]"; |
359 | 0 | return stream; |
360 | 0 | } |
361 | | |
362 | | /** |
363 | | * Sets a custom data directory for initialization of global parameters |
364 | | * |
365 | | * If no instances of \see document currently exist, this will save the |
366 | | * given path as a custom data directory to be used when the first instance |
367 | | * of the \see document is constructed. |
368 | | * |
369 | | * \returns true on success, false on failure |
370 | | * |
371 | | * \since 0.73.0 |
372 | | */ |
373 | | bool poppler::set_data_dir(const std::string &new_data_dir) |
374 | 0 | { |
375 | 0 | return GlobalParamsIniter::setCustomDataDir(new_data_dir); |
376 | 0 | } |
377 | | |
378 | | /** |
379 | | \typedef poppler::debug_func |
380 | | |
381 | | Debug/error function. |
382 | | |
383 | | This function type is used for debugging & error output; |
384 | | the first parameter is the actual message, the second is the unaltered |
385 | | closure argument which was passed to the set_debug_error_function() call. |
386 | | |
387 | | \since 0.30.0 |
388 | | */ |
389 | | |
390 | | /** |
391 | | Set a new debug/error output function. |
392 | | |
393 | | If not set, by default error and debug messages will be sent to stderr. |
394 | | |
395 | | \param debug_function the new debug function |
396 | | \param closure user data which will be passed as-is to the debug function |
397 | | |
398 | | \since 0.30.0 |
399 | | */ |
400 | | void poppler::set_debug_error_function(debug_func debug_function, void *closure) |
401 | 43.8k | { |
402 | 43.8k | poppler::detail::user_debug_function = debug_function; |
403 | 43.8k | poppler::detail::debug_closure = closure; |
404 | 43.8k | } |