Coverage Report

Created: 2026-09-14 06:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/qpdf/include/qpdf/QPDFObjectHandle.hh
Line
Count
Source
1
// Copyright (c) 2005-2021 Jay Berkenbilt
2
// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger
3
//
4
// This file is part of qpdf.
5
//
6
// Licensed under the Apache License, Version 2.0 (the "License");
7
// you may not use this file except in compliance with the License.
8
// You may obtain a copy of the License at
9
//
10
//   http://www.apache.org/licenses/LICENSE-2.0
11
//
12
// Unless required by applicable law or agreed to in writing, software
13
// distributed under the License is distributed on an "AS IS" BASIS,
14
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
// See the License for the specific language governing permissions and
16
// limitations under the License.
17
//
18
// Versions of qpdf prior to version 7 were released under the terms
19
// of version 2.0 of the Artistic License. At your option, you may
20
// continue to consider qpdf to be licensed under those terms. Please
21
// see the manual for additional information.
22
23
#ifndef QPDFOBJECTHANDLE_HH
24
#define QPDFOBJECTHANDLE_HH
25
26
#include <qpdf/ObjectHandle.hh>
27
28
#include <qpdf/Constants.h>
29
#include <qpdf/DLL.h>
30
#include <qpdf/Types.h>
31
32
#include <cinttypes>
33
#include <functional>
34
#include <map>
35
#include <memory>
36
#include <set>
37
#include <string>
38
#include <vector>
39
40
#include <qpdf/Buffer.hh>
41
#include <qpdf/InputSource.hh>
42
#include <qpdf/JSON.hh>
43
#include <qpdf/QPDFObjGen.hh>
44
#include <qpdf/QPDFTokenizer.hh>
45
46
class Pipeline;
47
class QPDF_Array;
48
class QPDF_Bool;
49
class QPDF_Dictionary;
50
class QPDF_InlineImage;
51
class QPDF_Integer;
52
class QPDF_Name;
53
class QPDF_Null;
54
class QPDF_Operator;
55
class QPDF_Real;
56
class QPDF_Reserved;
57
class QPDF_Stream;
58
class QPDF_String;
59
class QPDFObject;
60
class QPDFObjectHandle;
61
class QPDFTokenizer;
62
class QPDFExc;
63
class Pl_QPDFTokenizer;
64
class QPDFMatrix;
65
namespace qpdf::impl
66
{
67
    class Parser;
68
}
69
70
class QPDFObjectHandle: public qpdf::BaseHandle
71
{
72
    friend class qpdf::impl::Parser;
73
74
  public:
75
    // This class is used by replaceStreamData.  It provides an alternative way of associating
76
    // stream data with a stream.  See comments on replaceStreamData and newStream for additional
77
    // details.
78
    class QPDF_DLL_CLASS StreamDataProvider
79
    {
80
      public:
81
        QPDF_DLL
82
        StreamDataProvider(bool supports_retry = false);
83
84
        QPDF_DLL
85
        virtual ~StreamDataProvider();
86
        // The implementation of this function must write stream data to the given pipeline. The
87
        // stream data must conform to whatever filters are explicitly associated with the stream.
88
        // QPDFWriter may, in some cases, add compression, but if it does, it will update the
89
        // filters as needed. Every call to provideStreamData for a given stream must write the same
90
        // data. Note that, when writing linearized files, qpdf will call your provideStreamData
91
        // twice, and if it generates different output, you risk generating invalid output or having
92
        // qpdf throw an exception. The object ID and generation passed to this method are those
93
        // that belong to the stream on behalf of which the provider is called. They may be ignored
94
        // or used by the implementation for indexing or other purposes. This information is made
95
        // available just to make it more convenient to use a single StreamDataProvider object to
96
        // provide data for multiple streams.
97
98
        // A few things to keep in mind:
99
        //
100
        // * Stream data providers must not modify any objects since   they may be called after some
101
        //   parts of the file have already been written.
102
        //
103
        // * Since qpdf may call provideStreamData multiple times when writing linearized files, if
104
        //   the work done by your stream data provider is slow or computationally intensive, you
105
        //   might want to implement your own cache.
106
        //
107
        // * Once you have called replaceStreamData, the original stream data is no longer directly
108
        //   accessible from the   stream, but this is easy to work around by copying the stream to
109
        //   a separate QPDF object. The qpdf library implements this very efficiently without
110
        //   actually making a copy of the stream data. You can find examples of this pattern in
111
        //   some of the examples, including pdf-custom-filter.cc and pdf-invert-images.cc.
112
113
        // Prior to qpdf 10.0.0, it was not possible to handle errors the way pipeStreamData does or
114
        // to pass back success. Starting in qpdf 10.0.0, those capabilities have been added by
115
        // allowing an alternative provideStreamData to be implemented. You must implement at least
116
        // one of the versions of provideStreamData below. If you implement the version that
117
        // supports retry and returns a value, you should pass true as the value of supports_retry
118
        // in the base class constructor. This will cause the library to call that version of the
119
        // method, which should also return a boolean indicating whether it ran without errors.
120
        QPDF_DLL
121
        virtual void provideStreamData(QPDFObjGen const& og, Pipeline* pipeline);
122
        QPDF_DLL
123
        virtual bool provideStreamData(
124
            QPDFObjGen const& og, Pipeline* pipeline, bool suppress_warnings, bool will_retry);
125
        QPDF_DLL virtual void provideStreamData(int objid, int generation, Pipeline* pipeline);
126
        QPDF_DLL virtual bool provideStreamData(
127
            int objid, int generation, Pipeline* pipeline, bool suppress_warnings, bool will_retry);
128
        QPDF_DLL
129
        bool supportsRetry();
130
131
      private:
132
        bool supports_retry;
133
    };
134
135
    // The TokenFilter class provides a way to filter content streams in a lexically aware fashion.
136
    // TokenFilters can be attached to streams using the addTokenFilter or addContentTokenFilter
137
    // methods or can be applied on the spot by filterPageContents. You may also use
138
    // Pl_QPDFTokenizer directly if you need full control.
139
    //
140
    // The handleToken method is called for each token, including the eof token, and then handleEOF
141
    // is called at the very end. Handlers may call write (or writeToken) to pass data downstream.
142
    // Please see examples/pdf-filter-tokens.cc and examples/pdf-count-strings.cc for examples of
143
    // using TokenFilters.
144
    //
145
    // Please note that when you call token.getValue() on a token of type tt_string or tt_name, you
146
    // get the canonical, "parsed" representation of the token. For a string, this means that there
147
    // are no delimiters, and for a name, it means that all escaping (# followed by two hex digits)
148
    // has been resolved. qpdf's internal representation of a name includes the leading slash. As
149
    // such, you can't write the value of token.getValue() directly to output that is supposed to be
150
    // valid PDF syntax. If you want to do that, you need to call writeToken() instead, or you can
151
    // retrieve the token as it appeared in the input with token.getRawValue(). To construct a new
152
    // string or name token from a canonical representation, use
153
    // QPDFTokenizer::Token(QPDFTokenizer::tt_string, "parsed-str") or
154
    // QPDFTokenizer::Token(QPDFTokenizer::tt_name,
155
    // "/Canonical-Name"). Tokens created this way won't have a PDF-syntax raw value, but you can
156
    // still write them with writeToken(). Example:
157
    // writeToken(QPDFTokenizer::Token(QPDFTokenizer::tt_name, "/text/plain"))
158
    // would write `/text#2fplain`, and
159
    // writeToken(QPDFTokenizer::Token(QPDFTokenizer::tt_string, "a\\(b")) would write `(a\(b)`.
160
    class QPDF_DLL_CLASS TokenFilter
161
    {
162
      public:
163
0
        TokenFilter() = default;
164
0
        virtual ~TokenFilter() = default;
165
        virtual void handleToken(QPDFTokenizer::Token const&) = 0;
166
        QPDF_DLL
167
        virtual void handleEOF();
168
169
        class PipelineAccessor
170
        {
171
            friend class Pl_QPDFTokenizer;
172
173
          private:
174
            static void
175
            setPipeline(TokenFilter* f, Pipeline* p)
176
0
            {
177
0
                f->setPipeline(p);
178
0
            }
179
        };
180
181
      protected:
182
        QPDF_DLL
183
        void write(char const* data, size_t len);
184
        QPDF_DLL
185
        void write(std::string const& str);
186
        QPDF_DLL
187
        void writeToken(QPDFTokenizer::Token const&);
188
189
      private:
190
        QPDF_DLL_PRIVATE
191
        void setPipeline(Pipeline*);
192
193
        Pipeline* pipeline;
194
    };
195
196
    // This class is used by parse to decrypt strings when reading an object that contains encrypted
197
    // strings.
198
    class StringDecrypter
199
    {
200
      public:
201
0
        virtual ~StringDecrypter() = default;
202
        virtual void decryptString(std::string& val) = 0;
203
    };
204
205
    // This class is used by parsePageContents. Callers must instantiate a subclass of this with
206
    // handlers defined to accept QPDFObjectHandles that are parsed from the stream.
207
    class QPDF_DLL_CLASS ParserCallbacks
208
    {
209
      public:
210
0
        virtual ~ParserCallbacks() = default;
211
        // One of the handleObject methods must be overridden.
212
        QPDF_DLL
213
        virtual void handleObject(QPDFObjectHandle);
214
        QPDF_DLL
215
        virtual void handleObject(QPDFObjectHandle, size_t offset, size_t length);
216
217
        virtual void handleEOF() = 0;
218
219
        // Override this if you want to know the full size of the contents, possibly after
220
        // concatenation of multiple streams. This is called before the first call to handleObject.
221
        QPDF_DLL
222
        virtual void contentSize(size_t);
223
224
      protected:
225
        // Implementors may call this method during parsing to terminate parsing early. This method
226
        // throws an exception that is caught by parsePageContents, so its effect is immediate.
227
        QPDF_DLL
228
        void terminateParsing();
229
    };
230
231
    // Convenience object for rectangles
232
    class Rectangle
233
    {
234
      public:
235
        Rectangle() :
236
0
            llx(0.0),
237
0
            lly(0.0),
238
0
            urx(0.0),
239
0
            ury(0.0)
240
0
        {
241
0
        }
242
        Rectangle(double llx, double lly, double urx, double ury) :
243
0
            llx(llx),
244
0
            lly(lly),
245
0
            urx(urx),
246
0
            ury(ury)
247
0
        {
248
0
        }
249
250
        double llx;
251
        double lly;
252
        double urx;
253
        double ury;
254
    };
255
256
    // Convenience object for transformation matrices. See also QPDFMatrix. Unfortunately we can't
257
    // replace this with QPDFMatrix because QPDFMatrix's default constructor creates the identity
258
    // transform matrix and this one is all zeroes.
259
    class Matrix
260
    {
261
      public:
262
        Matrix() :
263
0
            a(0.0),
264
0
            b(0.0),
265
0
            c(0.0),
266
0
            d(0.0),
267
0
            e(0.0),
268
0
            f(0.0)
269
0
        {
270
0
        }
271
        Matrix(double a, double b, double c, double d, double e, double f) :
272
0
            a(a),
273
0
            b(b),
274
0
            c(c),
275
0
            d(d),
276
0
            e(e),
277
0
            f(f)
278
0
        {
279
0
        }
280
281
        double a;
282
        double b;
283
        double c;
284
        double d;
285
        double e;
286
        double f;
287
    };
288
289
2.62M
    QPDFObjectHandle() = default;
290
2.75M
    QPDFObjectHandle(QPDFObjectHandle const&) = default;
291
159k
    QPDFObjectHandle& operator=(QPDFObjectHandle const&) = default;
292
3.16M
    QPDFObjectHandle(QPDFObjectHandle&&) = default;
293
2.48M
    QPDFObjectHandle& operator=(QPDFObjectHandle&&) = default;
294
295
    // This method is provided for backward compatibility only. New code should convert to bool
296
    // instead.
297
    inline bool isInitialized() const;
298
299
    // This method returns true if the QPDFObjectHandle objects point to exactly the same underlying
300
    // object, meaning that changes to one are reflected in the other, or "if you paint one, the
301
    // other one changes color." This does not perform a structural comparison of the contents of
302
    // the objects.
303
    QPDF_DLL
304
    bool isSameObjectAs(QPDFObjectHandle const&) const;
305
306
    // Return type code and type name of underlying object.  These are useful for doing rapid type
307
    // tests (like switch statements) or for testing and debugging.
308
    QPDF_DLL
309
    qpdf_object_type_e getTypeCode() const;
310
    QPDF_DLL
311
    char const* getTypeName() const;
312
313
    // Exactly one of these will return true for any initialized object. Operator and InlineImage
314
    // are only allowed in content streams.
315
    QPDF_DLL
316
    bool isBool() const;
317
    QPDF_DLL
318
    bool isNull() const;
319
    QPDF_DLL
320
    bool isInteger() const;
321
    QPDF_DLL
322
    bool isReal() const;
323
    QPDF_DLL
324
    bool isName() const;
325
    QPDF_DLL
326
    bool isString() const;
327
    QPDF_DLL
328
    bool isOperator() const;
329
    QPDF_DLL
330
    bool isInlineImage() const;
331
    QPDF_DLL
332
    bool isArray() const;
333
    QPDF_DLL
334
    bool isDictionary() const;
335
    QPDF_DLL
336
    bool isStream() const;
337
    QPDF_DLL
338
    bool isReserved() const;
339
340
    // True for objects that are direct nulls. Does not attempt to resolve objects. This is intended
341
    // for internal use, but it can be used as an efficient way to check for nulls that are not
342
    // indirect objects.
343
    QPDF_DLL
344
    bool isDirectNull() const;
345
346
    // This returns true in addition to the query for the specific type for indirect objects.
347
    QPDF_DLL
348
    bool isIndirect() const;
349
350
    // This returns true for indirect objects from a QPDF that has been destroyed. Trying unparse
351
    // such an object will throw a logic_error.
352
    QPDF_DLL
353
    bool isDestroyed() const;
354
355
    // True for everything except array, dictionary, stream, word, and inline image.
356
    QPDF_DLL
357
    bool isScalar() const;
358
359
    // True if the object is a name object representing the provided name.
360
    QPDF_DLL
361
    bool isNameAndEquals(std::string const& name) const;
362
363
    // True if the object is a dictionary of the specified type and subtype, if any.
364
    QPDF_DLL
365
    bool isDictionaryOfType(std::string const& type, std::string const& subtype = "") const;
366
367
    // True if the object is a stream of the specified type and subtype, if any.
368
    QPDF_DLL
369
    bool isStreamOfType(std::string const& type, std::string const& subtype = "") const;
370
371
    // Public factory methods
372
373
    // Wrap an object in an array if it is not already an array. This is a helper for cases in which
374
    // something in a PDF may either be a single item or an array of items, which is a common idiom.
375
    QPDF_DLL
376
    QPDFObjectHandle wrapInArray();
377
378
    // Construct an object of any type from a string representation of the object.  Throws QPDFExc
379
    // with an empty filename and an offset into the string if there is an error.  Any indirect
380
    // object syntax (obj gen R) will cause a logic_error exception to be thrown.  If
381
    // object_description is provided, it will appear in the message of any QPDFExc exception thrown
382
    // for invalid syntax. See also the global `operator ""_qpdf` defined below.
383
    QPDF_DLL
384
    static QPDFObjectHandle
385
    parse(std::string const& object_str, std::string const& object_description = "");
386
387
    // Construct an object of any type from a string representation of the object. Indirect object
388
    // syntax (obj gen R) is allowed and will create indirect references within the passed-in
389
    // context. If object_description is provided, it will appear in the message of any QPDFExc
390
    // exception thrown for invalid syntax. Note that you can't parse an indirect object reference
391
    // all by itself as parse will stop at the end of the first complete object, which will just be
392
    // the first number and will report that there is trailing data at the end of the string.
393
    QPDF_DLL
394
    static QPDFObjectHandle
395
    parse(QPDF* context, std::string const& object_str, std::string const& object_description = "");
396
397
    // Construct an object as above by reading from the given InputSource at its current position
398
    // and using the tokenizer you supply.  Indirect objects and encrypted strings are permitted.
399
    // This method was intended to be called by QPDF for parsing objects that are read from the
400
    // object's input stream. To be removed in qpdf 13. See
401
    // <https:manual.qpdf.org/release-notes.html#r12-0-0-deprecate>.
402
    [[deprecated("to be removed in qpdf 13")]] QPDF_DLL static QPDFObjectHandle parse(
403
        std::shared_ptr<InputSource> input,
404
        std::string const& object_description,
405
        QPDFTokenizer&,
406
        bool& empty,
407
        StringDecrypter* decrypter,
408
        QPDF* context);
409
410
    // Return the offset where the object was found when parsed. A negative value means that the
411
    // object was created without parsing. If the object is in a stream, the offset is from the
412
    // beginning of the stream. Otherwise, the offset is from the beginning of the file.
413
    QPDF_DLL
414
    qpdf_offset_t getParsedOffset() const;
415
416
    // Older method: stream_or_array should be the value of /Contents from a page object. It's more
417
    // convenient to just call QPDFPageObjectHelper::parsePageContents on the page object, and error
418
    // messages will also be more useful because the page object information will be known.
419
    QPDF_DLL
420
    static void parseContentStream(QPDFObjectHandle stream_or_array, ParserCallbacks* callbacks);
421
422
    // When called on a stream or stream array that is some page's content streams, do the same as
423
    // pipePageContents. This method is a lower level way to do what
424
    // QPDFPageObjectHelper::pipePageContents does, but it allows you to perform this operation on a
425
    // contents object that is disconnected from a page object. The description argument should
426
    // describe the containing page and is used in error messages. The all_description argument is
427
    // initialized to something that could be used to describe the result of the pipeline. It is the
428
    // description amended with the identifiers of the underlying objects. Please note that if there
429
    // is an array of content streams, p->finish() is called after each stream. If you pass a
430
    // pipeline that doesn't allow write() to be called after finish(), you can wrap it in an
431
    // instance of Pl_Concatenate and then call manualFinish() on the Pl_Concatenate pipeline at the
432
    // end.
433
    QPDF_DLL
434
    void
435
    pipeContentStreams(Pipeline* p, std::string const& description, std::string& all_description);
436
437
    // As of qpdf 8, it is possible to add custom token filters to a stream. The tokenized stream
438
    // data is passed through the token filter after all original filters but before content stream
439
    // normalization if requested. This is a low-level interface to add it to a stream. You will
440
    // usually want to call QPDFPageObjectHelper::addContentTokenFilter instead, which can be
441
    // applied to a page object, and which will automatically handle the case of pages whose
442
    // contents are split across multiple streams.
443
    QPDF_DLL
444
    void addTokenFilter(std::shared_ptr<TokenFilter> token_filter);
445
446
    // Legacy helpers for parsing content streams. These methods are not going away, but newer code
447
    // should call the correspond methods in QPDFPageObjectHelper instead. The specification and
448
    // behavior of these methods are the same as the identically named methods in that class, but
449
    // newer functionality will be added there.
450
    QPDF_DLL
451
    void parsePageContents(ParserCallbacks* callbacks);
452
    QPDF_DLL
453
    void filterPageContents(TokenFilter* filter, Pipeline* next = nullptr);
454
    // See comments for QPDFPageObjectHelper::pipeContents.
455
    QPDF_DLL
456
    void pipePageContents(Pipeline* p);
457
    QPDF_DLL
458
    void addContentTokenFilter(std::shared_ptr<TokenFilter> token_filter);
459
    // End legacy content stream helpers
460
461
    // Called on a stream to filter the stream as if it were page contents. This can be used to
462
    // apply a TokenFilter to a form XObject, whose data is in the same format as a content stream.
463
    QPDF_DLL
464
    void filterAsContents(TokenFilter* filter, Pipeline* next = nullptr);
465
    // Called on a stream to parse the stream as page contents. This can be used to parse a form
466
    // XObject.
467
    QPDF_DLL
468
    void parseAsContents(ParserCallbacks* callbacks);
469
470
    // Type-specific factories
471
    QPDF_DLL
472
    static QPDFObjectHandle newNull();
473
    QPDF_DLL
474
    static QPDFObjectHandle newBool(bool value);
475
    QPDF_DLL
476
    static QPDFObjectHandle newInteger(long long value);
477
    QPDF_DLL
478
    static QPDFObjectHandle newReal(std::string const& value);
479
    QPDF_DLL
480
    static QPDFObjectHandle
481
    newReal(double value, int decimal_places = 0, bool trim_trailing_zeroes = true);
482
    // Note about name objects: qpdf's internal representation of a PDF name is a sequence of bytes,
483
    // excluding the NUL character, and starting with a slash. Name objects as represented in the
484
    // PDF specification can contain characters escaped with #, but such escaping is not of concern
485
    // when calling QPDFObjectHandle methods not directly relating to parsing. For example,
486
    // newName("/text/plain").getName() and parse("/text#2fplain").getName() both return
487
    // "/text/plain", while newName("/text/plain").unparse() and parse("/text#2fplain").unparse()
488
    // both return "/text#2fplain". When working with the qpdf API for creating, retrieving, and
489
    // modifying objects, you want to work with the internal, canonical representation. For names
490
    // containing alphanumeric characters, dashes, and underscores, there is no difference between
491
    // the two representations. For a lengthy discussion, see
492
    // https://github.com/qpdf/qpdf/discussions/625.
493
    QPDF_DLL
494
    static QPDFObjectHandle newName(std::string const& name);
495
    QPDF_DLL
496
    static QPDFObjectHandle newString(std::string const& str);
497
    // Create a string encoded from the given utf8-encoded string appropriately encoded to appear in
498
    // PDF files outside of content streams, such as in document metadata form field values, page
499
    // labels, outlines, and similar locations. We try ASCII first, then PDFDocEncoding, then UTF-16
500
    // as needed to successfully encode all the characters.
501
    QPDF_DLL
502
    static QPDFObjectHandle newUnicodeString(std::string const& utf8_str);
503
    QPDF_DLL
504
    static QPDFObjectHandle newOperator(std::string const&);
505
    QPDF_DLL
506
    static QPDFObjectHandle newInlineImage(std::string const&);
507
    QPDF_DLL
508
    static QPDFObjectHandle newArray();
509
    QPDF_DLL
510
    static QPDFObjectHandle newArray(std::vector<QPDFObjectHandle> const& items);
511
    QPDF_DLL
512
    static QPDFObjectHandle newArray(Rectangle const&);
513
    QPDF_DLL
514
    static QPDFObjectHandle newArray(Matrix const&);
515
    QPDF_DLL
516
    static QPDFObjectHandle newArray(QPDFMatrix const&);
517
    QPDF_DLL
518
    static QPDFObjectHandle newDictionary();
519
    QPDF_DLL
520
    static QPDFObjectHandle newDictionary(std::map<std::string, QPDFObjectHandle> const& items);
521
522
    // Create an array from a rectangle. Equivalent to the rectangle form of newArray.
523
    QPDF_DLL
524
    static QPDFObjectHandle newFromRectangle(Rectangle const&);
525
    // Create an array from a matrix. Equivalent to the matrix form of newArray.
526
    QPDF_DLL
527
    static QPDFObjectHandle newFromMatrix(Matrix const&);
528
    QPDF_DLL
529
    static QPDFObjectHandle newFromMatrix(QPDFMatrix const&);
530
531
    // Note: new stream creation methods have were added to the QPDF class starting with
532
    // version 11.2.0. The ones in this class are here for backward compatibility.
533
534
    // Create a new stream and associate it with the given qpdf object. A subsequent call must be
535
    // made to replaceStreamData() to provide data for the stream. The stream's dictionary may be
536
    // retrieved by calling getDict(), and the resulting dictionary may be modified. Alternatively,
537
    // you can create a new dictionary and call replaceDict to install it. From QPDF 11.2, you can
538
    // call QPDF::newStream() instead.
539
    QPDF_DLL
540
    static QPDFObjectHandle newStream(QPDF* qpdf);
541
542
    // Create a new stream and associate it with the given qpdf object. Use the given buffer as the
543
    // stream data. The stream dictionary's /Length key will automatically be set to the size of the
544
    // data buffer. If additional keys are required, the stream's dictionary may be retrieved by
545
    // calling getDict(), and the resulting dictionary may be modified. This method is just a
546
    // convenient wrapper around the newStream() and replaceStreamData(). It is a convenience
547
    // methods for streams that require no parameters beyond the stream length. Note that you don't
548
    // have to deal with compression yourself if you use QPDFWriter. By default, QPDFWriter will
549
    // automatically compress uncompressed stream data. Example programs are provided that
550
    // illustrate this. From QPDF 11.2, you can call QPDF::newStream()
551
    // instead.
552
    QPDF_DLL
553
    static QPDFObjectHandle newStream(QPDF* qpdf, std::shared_ptr<Buffer> data);
554
555
    // Create new stream with data from string. This method will create a copy of the data rather
556
    // than using the user-provided buffer as in the std::shared_ptr<Buffer> version of newStream.
557
    // From QPDF 11.2, you can call QPDF::newStream() instead.
558
    QPDF_DLL
559
    static QPDFObjectHandle newStream(QPDF* qpdf, std::string const& data);
560
561
    // A reserved object is a special sentinel used for qpdf to reserve a spot for an object that is
562
    // going to be added to the QPDF object.  Normally you don't have to use this type since you can
563
    // just call QPDF::makeIndirectObject.  However, in some cases, if you have to create objects
564
    // with circular references, you may need to create a reserved object so that you can have a
565
    // reference to it and then replace the object later.  Reserved objects have the special
566
    // property that they can't be resolved to direct objects.  This makes it possible to replace a
567
    // reserved object with a new object while preserving existing references to them.  When you are
568
    // ready to replace a reserved object with its replacement, use QPDF::replaceReserved for this
569
    // purpose rather than the more general QPDF::replaceObject.  It is an error to try to write a
570
    // QPDF with QPDFWriter if it has any reserved objects in it. From QPDF 11.4, you can call
571
    // QPDF::newReserved() instead.
572
    QPDF_DLL
573
    static QPDFObjectHandle newReserved(QPDF* qpdf);
574
575
    // Provide an owning qpdf and object description. The library does this automatically with
576
    // objects that are read from the input PDF and with objects that are created programmatically
577
    // and inserted into the QPDF as a new indirect object. Most end user code will not need to call
578
    // this. If an object has an owning qpdf and object description, it enables qpdf to give
579
    // warnings with proper context in some cases where it would otherwise raise exceptions. It is
580
    // okay to add objects without an owning_qpdf to objects that have one, but it is an error to
581
    // have a QPDF contain objects with owning_qpdf set to something else. To add objects from
582
    // another qpdf, use copyForeignObject instead.
583
    QPDF_DLL
584
    void setObjectDescription(QPDF* owning_qpdf, std::string const& object_description);
585
    QPDF_DLL
586
    bool hasObjectDescription() const;
587
588
    // Accessor methods
589
    //
590
    // (Note: this comment is referenced in qpdf-c.h and the manual.)
591
    //
592
    // In PDF files, objects have specific types, but there is nothing that prevents PDF files from
593
    // containing objects of types that aren't expected by the specification.
594
    //
595
    // There are two flavors of accessor methods:
596
    //
597
    // * getSomethingValue() returns the value and issues a type   warning if the type is incorrect.
598
    //
599
    // * getValueAsSomething() returns false if the value is the wrong type. Otherwise, it returns
600
    //   true and initializes a reference of the appropriate type. These methods never issue type
601
    //   warnings.
602
    //
603
    // The getSomethingValue() accessors and some of the other methods expect objects of a
604
    // particular type. Prior to qpdf 8, calling an accessor on a method of the wrong type, such as
605
    // trying to get a dictionary key from an array, trying to get the string value of a number,
606
    // etc., would throw an exception, but since qpdf 8, qpdf issues a warning and recovers using
607
    // the following behavior:
608
    //
609
    // * Requesting a value of the wrong type (int value from string,   array item from a scalar or
610
    //   dictionary, etc.) will return a zero-like value for that type: false for boolean, 0 for
611
    //   number, the empty string for string, or the null object for an object handle.
612
    //
613
    // * Accessing an array item that is out of bounds will return a null object.
614
    //
615
    // * Attempts to mutate an object of the wrong type (e.g., attempting to add a dictionary key to
616
    //   a scalar or array) will be ignored.
617
    //
618
    // When any of these fallback behaviors are used, qpdf issues a warning. Starting in qpdf 10.5,
619
    // these warnings have the error code qpdf_e_object. Prior to 10.5, they had the error code
620
    // qpdf_e_damaged_pdf. If the QPDFObjectHandle is associated with a QPDF object (as is the case
621
    // for all objects whose origin was a PDF file), the warning is issued using the normal warning
622
    // mechanism (as described in QPDF.hh), making it possible to suppress or otherwise detect them.
623
    // If the QPDFObjectHandle is not associated with a QPDF object (meaning it was created
624
    // programmatically), an exception will be thrown.
625
    //
626
    // The way to avoid getting any type warnings or exceptions, even when working with malformed
627
    // PDF files, is to always check the type of a QPDFObjectHandle before accessing it (for
628
    // example, make sure that isString() returns true before calling getStringValue()) and to
629
    // always be sure that any array indices are in bounds.
630
    //
631
    // For additional discussion and rationale for this behavior, see the section in the QPDF manual
632
    // entitled "Object Accessor Methods".
633
634
    // Methods for bool objects
635
    QPDF_DLL
636
    bool getBoolValue() const;
637
    QPDF_DLL
638
    bool getValueAsBool(bool&) const;
639
640
    // Methods for integer objects. Note: if an integer value is too big (too far away from zero in
641
    // either direction) to fit in the requested return type, the maximum or minimum value for that
642
    // return type may be returned. For example, on a system with 32-bit int, a numeric object with
643
    // a value of 2^40 (or anything too big for 32 bits) will be returned as INT_MAX.
644
    QPDF_DLL
645
    long long getIntValue() const;
646
    QPDF_DLL
647
    bool getValueAsInt(long long&) const;
648
    QPDF_DLL
649
    int getIntValueAsInt() const;
650
    QPDF_DLL
651
    bool getValueAsInt(int&) const;
652
    QPDF_DLL
653
    unsigned long long getUIntValue() const;
654
    QPDF_DLL
655
    bool getValueAsUInt(unsigned long long&) const;
656
    QPDF_DLL
657
    unsigned int getUIntValueAsUInt() const;
658
    QPDF_DLL
659
    bool getValueAsUInt(unsigned int&) const;
660
661
    // Methods for real objects
662
    QPDF_DLL
663
    std::string getRealValue() const;
664
    QPDF_DLL
665
    bool getValueAsReal(std::string&) const;
666
667
    // Methods that work for both integer and real objects
668
    QPDF_DLL
669
    bool isNumber() const;
670
    QPDF_DLL
671
    double getNumericValue() const;
672
    QPDF_DLL
673
    bool getValueAsNumber(double&) const;
674
675
    // Methods for name objects. The returned name value is in qpdf's canonical form with all
676
    // escaping resolved. See comments for newName() for details.
677
    QPDF_DLL
678
    std::string getName() const;
679
    QPDF_DLL
680
    bool getValueAsName(std::string&) const;
681
682
    // Methods for string objects
683
    QPDF_DLL
684
    std::string getStringValue() const;
685
    QPDF_DLL
686
    bool getValueAsString(std::string&) const;
687
688
    // If a string starts with the UTF-16 marker, it is converted from UTF-16 to UTF-8. Otherwise,
689
    // it is treated as a string encoded with PDF Doc Encoding. PDF Doc Encoding is identical to
690
    // ISO-8859-1 except in the range from 0200 through 0240, where there is a mapping of characters
691
    // to Unicode. QPDF versions prior to version 8.0.0 erroneously left characters in that range
692
    // unmapped.
693
    QPDF_DLL
694
    std::string getUTF8Value() const;
695
    QPDF_DLL
696
    bool getValueAsUTF8(std::string&) const;
697
698
    // Methods for content stream objects
699
    QPDF_DLL
700
    std::string getOperatorValue() const;
701
    QPDF_DLL
702
    bool getValueAsOperator(std::string&) const;
703
    QPDF_DLL
704
    std::string getInlineImageValue() const;
705
    QPDF_DLL
706
    bool getValueAsInlineImage(std::string&) const;
707
708
    // Methods for array objects; see also name and array objects.
709
710
    // Return an object that enables iteration over members. You can do
711
    //
712
    // for (auto iter: obj.aitems())
713
    // {
714
    //     // iter is an array element
715
    // }
716
    class QPDFArrayItems;
717
    QPDF_DLL
718
    QPDFArrayItems aitems();
719
720
    QPDF_DLL
721
    int getArrayNItems() const;
722
    QPDF_DLL
723
    QPDFObjectHandle getArrayItem(int n) const;
724
    // Note: QPDF arrays internally optimize memory for arrays containing lots of nulls. Calling
725
    // getArrayAsVector may cause a lot of memory to be allocated for very large arrays with lots of
726
    // nulls.
727
    QPDF_DLL
728
    std::vector<QPDFObjectHandle> getArrayAsVector() const;
729
    QPDF_DLL
730
    bool isRectangle() const;
731
    // If the array is an array of four numeric values, return as a rectangle. Otherwise, return the
732
    // rectangle [0, 0, 0, 0]
733
    QPDF_DLL
734
    Rectangle getArrayAsRectangle() const;
735
    QPDF_DLL
736
    bool isMatrix() const;
737
    // If the array is an array of six numeric values, return as a matrix. Otherwise, return the
738
    // matrix [1, 0, 0, 1, 0, 0]
739
    QPDF_DLL
740
    Matrix getArrayAsMatrix() const;
741
742
    // Methods for dictionary objects. In all dictionary methods, keys are specified/represented as
743
    // canonical name strings starting with a leading slash and not containing any PDF syntax
744
    // escaping. See comments for getName() for details.
745
746
    // Return an object that enables iteration over members. You can do
747
    //
748
    // for (auto iter: obj.ditems())
749
    // {
750
    //     // iter.first is the key
751
    //     // iter.second is the value
752
    // }
753
    class QPDFDictItems;
754
    QPDF_DLL
755
    QPDFDictItems ditems();
756
757
    // Return true if key is present.  Keys with null values are treated as if they are not present.
758
    // This is as per the PDF spec.
759
    QPDF_DLL
760
    bool hasKey(std::string const&) const;
761
    // Return the value for the key.  If the key is not present, null is returned.
762
    QPDF_DLL
763
    QPDFObjectHandle getKey(std::string const&) const;
764
    // If the object is null, return null. Otherwise, call getKey(). This makes it easier to access
765
    // lower-level dictionaries, as in
766
    // auto font = page.getKeyIfDict("/Resources").getKeyIfDict("/Font");
767
    QPDF_DLL
768
    QPDFObjectHandle getKeyIfDict(std::string const&) const;
769
    // Return all keys.  Keys with null values are treated as if they are not present.  This is as
770
    // per the PDF spec.
771
    QPDF_DLL
772
    std::set<std::string> getKeys() const;
773
    // Return dictionary as a map.  Entries with null values are included.
774
    QPDF_DLL
775
    std::map<std::string, QPDFObjectHandle> getDictAsMap() const;
776
777
    // Methods for name and array objects. The name value is in qpdf's canonical form with all
778
    // escaping resolved. See comments for newName() for details.
779
    QPDF_DLL
780
    bool isOrHasName(std::string const&) const;
781
782
    // Make all resources in a resource dictionary indirect. This just goes through all entries of
783
    // top-level subdictionaries and converts any direct objects to indirect objects. This can be
784
    // useful to call before mergeResources if it is going to be called multiple times to prevent
785
    // resources from being copied multiple times.
786
    QPDF_DLL
787
    void makeResourcesIndirect(QPDF& owning_qpdf);
788
789
    // Merge resource dictionaries. If the "conflicts" parameter is provided, conflicts in
790
    // dictionary subitems are resolved, and "conflicts" is initialized to a map such that
791
    // conflicts[resource_type][old_key] == [new_key]
792
    //
793
    // See also makeResourcesIndirect, which can be useful to call before calling this.
794
    //
795
    // This method does nothing if both this object and the other object are not dictionaries.
796
    // Otherwise, it has following behavior, where "object" refers to the object whose method is
797
    // invoked, and "other" refers to the argument:
798
    //
799
    // * For each key in "other" whose value is an array:
800
    //   * If "object" does not have that entry, shallow copy it.
801
    //   * Otherwise, if "object" has an array in the same place, append to that array any objects
802
    //     in "other"'s array that are not already present.
803
    // * For each key in "other" whose value is a dictionary:
804
    //   * If "object" does not have that entry, shallow copy it.
805
    //   * Otherwise, for each key in the subdictionary:
806
    //     * If key is not present in "object"'s entry, shallow copy it if direct or just add it if
807
    //       indirect.
808
    //     * Otherwise, if conflicts are being detected:
809
    //       * If there is a key (oldkey) already in the dictionary that points to the same indirect
810
    //         destination as key, indicate that key was replaced by oldkey. This would happen if
811
    //         these two resource dictionaries have previously been merged.
812
    //       * Otherwise pick a new key (newkey) that is unique within the resource dictionary,
813
    //         store that in the resource dictionary with key's destination as its destination, and
814
    //         indicate that key was replaced by newkey.
815
    //
816
    // The primary purpose of this method is to facilitate merging of resource dictionaries that are
817
    // supposed to have the same scope as each other. For example, this can be used to merge a form
818
    // XObject's /Resources dictionary with a form field's /DR or to merge two /DR dictionaries. The
819
    // "conflicts" parameter may be previously initialized. This method adds to whatever is already
820
    // there, which can be useful when merging with multiple things.
821
    QPDF_DLL
822
    void mergeResources(
823
        QPDFObjectHandle other,
824
        std::map<std::string, std::map<std::string, std::string>>* conflicts = nullptr);
825
826
    // Get all resource names from a resource dictionary. If this object is a dictionary, this
827
    // method returns a set of all the keys in all top-level subdictionaries. For resources
828
    // dictionaries, this is the collection of names that may be referenced in the content stream.
829
    QPDF_DLL
830
    std::set<std::string> getResourceNames() const;
831
832
    // Find a unique name within a resource dictionary starting with a given prefix. This method
833
    // works by appending a number to the given prefix. It searches starting with min_suffix and
834
    // sets min_suffix to selected value upon return. This can be used to increase efficiency if
835
    // adding multiple items with the same prefix. (Why doesn't it set min_suffix to the next
836
    // number? Well, maybe you aren't going to actually use the name it returns.) If you are calling
837
    // this multiple times on the same resource dictionary, you can initialize resource_names by
838
    // calling getResourceNames(), incrementally update it as you add resources, and keep passing it
839
    // in so that getUniqueResourceName doesn't have to traverse the resource dictionary each time
840
    // it's called.
841
    QPDF_DLL
842
    std::string getUniqueResourceName(
843
        std::string const& prefix,
844
        int& min_suffix,
845
        std::set<std::string>* resource_names = nullptr) const;
846
847
    // A QPDFObjectHandle has an owning QPDF if it is associated with ("owned by") a specific QPDF
848
    // object. Indirect objects always have an owning QPDF. Direct objects that are read from the
849
    // input source will also have an owning QPDF. Programmatically created objects will only have
850
    // one if setObjectDescription was called.
851
    //
852
    // When the QPDF object that owns an object is destroyed, the object is changed into a null, and
853
    // its owner is cleared. Therefore you should not retain the value of an owning QPDF beyond the
854
    // life of the QPDF. If in doubt, ask for it each time you need it.
855
856
    // getOwningQPDF returns a pointer to the owning QPDF is the object has one. Otherwise, it
857
    // returns a null pointer. Use this when you are able to handle the case of an object that
858
    // doesn't have an owning QPDF.
859
    QPDF_DLL
860
    QPDF* getOwningQPDF() const;
861
    // getQPDF, new in qpdf 11, returns a reference owning QPDF. If there is none, it throws a
862
    // runtime_error. Use this when you know the object has to have an owning QPDF, such as when
863
    // it's a known indirect object. Since streams are always indirect objects, this method can be
864
    // used safely for streams. If error_msg is specified, it will be used at the contents of the
865
    // runtime_error if there is now owner.
866
    QPDF_DLL
867
    QPDF& getQPDF(std::string const& error_msg = "") const;
868
869
    // Create a shallow copy of an object as a direct object, but do not traverse across indirect
870
    // object boundaries. That means that, for dictionaries and arrays, any keys or items that were
871
    // indirect objects will still be indirect objects that point to the same place. In the
872
    // strictest sense, this is not a shallow copy because it recursively descends arrays and
873
    // dictionaries; it just doesn't cross over indirect objects. See also unsafeShallowCopy(). You
874
    // can't copy a stream this way. See copyStream() instead.
875
    QPDF_DLL
876
    QPDFObjectHandle shallowCopy();
877
878
    // Create a true shallow copy of an array or dictionary, just copying the immediate items
879
    // (array) or keys (dictionary). This is "unsafe" because, if you *modify* any of the items in
880
    // the copy, you are modifying the original, which is almost never what you want. However, if
881
    // your intention is merely to *replace* top-level items or keys and not to modify lower-level
882
    // items in the copy, this method is much faster than shallowCopy().
883
    QPDF_DLL
884
    QPDFObjectHandle unsafeShallowCopy();
885
886
    // Create a copy of this stream. The new stream and the old stream are independent: after the
887
    // copy, either the original or the copy's dictionary or data can be modified without affecting
888
    // the other. This uses StreamDataProvider internally, so no unnecessary copies of the stream's
889
    // data are made. If the source stream's data is already being provided by a StreamDataProvider,
890
    // the new stream will use the same one, so you have to make sure your StreamDataProvider can
891
    // handle that case. But if you're already using a StreamDataProvider, you probably don't need
892
    // to call this method.
893
    QPDF_DLL
894
    QPDFObjectHandle copyStream();
895
896
    // Mutator methods.
897
898
    // Since qpdf 11: for mutators that may add or remove an item, there are additional versions
899
    // whose names contain "AndGet" that return the added or removed item. For example:
900
    //
901
    //   auto new_dict = dict.replaceKeyAndGetNew(
902
    //       "/New", QPDFObjectHandle::newDictionary());
903
    //
904
    //   auto old_value = dict.replaceKeyAndGetOld(
905
    //       "/New", "(something)"_qpdf);
906
907
    // Recursively copy this object, making it direct. An exception is thrown if a loop is detected.
908
    // With allow_streams true, keep indirect object references to streams. Otherwise, throw an
909
    // exception if any sub-object is a stream. Note that, when allow_streams is true and a stream
910
    // is found, the resulting object is still associated with the containing qpdf. When
911
    // allow_streams is false, the object will no longer be connected to the original QPDF object
912
    // after this call completes successfully.
913
    QPDF_DLL
914
    void makeDirect(bool allow_streams = false);
915
916
    // Mutator methods for array objects
917
    QPDF_DLL
918
    void setArrayItem(int, QPDFObjectHandle const&);
919
    QPDF_DLL
920
    void setArrayFromVector(std::vector<QPDFObjectHandle> const& items);
921
    // Insert an item before the item at the given position ("at") so that it has that position
922
    // after insertion. If "at" is equal to the size of the array, insert the item at the end.
923
    QPDF_DLL
924
    void insertItem(int at, QPDFObjectHandle const& item);
925
    // Like insertItem but return the item that was inserted.
926
    QPDF_DLL
927
    QPDFObjectHandle insertItemAndGetNew(int at, QPDFObjectHandle const& item);
928
    // Append an item to an array.
929
    QPDF_DLL
930
    void appendItem(QPDFObjectHandle const& item);
931
    // Append an item, and return the newly added item.
932
    QPDF_DLL
933
    QPDFObjectHandle appendItemAndGetNew(QPDFObjectHandle const& item);
934
    // Remove the item at that position, reducing the size of the array by one.
935
    QPDF_DLL
936
    void eraseItem(int at);
937
    // Erase and item and return the item that was removed.
938
    QPDF_DLL
939
    QPDFObjectHandle eraseItemAndGetOld(int at);
940
941
    // Mutator methods for dictionary objects
942
943
    // Replace value of key, adding it if it does not exist. If value is null, remove the key.
944
    QPDF_DLL
945
    void replaceKey(std::string const& key, QPDFObjectHandle const& value);
946
    // Replace value of key and return the value.
947
    QPDF_DLL
948
    QPDFObjectHandle replaceKeyAndGetNew(std::string const& key, QPDFObjectHandle const& value);
949
    // Replace value of key and return the old value, or null if the key was previously not present.
950
    QPDF_DLL
951
    QPDFObjectHandle replaceKeyAndGetOld(std::string const& key, QPDFObjectHandle const& value);
952
    // Remove key, doing nothing if key does not exist.
953
    QPDF_DLL
954
    void removeKey(std::string const& key);
955
    // Remove key and return the old value. If the old value didn't exist, return a null object.
956
    QPDF_DLL
957
    QPDFObjectHandle removeKeyAndGetOld(std::string const& key);
958
959
    // Methods for stream objects
960
    QPDF_DLL
961
    QPDFObjectHandle getDict() const;
962
963
    // By default, or if true passed, QPDFWriter will attempt to filter a stream based on decode
964
    // level, whether compression is enabled, and its ability to filter. Passing false will prevent
965
    // QPDFWriter from attempting to filter the stream even if it can. This includes both decoding
966
    // and compressing. This makes it possible for you to prevent QPDFWriter from uncompressing and
967
    // recompressing a stream that it knows how to operate on for any application-specific reason,
968
    // such as that you have already optimized its filtering. Note that this doesn't affect any
969
    // other ways to get the stream's data, such as pipeStreamData or getStreamData.
970
    QPDF_DLL
971
    void setFilterOnWrite(bool);
972
    QPDF_DLL
973
    bool getFilterOnWrite();
974
975
    // If addTokenFilter has been called for this stream, then the original data should be
976
    // considered to be modified. This means we should avoid optimizations such as not filtering a
977
    // stream that is already compressed.
978
    QPDF_DLL
979
    bool isDataModified();
980
981
    // Returns filtered (uncompressed) stream data.  Throws an exception if the stream is filtered
982
    // and we can't decode it.
983
    QPDF_DLL
984
    std::shared_ptr<Buffer> getStreamData(qpdf_stream_decode_level_e level = qpdf_dl_generalized);
985
986
    // Returns unfiltered (raw) stream data.
987
    QPDF_DLL
988
    std::shared_ptr<Buffer> getRawStreamData();
989
990
    // Write stream data through the given pipeline. A null pipeline value may be used if all you
991
    // want to do is determine whether a stream is filterable and would be filtered based on the
992
    // provided flags. If flags is 0, write raw stream data and return false. Otherwise, the flags
993
    // alter the behavior in the following way:
994
    //
995
    // encode_flags:
996
    //
997
    // qpdf_sf_compress -- compress data with /FlateDecode if no other compression filters are
998
    // applied.
999
    //
1000
    // qpdf_sf_normalize -- tokenize as content stream and normalize tokens
1001
    //
1002
    // decode_level:
1003
    //
1004
    // qpdf_dl_none -- do not decode any streams.
1005
    //
1006
    // qpdf_dl_generalized -- decode supported general-purpose filters. This includes
1007
    // /ASCIIHexDecode, /ASCII85Decode, /LZWDecode, and /FlateDecode.
1008
    //
1009
    // qpdf_dl_specialized -- in addition to generalized filters, also decode supported non-lossy
1010
    // specialized filters. This includes /RunLengthDecode.
1011
    //
1012
    // qpdf_dl_all -- in addition to generalized and non-lossy specialized filters, decode supported
1013
    // lossy filters. This includes /DCTDecode.
1014
    //
1015
    // If, based on the flags and the filters and decode parameters, we determine that we know how
1016
    // to apply all requested filters, do so and return true if we are successful.
1017
    //
1018
    // The exact meaning of the return value differs the different versions of this function, but
1019
    // for any version, the meaning has been the same. For the main version, added in qpdf 10, the
1020
    // return value indicates whether the overall operation succeeded. The filter parameter, if
1021
    // specified, will be set to whether or not filtering was attempted. If filtering was not
1022
    // requested, this value will be false even if the overall operation succeeded.
1023
    //
1024
    // If filtering is requested but this method returns false, it means there was some error in the
1025
    // filtering, in which case the resulting data is likely partially filtered and/or incomplete
1026
    // and may not be consistent with the configured filters. QPDFWriter handles this by attempting
1027
    // to get the stream data without filtering, but callers should consider a false return value
1028
    // when decode_level is not qpdf_dl_none to be a potential loss of data. If you intend to retry
1029
    // in that case, pass true as the value of will_retry. This changes the warning issued by the
1030
    // library to indicate that the operation will be retried without filtering to avoid data loss.
1031
1032
    // Return value is overall success, even if filtering is not requested.
1033
    QPDF_DLL
1034
    bool pipeStreamData(
1035
        Pipeline*,
1036
        bool* filtering_attempted,
1037
        int encode_flags,
1038
        qpdf_stream_decode_level_e decode_level,
1039
        bool suppress_warnings = false,
1040
        bool will_retry = false);
1041
1042
    // Legacy version. Return value is whether filtering was attempted. There is no way to determine
1043
    // success if filtering was not attempted.
1044
    QPDF_DLL
1045
    bool pipeStreamData(
1046
        Pipeline*,
1047
        int encode_flags,
1048
        qpdf_stream_decode_level_e decode_level,
1049
        bool suppress_warnings = false,
1050
        bool will_retry = false);
1051
1052
    // Legacy pipeStreamData. This maps to the the flags-based pipeStreamData as follows:
1053
    //  filter = false                  -> encode_flags = 0
1054
    //  filter = true                   -> decode_level = qpdf_dl_generalized
1055
    //    normalize = true -> encode_flags |= qpdf_sf_normalize
1056
    //    compress = true  -> encode_flags |= qpdf_sf_compress
1057
    // Return value is whether filtering was attempted.
1058
    QPDF_DLL
1059
    bool pipeStreamData(Pipeline*, bool filter, bool normalize, bool compress);
1060
1061
    // Replace a stream's dictionary.  The new dictionary must be consistent with the stream's data.
1062
    // This is most appropriately used when creating streams from scratch that will use a stream
1063
    // data provider and therefore start with an empty dictionary.  It may be more convenient in
1064
    // this case than calling getDict and modifying it for each key.  The pdf-create example does
1065
    // this.
1066
    QPDF_DLL
1067
    void replaceDict(QPDFObjectHandle const&);
1068
1069
    // Test whether a stream is the root XMP /Metadata object of its owning QPDF.
1070
    QPDF_DLL
1071
    bool isRootMetadata() const;
1072
1073
    // REPLACING STREAM DATA
1074
1075
    // Note about all replaceStreamData methods: whatever values are passed as filter and
1076
    // decode_parms will overwrite /Filter and /DecodeParms in the stream. Passing a null object
1077
    // (QPDFObjectHandle::newNull()) will remove those values from the stream dictionary. From qpdf
1078
    // 11, passing an *uninitialized* QPDFObjectHandle (QPDFObjectHandle()) will leave any existing
1079
    // values untouched.
1080
1081
    // Replace this stream's stream data with the given data buffer. The stream's /Length key is
1082
    // replaced with the length of the data buffer. The stream is interpreted as if the data read
1083
    // from the file, after any decryption filters have been applied, is as presented.
1084
    QPDF_DLL
1085
    void replaceStreamData(
1086
        std::shared_ptr<Buffer> data,
1087
        QPDFObjectHandle const& filter,
1088
        QPDFObjectHandle const& decode_parms);
1089
1090
    // Replace the stream's stream data with the given string. This method will create a copy of the
1091
    // data rather than using the user-provided buffer as in the std::shared_ptr<Buffer> version of
1092
    // replaceStreamData.
1093
    QPDF_DLL
1094
    void replaceStreamData(
1095
        std::string const& data,
1096
        QPDFObjectHandle const& filter,
1097
        QPDFObjectHandle const& decode_parms);
1098
1099
    // As above, replace this stream's stream data.  Instead of directly providing a buffer with the
1100
    // stream data, call the given provider's provideStreamData method.  See comments on the
1101
    // StreamDataProvider class (defined above) for details on the method.  The data must be
1102
    // consistent with filter and decode_parms as provided.  Although it is more complex to use this
1103
    // form of replaceStreamData than the one that takes a buffer, it makes it possible to avoid
1104
    // allocating memory for the stream data.  Example programs are provided that use both forms of
1105
    // replaceStreamData.
1106
1107
    // Note about stream length: for any given stream, the provider must provide the same amount of
1108
    // data each time it is called. This is critical for making linearization work properly.
1109
    // Versions of qpdf before 3.0.0 required a length to be specified here.  Starting with
1110
    // version 3.0.0, this is no longer necessary (or permitted).  The first time the stream data
1111
    // provider is invoked for a given stream, the actual length is stored. Subsequent times, it is
1112
    // enforced that the length be the same as the first time.
1113
1114
    // If you have gotten a compile error here while building code that worked with older versions
1115
    // of qpdf, just omit the length parameter.  You can also simplify your code by not having to
1116
    // compute the length in advance.
1117
    QPDF_DLL
1118
    void replaceStreamData(
1119
        std::shared_ptr<StreamDataProvider> provider,
1120
        QPDFObjectHandle const& filter,
1121
        QPDFObjectHandle const& decode_parms);
1122
1123
    // Starting in qpdf 10.2, you can use C++-11 function objects instead of StreamDataProvider.
1124
1125
    // The provider should write the stream data to the pipeline. For a one-liner to replace stream
1126
    // data with the contents of a file, pass QUtil::file_provider(filename) as provider.
1127
    QPDF_DLL
1128
    void replaceStreamData(
1129
        std::function<void(Pipeline*)> provider,
1130
        QPDFObjectHandle const& filter,
1131
        QPDFObjectHandle const& decode_parms);
1132
    // The provider should write the stream data to the pipeline, returning true if it succeeded
1133
    // without errors.
1134
    QPDF_DLL
1135
    void replaceStreamData(
1136
        std::function<bool(Pipeline*, bool suppress_warnings, bool will_retry)> provider,
1137
        QPDFObjectHandle const& filter,
1138
        QPDFObjectHandle const& decode_parms);
1139
1140
    // Access object ID and generation.  For direct objects, return object ID 0.
1141
1142
    // NOTE: Be careful about calling getObjectID() and getGeneration() directly as this can lead to
1143
    // the pattern of depending on object ID or generation without the other.  In general, when
1144
    // keeping track of object IDs, it's better to use QPDFObjGen instead.
1145
1146
    QPDF_DLL
1147
    QPDFObjGen getObjGen() const;
1148
    QPDF_DLL
1149
    int getObjectID() const;
1150
    QPDF_DLL
1151
    int getGeneration() const;
1152
1153
    QPDF_DLL
1154
    std::string unparse() const;
1155
    QPDF_DLL
1156
    std::string unparseResolved() const;
1157
    // For strings only, force binary representation. Otherwise, same as unparse.
1158
    QPDF_DLL
1159
    std::string unparseBinary() const;
1160
1161
    // Return encoded as JSON. The constant JSON::LATEST can be used to specify the latest available
1162
    // JSON version. The JSON is generated as follows:
1163
    // * Arrays, dictionaries, booleans, nulls, integers, and real numbers are represented by their
1164
    //   native JSON types.
1165
    // * Names are encoded as strings representing the canonical representation (after parsing #xx)
1166
    //   and preceded by a slash, just as unparse() returns. For example, the JSON for the
1167
    //   PDF-syntax name /Text#2fPlain would be "/Text/Plain".
1168
    // * Indirect references are encoded as strings containing "obj gen R"
1169
    // * Strings
1170
    //   * JSON v1: Strings are encoded as UTF-8 strings with unrepresentable binary characters
1171
    //     encoded as \uHHHH. Characters in PDF Doc encoding that don't have bidirectional unicode
1172
    //     mappings are not reversible. There is no way to tell the difference between a string that
1173
    //     looks like a name or indirect object from an actual name or indirect object.
1174
    //   * JSON v2:
1175
    //     * Unicode strings and strings encoded with PDF Doc encoding that can be bidirectionally
1176
    //       mapped to Unicode (which is all strings without undefined characters) are represented
1177
    //       as "u:" followed by the UTF-8 encoded string. Example:
1178
    //       "u:potato".
1179
    //     * All other strings are represented as "b:" followed by a hexadecimal encoding of the
1180
    //       string. Example: "b:0102cacb"
1181
    // * Streams
1182
    //   * JSON v1: Only the stream's dictionary is encoded. There is no way to tell a stream from a
1183
    //     dictionary other than context.
1184
    //   * JSON v2: A stream is encoded as {"dict": {...}} with the value being the encoding of the
1185
    //     stream's dictionary. Since "dict" does not otherwise represent anything, this is
1186
    //     unambiguous. The getStreamJSON() call can be used to add encoding of the stream's data.
1187
    // * Object types that are only valid in content streams (inline image, operator) are serialized
1188
    //   as "null". Attempting to serialize a "reserved" object is an error.
1189
    // If dereference_indirect is true and this is an indirect object, show the actual contents of
1190
    // the object. The effect of dereference_indirect applies only to this object. It is not
1191
    // recursive.
1192
    QPDF_DLL
1193
    JSON getJSON(int json_version, bool dereference_indirect = false) const;
1194
1195
    // Write the object encoded as JSON to a pipeline. This is equivalent to, but more efficient
1196
    // than, calling getJSON(json_version, dereference_indirect).write(p, depth). See the
1197
    // documentation for getJSON and JSON::write for further detail.
1198
    QPDF_DLL
1199
    void writeJSON(
1200
        int json_version, Pipeline* p, bool dereference_indirect = false, size_t depth = 0) const;
1201
1202
    // This method can be called on a stream to get a more extended JSON representation of the
1203
    // stream that includes the stream's data. The JSON object returned is always a dictionary whose
1204
    // "dict" key is an encoding of the stream's dictionary. The representation of the data is
1205
    // determined by the json_data field.
1206
    //
1207
    // The json_data field may have the value qpdf_sj_none, qpdf_sj_inline, or qpdf_sj_file.
1208
    //
1209
    // If json_data is qpdf_sj_none, stream data is not represented.
1210
    //
1211
    // If json_data is qpdf_sj_inline or qpdf_sj_file, then stream data is filtered or not based on
1212
    // the value of decode_level, which has the same meaning as with pipeStreamData.
1213
    //
1214
    // If json_data is qpdf_sj_inline, the base64-encoded stream data is included in the "data"
1215
    // field of the dictionary that is returned.
1216
    //
1217
    // If json_data is qpdf_sj_file, then the Pipeline ("p") and data_filename argument must be
1218
    // supplied. The value of data_filename is stored in the resulting json in the "datafile" key
1219
    // but is not otherwise use. The stream data itself (raw or filtered depending on decode level),
1220
    // is written to the pipeline via pipeStreamData().
1221
    //
1222
    // NOTE: When json_data is qpdf_sj_inline, the QPDF object from which the stream originates must
1223
    // remain valid until after the JSON object is written.
1224
    QPDF_DLL
1225
    JSON getStreamJSON(
1226
        int json_version,
1227
        qpdf_json_stream_data_e json_data,
1228
        qpdf_stream_decode_level_e decode_level,
1229
        Pipeline* p,
1230
        std::string const& data_filename);
1231
1232
    // Legacy helper methods for commonly performed operations on pages. Newer code should use
1233
    // QPDFPageObjectHelper instead. The specification and behavior of these methods are the same as
1234
    // the identically named methods in that class, but newer functionality will be added there.
1235
    QPDF_DLL
1236
    std::map<std::string, QPDFObjectHandle> getPageImages();
1237
    QPDF_DLL
1238
    std::vector<QPDFObjectHandle> getPageContents();
1239
    QPDF_DLL
1240
    void addPageContents(QPDFObjectHandle contents, bool first);
1241
    QPDF_DLL
1242
    void rotatePage(int angle, bool relative);
1243
    QPDF_DLL
1244
    void coalesceContentStreams();
1245
    // End legacy page helpers
1246
1247
    // Issue a warning about this object if possible. If the object has a description, a warning
1248
    // will be issued using the owning QPDF as context. Otherwise, a message will be written to the
1249
    // default logger's error stream, which is standard error if not overridden. Objects read
1250
    // normally from the file have descriptions. See comments on setObjectDescription for additional
1251
    // details.
1252
    QPDF_DLL
1253
    void warnIfPossible(std::string const& warning) const;
1254
1255
    // Convenience routine: Throws if the assumption is violated. Your code will be better if you
1256
    // call one of the isType methods and handle the case of the type being wrong, but these can be
1257
    // convenient if you have already verified the type.
1258
    QPDF_DLL
1259
    void assertInitialized() const;
1260
1261
    QPDF_DLL
1262
    void assertNull() const;
1263
    QPDF_DLL
1264
    void assertBool() const;
1265
    QPDF_DLL
1266
    void assertInteger() const;
1267
    QPDF_DLL
1268
    void assertReal() const;
1269
    QPDF_DLL
1270
    void assertName() const;
1271
    QPDF_DLL
1272
    void assertString() const;
1273
    QPDF_DLL
1274
    void assertOperator() const;
1275
    QPDF_DLL
1276
    void assertInlineImage() const;
1277
    QPDF_DLL
1278
    void assertArray() const;
1279
    QPDF_DLL
1280
    void assertDictionary() const;
1281
    QPDF_DLL
1282
    void assertStream() const;
1283
    QPDF_DLL
1284
    void assertReserved() const;
1285
1286
    QPDF_DLL
1287
    void assertIndirect() const;
1288
    QPDF_DLL
1289
    void assertScalar() const;
1290
    QPDF_DLL
1291
    void assertNumber() const;
1292
1293
    // The isPageObject method checks the /Type key of the object. This is not completely reliable
1294
    // as there are some otherwise valid files whose /Type is wrong for page objects. qpdf is
1295
    // slightly more accepting but may still return false here when treating the object as a page
1296
    // would work. Use this sparingly.
1297
    QPDF_DLL
1298
    bool isPageObject() const;
1299
    QPDF_DLL
1300
    bool isPagesObject() const;
1301
    QPDF_DLL
1302
    void assertPageObject() const;
1303
1304
    QPDF_DLL
1305
    bool isFormXObject() const;
1306
1307
    // Indicate if this is an image. If exclude_imagemask is true, don't count image masks as
1308
    // images.
1309
    QPDF_DLL
1310
    bool isImage(bool exclude_imagemask = true) const;
1311
1312
    // The following methods do not form part of the public API and are for internal use only.
1313
1314
    QPDFObjectHandle(std::shared_ptr<QPDFObject> const& obj) :
1315
36.4k
        qpdf::BaseHandle(obj)
1316
36.4k
    {
1317
36.4k
    }
1318
    QPDFObjectHandle(std::shared_ptr<QPDFObject>&& obj) :
1319
2.41M
        qpdf::BaseHandle(std::move(obj))
1320
2.41M
    {
1321
2.41M
    }
1322
    std::shared_ptr<QPDFObject>
1323
    getObj()
1324
0
    {
1325
0
        return obj;
1326
0
    }
1327
1328
    void writeJSON(int json_version, JSON::Writer& p, bool dereference_indirect = false) const;
1329
1330
    inline qpdf::Array as_array(qpdf::typed options = qpdf::typed::any) const;
1331
    inline qpdf::Dictionary as_dictionary(qpdf::typed options = qpdf::typed::any) const;
1332
    inline qpdf::Stream as_stream(qpdf::typed options = qpdf::typed::strict) const;
1333
1334
  private:
1335
    void typeWarning(char const* expected_type, std::string const& warning) const;
1336
    void objectWarning(std::string const& warning) const;
1337
    void assertType(char const* type_name, bool istype) const;
1338
    void makeDirect(uint32_t level, QPDFObjGen::set& visited, bool stop_at_streams);
1339
    void setParsedOffset(qpdf_offset_t offset);
1340
    void parseContentStream_internal(std::string const& description, ParserCallbacks* callbacks);
1341
    static void parseContentStream_data(
1342
        std::string_view stream_data,
1343
        std::string const& description,
1344
        ParserCallbacks* callbacks,
1345
        QPDF* context);
1346
    std::vector<QPDFObjectHandle>
1347
    arrayOrStreamToStreamArray(std::string const& description, std::string& all_description);
1348
    void checkOwnership(QPDFObjectHandle const&) const;
1349
};
1350
1351
#ifndef QPDF_NO_QPDF_STRING
1352
// This is short for QPDFObjectHandle::parse, so you can do
1353
1354
// auto oh = "<< /Key (value) >>"_qpdf;
1355
1356
// If this is causing problems in your code, define QPDF_NO_QPDF_STRING to prevent the declaration
1357
// from being here.
1358
1359
/* clang-format off */
1360
  // Disable formatting for this declaration: emacs font-lock in cc-mode (as of 28.1) treats the rest
1361
  // of the file as a string if clang-format removes the space after "operator", and as of
1362
  // clang-format 15, there's no way to prevent it from doing so.
1363
  QPDF_DLL
1364
  QPDFObjectHandle operator ""_qpdf(char const* v, size_t len);
1365
/* clang-format on */
1366
1367
#endif // QPDF_NO_QPDF_STRING
1368
1369
class QPDFObjectHandle::QPDFDictItems
1370
{
1371
    // This class allows C++-style iteration, including range-for iteration, around dictionaries.
1372
    // You can write
1373
1374
    // for (auto iter: QPDFDictItems(dictionary_obj))
1375
    // {
1376
    //     // iter.first is a string
1377
    //     // iter.second is a QPDFObjectHandle
1378
    // }
1379
1380
    // See examples/pdf-name-number-tree.cc for a demonstration of using this API.
1381
1382
  public:
1383
    QPDF_DLL
1384
    QPDFDictItems(QPDFObjectHandle const& oh);
1385
1386
    class iterator
1387
    {
1388
        friend class QPDFDictItems;
1389
1390
      public:
1391
        typedef std::pair<std::string, QPDFObjectHandle> T;
1392
        using iterator_category = std::bidirectional_iterator_tag;
1393
        using value_type = T;
1394
        using difference_type = long;
1395
        using pointer = T*;
1396
        using reference = T&;
1397
1398
0
        virtual ~iterator() = default;
1399
        QPDF_DLL
1400
        iterator& operator++();
1401
        iterator
1402
        operator++(int)
1403
0
        {
1404
0
            iterator t = *this;
1405
0
            ++(*this);
1406
0
            return t;
1407
0
        }
1408
        QPDF_DLL
1409
        iterator& operator--();
1410
        iterator
1411
        operator--(int)
1412
0
        {
1413
0
            iterator t = *this;
1414
0
            --(*this);
1415
0
            return t;
1416
0
        }
1417
        QPDF_DLL
1418
        reference operator*();
1419
        QPDF_DLL
1420
        pointer operator->();
1421
        QPDF_DLL
1422
        bool operator==(iterator const& other) const;
1423
        bool
1424
        operator!=(iterator const& other) const
1425
0
        {
1426
0
            return !operator==(other);
1427
0
        }
1428
1429
      private:
1430
        iterator(QPDFObjectHandle& oh, bool for_begin);
1431
        void updateIValue();
1432
1433
        class Members
1434
        {
1435
            friend class QPDFDictItems::iterator;
1436
1437
          public:
1438
0
            ~Members() = default;
1439
1440
          private:
1441
            Members(QPDFObjectHandle& oh, bool for_begin);
1442
            Members() = delete;
1443
            Members(Members const&) = delete;
1444
1445
            QPDFObjectHandle& oh;
1446
            std::set<std::string> keys;
1447
            std::set<std::string>::iterator iter;
1448
            bool is_end;
1449
        };
1450
        std::shared_ptr<Members> m;
1451
        value_type ivalue;
1452
    };
1453
1454
    QPDF_DLL
1455
    iterator begin();
1456
    QPDF_DLL
1457
    iterator end();
1458
1459
  private:
1460
    QPDFObjectHandle oh;
1461
};
1462
1463
class QPDFObjectHandle::QPDFArrayItems
1464
{
1465
    // This class allows C++-style iteration, including range-for iteration, around arrays. You can
1466
    // write
1467
1468
    // for (auto iter: QPDFArrayItems(array_obj))
1469
    // {
1470
    //     // iter is a QPDFObjectHandle
1471
    // }
1472
1473
    // See examples/pdf-name-number-tree.cc for a demonstration of using this API.
1474
1475
  public:
1476
    QPDF_DLL
1477
    QPDFArrayItems(QPDFObjectHandle const& oh);
1478
1479
    class iterator
1480
    {
1481
        friend class QPDFArrayItems;
1482
1483
      public:
1484
        typedef QPDFObjectHandle T;
1485
        using iterator_category = std::bidirectional_iterator_tag;
1486
        using value_type = T;
1487
        using difference_type = long;
1488
        using pointer = T*;
1489
        using reference = T&;
1490
1491
0
        virtual ~iterator() = default;
1492
        QPDF_DLL
1493
        iterator& operator++();
1494
        iterator
1495
        operator++(int)
1496
0
        {
1497
0
            iterator t = *this;
1498
0
            ++(*this);
1499
0
            return t;
1500
0
        }
1501
        QPDF_DLL
1502
        iterator& operator--();
1503
        iterator
1504
        operator--(int)
1505
0
        {
1506
0
            iterator t = *this;
1507
0
            --(*this);
1508
0
            return t;
1509
0
        }
1510
        QPDF_DLL
1511
        reference operator*();
1512
        QPDF_DLL
1513
        pointer operator->();
1514
        QPDF_DLL
1515
        bool operator==(iterator const& other) const;
1516
        bool
1517
        operator!=(iterator const& other) const
1518
0
        {
1519
0
            return !operator==(other);
1520
0
        }
1521
1522
      private:
1523
        iterator(QPDFObjectHandle& oh, bool for_begin);
1524
        void updateIValue();
1525
1526
        class Members
1527
        {
1528
            friend class QPDFArrayItems::iterator;
1529
1530
          public:
1531
            ~Members() = default;
1532
1533
          private:
1534
            Members(QPDFObjectHandle& oh, bool for_begin);
1535
            Members() = delete;
1536
            Members(Members const&) = delete;
1537
1538
            QPDFObjectHandle& oh;
1539
            int item_number;
1540
            bool is_end;
1541
        };
1542
        std::shared_ptr<Members> m;
1543
        value_type ivalue;
1544
    };
1545
1546
    QPDF_DLL
1547
    iterator begin();
1548
    QPDF_DLL
1549
    iterator end();
1550
1551
  private:
1552
    QPDFObjectHandle oh;
1553
};
1554
1555
namespace qpdf
1556
{
1557
    inline BaseHandle::
1558
    operator bool() const
1559
7.25M
    {
1560
7.25M
        return static_cast<bool>(obj);
1561
7.25M
    }
1562
1563
    inline BaseHandle::
1564
    operator QPDFObjectHandle() const
1565
3.36k
    {
1566
3.36k
        return {obj};
1567
3.36k
    }
1568
1569
} // namespace qpdf
1570
1571
inline bool
1572
QPDFObjectHandle::isInitialized() const
1573
0
{
1574
0
    return obj != nullptr;
1575
0
}
1576
1577
#endif // QPDFOBJECTHANDLE_HH