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
48namespace {
49
50struct MiniIconv
51{
52 MiniIconv(const char *to_code, const char *from_code) : i_(iconv_open(tocode: to_code, fromcode: from_code)) { }
53 ~MiniIconv()
54 {
55 if (is_valid()) {
56 iconv_close(cd: i_);
57 }
58 }
59 MiniIconv(const MiniIconv &) = delete;
60 MiniIconv &operator=(const MiniIconv &) = delete;
61 bool is_valid() const { return i_ != (iconv_t)-1; }
62 explicit operator iconv_t() const { return i_; }
63 iconv_t i_;
64};
65
66}
67
68using namespace poppler;
69
70/**
71 \namespace poppler
72
73 Single namespace containing all the classes and functions of poppler-cpp.
74 */
75
76/**
77 \class poppler::noncopyable
78
79 A class that cannot be copied.
80 */
81
82/**
83 \enum poppler::rotation_enum
84
85 The case sensitivity.
86*/
87/**
88 \var poppler::rotation_enum poppler::rotate_0
89
90 A rotation of 0 degrees clockwise.
91*/
92/**
93 \var poppler::rotation_enum poppler::rotate_90
94
95 A rotation of 90 degrees clockwise.
96*/
97/**
98 \var poppler::rotation_enum poppler::rotate_180
99
100 A rotation of 180 degrees clockwise.
101*/
102/**
103 \var poppler::rotation_enum poppler::rotate_270
104
105 A rotation of 270 degrees clockwise.
106*/
107
108/**
109 \enum poppler::page_box_enum
110
111 A possible box of a page in a PDF %document.
112*/
113/**
114 \var poppler::page_box_enum poppler::media_box
115
116 The "media" box.
117*/
118/**
119 \var poppler::page_box_enum poppler::crop_box
120
121 The "crop" box.
122*/
123/**
124 \var poppler::page_box_enum poppler::bleed_box
125
126 The "bleed" box.
127*/
128/**
129 \var poppler::page_box_enum poppler::trim_box
130
131 The "trim" box.
132*/
133/**
134 \var poppler::page_box_enum poppler::art_box
135
136 The "art" box.
137*/
138
139/**
140 \enum poppler::permission_enum
141
142 A possible permission in a PDF %document.
143*/
144/**
145 \var poppler::permission_enum poppler::perm_print
146
147 The permission to allow the print of a %document.
148*/
149/**
150 \var poppler::permission_enum poppler::perm_change
151
152 The permission to change a %document.
153
154 This is a generic "change" permission, so other permissions could affect
155 some types of changes.
156*/
157/**
158 \var poppler::permission_enum poppler::perm_copy
159
160 The permission to allow the copy or extraction of the text in a %document.
161*/
162/**
163 \var poppler::permission_enum poppler::perm_add_notes
164
165 The permission to allow the addition or editing of annotations,
166 and the filling of interactive form fields (including signature fields).
167*/
168/**
169 \var poppler::permission_enum poppler::perm_fill_forms
170
171 The permission to allow the filling of interactive form fields
172 (including signature fields).
173
174 \note this permission can be set even when the \ref poppler::perm_add_notes "perm_add_notes"
175 is not: this means that only the filling of forms is allowed.
176*/
177/**
178 \var poppler::permission_enum poppler::perm_accessibility
179
180 The permission to allow the extracting of content (for example, text) for
181 accessibility usage (e.g. for a screen reader).
182*/
183/**
184 \var poppler::permission_enum poppler::perm_assemble
185
186 The permission to allow to "assemble" a %document.
187
188 This implies operations such as the insertion, the rotation and the deletion
189 of pages; the creation of bookmarks and thumbnail images.
190
191 \note this permission can be set even when the \ref poppler::perm_change "perm_change"
192 is not
193*/
194/**
195 \var poppler::permission_enum poppler::perm_print_high_resolution
196
197 The permission to allow the high resolution print of a %document.
198*/
199
200/**
201 \enum poppler::case_sensitivity_enum
202
203 The case sensitivity.
204*/
205
206noncopyable::noncopyable() { }
207
208noncopyable::~noncopyable() { }
209
210noncopyable &noncopyable::operator=(noncopyable &&other) noexcept = default;
211
212ustring::ustring() { }
213
214ustring::ustring(size_type len, value_type ch) : std::basic_string<value_type>(len, ch) { }
215
216ustring::~ustring() { }
217
218byte_array ustring::to_utf8() const
219{
220 if (!size()) {
221 return byte_array();
222 }
223
224#ifdef WORDS_BIGENDIAN
225 MiniIconv ic("UTF-8", "UTF-16BE");
226#else
227 MiniIconv ic("UTF-8", "UTF-16LE");
228#endif
229 if (!ic.is_valid()) {
230 return byte_array();
231 }
232 const value_type *me_data = data();
233 byte_array str(size() * sizeof(value_type));
234 char *str_data = &str[0];
235 size_t me_len_char = size() * sizeof(value_type);
236 size_t str_len_left = str.size();
237 size_t ir = iconv(cd: static_cast<iconv_t>(ic), inbuf: (ICONV_CONST char **)&me_data, inbytesleft: &me_len_char, outbuf: &str_data, outbytesleft: &str_len_left);
238 if ((ir == (size_t)-1) && (errno == E2BIG)) {
239 const size_t delta = str_data - &str[0];
240 str_len_left += str.size();
241 str.resize(new_size: str.size() * 2);
242 str_data = &str[delta];
243 ir = iconv(cd: static_cast<iconv_t>(ic), inbuf: (ICONV_CONST char **)&me_data, inbytesleft: &me_len_char, outbuf: &str_data, outbytesleft: &str_len_left);
244 if (ir == (size_t)-1) {
245 return byte_array();
246 }
247 }
248 str.resize(new_size: str.size() - str_len_left);
249 return str;
250}
251
252std::string ustring::to_latin1() const
253{
254 if (!size()) {
255 return std::string();
256 }
257
258 const size_type mylength = size();
259 std::string ret(mylength, '\0');
260 const value_type *me = data();
261 for (size_type i = 0; i < mylength; ++i) {
262 ret[i] = (char)*me++;
263 }
264 return ret;
265}
266
267ustring ustring::from_utf8(const char *str, int len)
268{
269 if (len <= 0) {
270 len = std::strlen(s: str);
271 if (len <= 0) {
272 return ustring();
273 }
274 }
275
276#ifdef WORDS_BIGENDIAN
277 MiniIconv ic("UTF-16BE", "UTF-8");
278#else
279 MiniIconv ic("UTF-16LE", "UTF-8");
280#endif
281 if (!ic.is_valid()) {
282 return ustring();
283 }
284
285 // +1, because iconv inserts byte order marks
286 ustring ret(len + 1, 0);
287 char *ret_data = reinterpret_cast<char *>(&ret[0]);
288 char *str_data = const_cast<char *>(str);
289 size_t str_len_char = len;
290 size_t ret_len_left = ret.size() * sizeof(ustring::value_type);
291 size_t ir = iconv(cd: static_cast<iconv_t>(ic), inbuf: (ICONV_CONST char **)&str_data, inbytesleft: &str_len_char, outbuf: &ret_data, outbytesleft: &ret_len_left);
292 if ((ir == (size_t)-1) && (errno == E2BIG)) {
293 const size_t delta = ret_data - reinterpret_cast<char *>(&ret[0]);
294 ret_len_left += ret.size() * sizeof(ustring::value_type);
295 ret.resize(n: ret.size() * 2);
296 ret_data = reinterpret_cast<char *>(&ret[0]) + delta;
297 ir = iconv(cd: static_cast<iconv_t>(ic), inbuf: (ICONV_CONST char **)&str_data, inbytesleft: &str_len_char, outbuf: &ret_data, outbytesleft: &ret_len_left);
298 if (ir == (size_t)-1) {
299 return ustring();
300 }
301 }
302 ret.resize(n: ret.size() - ret_len_left / sizeof(ustring::value_type));
303
304 return ret;
305}
306
307ustring ustring::from_latin1(const std::string &str)
308{
309 const size_type l = str.size();
310 if (!l) {
311 return ustring();
312 }
313 const char *c = str.data();
314 ustring ret(l, 0);
315 for (size_type i = 0; i < l; ++i) {
316 ret[i] = static_cast<unsigned char>(*c);
317 c++;
318 }
319 return ret;
320}
321
322/**
323 Converts a string representing a PDF date to a value compatible with time_type.
324 */
325time_type poppler::convert_date(const std::string &date)
326{
327 GooString gooDateStr(date.c_str());
328 return static_cast<time_type>(dateStringToTime(dateString: &gooDateStr));
329}
330
331/**
332 Converts a string representing a PDF date to a value compatible with time_t.
333 */
334time_t poppler::convert_date_t(const std::string &date)
335{
336 GooString gooDateStr(date.c_str());
337 return dateStringToTime(dateString: &gooDateStr);
338}
339
340std::ostream &poppler::operator<<(std::ostream &stream, const byte_array &array)
341{
342 stream << "[";
343 const std::ios_base::fmtflags f = stream.flags();
344 std::hex(base&: stream);
345 const char *data = &array[0];
346 const byte_array::size_type out_len = std::min<byte_array::size_type>(a: array.size(), b: 50);
347 for (byte_array::size_type i = 0; i < out_len; ++i) {
348 if (i != 0) {
349 stream << " ";
350 }
351 stream << ((data[i] & 0xf0) >> 4) << (data[i] & 0xf);
352 }
353 stream.flags(fmtfl: f);
354 if (out_len < array.size()) {
355 stream << " ...";
356 }
357 stream << "]";
358 return stream;
359}
360
361/**
362 * Sets a custom data directory for initialization of global parameters
363 *
364 * If no instances of \see document currently exist, this will save the
365 * given path as a custom data directory to be used when the first instance
366 * of the \see document is constructed.
367 *
368 * \returns true on success, false on failure
369 *
370 * \since 0.73.0
371 */
372bool poppler::set_data_dir(const std::string &new_data_dir)
373{
374 return GlobalParamsIniter::setCustomDataDir(new_data_dir);
375}
376
377/**
378 \typedef poppler::debug_func
379
380 Debug/error function.
381
382 This function type is used for debugging & error output;
383 the first parameter is the actual message, the second is the unaltered
384 closure argument which was passed to the set_debug_error_function() call.
385
386 \since 0.30.0
387 */
388
389/**
390 Set a new debug/error output function.
391
392 If not set, by default error and debug messages will be sent to stderr.
393
394 \param debug_function the new debug function
395 \param closure user data which will be passed as-is to the debug function
396
397 \since 0.30.0
398 */
399void poppler::set_debug_error_function(debug_func debug_function, void *closure)
400{
401 poppler::detail::user_debug_function = debug_function;
402 poppler::detail::debug_closure = closure;
403}
404

source code of poppler/cpp/poppler-global.cpp