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