Coverage Report

Created: 2025-07-12 07:23

/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
}