Coverage Report

Created: 2026-09-28 08:21

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}