aboutsummaryrefslogtreecommitdiffstats
path: root/include/qpdf/qpdf-c.h
blob: e261c7c14c85a7c2271b34c3be4520d6c2b454b7 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
/* Copyright (c) 2005-2021 Jay Berkenbilt
 *
 * This file is part of qpdf.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Versions of qpdf prior to version 7 were released under the terms
 * of version 2.0 of the Artistic License. At your option, you may
 * continue to consider qpdf to be licensed under those terms. Please
 * see the manual for additional information.
 */

#ifndef QPDF_C_H
#define QPDF_C_H

/*
 * This file defines a basic "C" API for qpdf.  It provides access to
 * a subset of the QPDF library's capabilities to make them accessible
 * to callers who can't handle calling C++ functions or working with
 * C++ classes.  This may be especially useful to Windows users who
 * are accessing the qpdf DLL directly or to other people programming
 * in non-C/C++ languages that can call C code but not C++ code.
 *
 * There are several things to keep in mind when using the C API.
 *
 *     Error handling is tricky because the underlying C++ API uses
 *     exception handling. See "ERROR HANDLING" below for a detailed
 *     explanation.
 *
 *     The C API is not as rich as the C++ API.  For any operations
 *     that involve actually manipulating PDF objects, you must use
 *     the C++ API.  The C API is primarily useful for doing basic
 *     transformations on PDF files similar to what you might do with
 *     the qpdf command-line tool.
 *
 *     These functions store their state in a qpdf_data object.
 *     Individual instances of qpdf_data are not thread-safe: although
 *     you may access different qpdf_data objects from different
 *     threads, you may not access one qpdf_data simultaneously from
 *     multiple threads.
 *
 *     All dynamic memory, except for that of the qpdf_data object
 *     itself, is managed by the library unless otherwise noted. You
 *     must create a qpdf_data object using qpdf_init and free it
 *     using qpdf_cleanup.
 *
 *     Many functions return char*. In all cases, the char* values
 *     returned are pointers to data inside the qpdf_data object. As
 *     such, they are always freed by qpdf_cleanup. In most cases,
 *     strings returned by functions here may be invalidated by
 *     subsequent function calls, sometimes even to different
 *     functions. If you want a string to last past the next qpdf call
 *     or after a call to qpdf_cleanup, you should make a copy of it.
 *     It is possible for the internal string data to contain null
 *     characters. To handle that case, you call
 *     qpdf_get_last_string_length() to get the length of whatever
 *     string was just returned.
 *
 *     Most functions defined here have obvious counterparts that are
 *     methods to either QPDF or QPDFWriter.  Please see comments in
 *     QPDF.hh and QPDFWriter.hh for details on their use.  In order
 *     to avoid duplication of information, comments here focus
 *     primarily on differences between the C and C++ API.
 */

/* ERROR HANDLING -- changed in qpdf 10.5 */

/* SUMMARY: The only way to know whether a function that does not
 * return an error code has encountered an error is to call
 * qpdf_has_error after each function. You can do this even for
 * functions that do return error codes. You can also call
 * qpdf_silence_errors to prevent qpdf from writing these errors to
 * stderr.
 *
 * DETAILS:
 *
 * The data type underlying qpdf_data maintains a list of warnings and
 * a single error. To retrieve warnings, call qpdf_next_warning while
 * qpdf_more_warnings is true. To retrieve the error, call
 * qpdf_get_error when qpdf_has_error is true.
 *
 * There are several things that are important to understand.
 *
 * Some functions return an error code. The value of the error code is
 * made up of a bitwise-OR of QPDF_WARNINGS and QPDF_ERRORS. The
 * QPDF_ERRORS bit is set if there was an error during the *most
 * recent call* to the API. The QPDF_WARNINGS bit is set if there are
 * any warnings that have not yet been retrieved by calling
 * qpdf_more_warnings. It is possible for both its or neither bit to
 * be set.
 *
 * The expected mode of operation is to go through a series of
 * operations, checking for errors after each call, but only checking
 * for warnings at the end. This is similar to how it works in the C++
 * API where warnings are handled in exactly this way but errors
 * result in exceptions being thrown. However, in both the C and C++
 * API, it is possible to check for and handle warnings as they arise.
 *
 * Some functions return values (or void) rather than an error code.
 * This is especially true with the object handling functions. Those
 * functions can still generate errors. To handle errors in those
 * cases, you should explicitly call qpdf_has_error(). Note that, if
 * you want to avoid the inconsistencies in the interface, you can
 * always check for error conditions in this way rather than looking
 * at status return codes.
 *
 * Prior to qpdf 10.5, if one of the functions that does not return an
 * error code encountered an exception, it would cause the entire
 * program to crash. Starting in qpdf 10.5, the default response to an
 * error condition in these situations is to print the error to
 * standard error, issue exactly one warning indicating that such an
 * error occurred, and return a sensible fallback value (0 for
 * numbers, QPDF_FALSE for booleans, "" for strings, or a null or
 * uninitialized object handle). This is better than the old behavior
 * but still undesirable as the best option is to explicitly check for
 * error conditions.
 *
 * To prevent qpdf from writing error messages to stderr in this way,
 * you can call qpdf_silence_errors(). This signals to the qpdf
 * library that you intend to check the error codes yourself.
 *
 * If you encounter a situation where an exception from the C++ code
 * is not properly converted to an error as described above, it is a
 * bug in qpdf, which should be reported at
 * https://github.com/qpdf/qpdf/issues/new.
 */

#include <qpdf/DLL.h>
#include <qpdf/Types.h>
#include <qpdf/Constants.h>
#include <string.h>

#ifdef __cplusplus
extern "C" {
#endif

    typedef struct _qpdf_data* qpdf_data;
    typedef struct _qpdf_error* qpdf_error;

    /* Many functions return an integer error code.  Codes are defined
     * below.  See comments at the top of the file for details.  Note
     * that the values below can be logically orred together.
     */
    typedef int QPDF_ERROR_CODE;
#   define QPDF_SUCCESS 0
#   define QPDF_WARNINGS 1 << 0
#   define QPDF_ERRORS 1 << 1

    typedef int QPDF_BOOL;
#   define QPDF_TRUE 1
#   define QPDF_FALSE 0

    /* From qpdf 10.5: call this method to signal to the library that
     * you are explicitly handling errors from functions that don't
     * return error codes. Otherwise, the library will print these
     * error conditions to stderr and issue a warning. Prior to 10.5,
     * the program would have crashed from an unhandled exception.
     */
    QPDF_DLL
    void qpdf_silence_errors(qpdf_data qpdf);

    /* Returns the version of the qpdf software */
    QPDF_DLL
    char const* qpdf_get_qpdf_version();

    /* Returns dynamically allocated qpdf_data pointer; must be freed
     * by calling qpdf_cleanup. You must call qpdf_read or one of the
     * other qpdf_read_* functions before calling any function that
     * would need to operate on the PDF file.
     */
    QPDF_DLL
    qpdf_data qpdf_init();

    /* Pass a pointer to the qpdf_data pointer created by qpdf_init to
     * clean up resources. This does not include buffers initialized
     * by functions that return stream data but it otherwise includes
     * all data associated with the QPDF object or any object handles.
     */
    QPDF_DLL
    void qpdf_cleanup(qpdf_data* qpdf);

    /* Return the length of the last string returned. This enables you
     * to retrieve the entire string for cases in which a char*
     * returned by one of the functions below points to a string with
     * embedded null characters.
     */
    QPDF_DLL
    size_t qpdf_get_last_string_length(qpdf_data qpdf);

    /* ERROR REPORTING */

    /* Returns 1 if there is an error condition.  The error condition
     * can be retrieved by a single call to qpdf_get_error.
     */
    QPDF_DLL
    QPDF_BOOL qpdf_has_error(qpdf_data qpdf);

    /* Returns the error condition, if any.  The return value is a
     * pointer to data that will become invalid after the next call to
     * this function, qpdf_next_warning, or qpdf_cleanup.  After this
     * function is called, qpdf_has_error will return QPDF_FALSE until
     * the next error condition occurs.  If there is no error
     * condition, this function returns a null pointer.
     */
    QPDF_DLL
    qpdf_error qpdf_get_error(qpdf_data qpdf);

    /* Returns 1 if there are any unretrieved warnings, and zero
     * otherwise.
     */
    QPDF_DLL
    QPDF_BOOL qpdf_more_warnings(qpdf_data qpdf);

    /* If there are any warnings, returns a pointer to the next
     * warning.  Otherwise returns a null pointer.
     */
    QPDF_DLL
    qpdf_error qpdf_next_warning(qpdf_data qpdf);

    /* Extract fields of the error. */

    /* Use this function to get a full error message suitable for
     * showing to the user. */
    QPDF_DLL
    char const* qpdf_get_error_full_text(qpdf_data q, qpdf_error e);

    /* Use these functions to extract individual fields from the
     * error; see QPDFExc.hh for details. */
    QPDF_DLL
    enum qpdf_error_code_e qpdf_get_error_code(qpdf_data q, qpdf_error e);
    QPDF_DLL
    char const* qpdf_get_error_filename(qpdf_data q, qpdf_error e);
    QPDF_DLL
    unsigned long long qpdf_get_error_file_position(qpdf_data q, qpdf_error e);
    QPDF_DLL
    char const* qpdf_get_error_message_detail(qpdf_data q, qpdf_error e);

    /* By default, warnings are written to stderr.  Passing true to
     * this function will prevent warnings from being written to
     * stderr.  They will still be available by calls to
     * qpdf_next_warning.
     */
    QPDF_DLL
    void qpdf_set_suppress_warnings(qpdf_data qpdf, QPDF_BOOL value);

    /* CHECK FUNCTIONS */

    /* Attempt to read the entire PDF file to see if there are any
     * errors qpdf can detect.
     */
    QPDF_DLL
    QPDF_ERROR_CODE qpdf_check_pdf(qpdf_data qpdf);

    /* READ FUNCTIONS */

    /* READ PARAMETER FUNCTIONS -- must be called before qpdf_read */

    QPDF_DLL
    void qpdf_set_ignore_xref_streams(qpdf_data qpdf, QPDF_BOOL value);

    QPDF_DLL
    void qpdf_set_attempt_recovery(qpdf_data qpdf, QPDF_BOOL value);

    /* Calling qpdf_read causes processFile to be called in the C++
     * API.  Basic parsing is performed, but data from the file is
     * only read as needed.  For files without passwords, pass a null
     * pointer or an empty string as the password.
     */
    QPDF_DLL
    QPDF_ERROR_CODE qpdf_read(qpdf_data qpdf, char const* filename,
			      char const* password);

    /* Calling qpdf_read_memory causes processMemoryFile to be called
     * in the C++ API.  Otherwise, it behaves in the same way as
     * qpdf_read.  The description argument will be used in place of
     * the file name in any error or warning messages generated by the
     * library.
     */
    QPDF_DLL
    QPDF_ERROR_CODE qpdf_read_memory(qpdf_data qpdf,
				     char const* description,
				     char const* buffer,
				     unsigned long long size,
				     char const* password);

    /* Read functions below must be called after qpdf_read or
     * qpdf_read_memory. */

    /*
     * NOTE: Functions that return char* are returning a pointer to an
     * internal buffer that will be reused for each call to a function
     * that returns a char*.  You must use or copy the value before
     * calling any other qpdf library functions.
     */

    /* Return the version of the PDF file.  See warning above about
     * functions that return char*. */
    QPDF_DLL
    char const* qpdf_get_pdf_version(qpdf_data qpdf);

    /* Return the extension level of the PDF file. */
    QPDF_DLL
    int qpdf_get_pdf_extension_level(qpdf_data qpdf);

    /* Return the user password.  If the file is opened using the
     * owner password, the user password may be retrieved using this
     * function.  If the file is opened using the user password, this
     * function will return that user password.  See warning above
     * about functions that return char*.
     */
    QPDF_DLL
    char const* qpdf_get_user_password(qpdf_data qpdf);

    /* Return the string value of a key in the document's Info
     * dictionary.  The key parameter should include the leading
     * slash, e.g. "/Author".  If the key is not present or has a
     * non-string value, a null pointer is returned.  Otherwise, a
     * pointer to an internal buffer is returned.  See warning above
     * about functions that return char*.
     */
    QPDF_DLL
    char const* qpdf_get_info_key(qpdf_data qpdf, char const* key);

    /* Set a value in the info dictionary, possibly replacing an
     * existing value.  The key must include the leading slash
     * (e.g. "/Author").  Passing a null pointer as a value will
     * remove the key from the info dictionary.  Otherwise, a copy
     * will be made of the string that is passed in.
     */
    QPDF_DLL
    void qpdf_set_info_key(qpdf_data qpdf, char const* key, char const* value);

    /* Indicate whether the input file is linearized. */
    QPDF_DLL
    QPDF_BOOL qpdf_is_linearized(qpdf_data qpdf);

    /* Indicate whether the input file is encrypted. */
    QPDF_DLL
    QPDF_BOOL qpdf_is_encrypted(qpdf_data qpdf);

    QPDF_DLL
    QPDF_BOOL qpdf_allow_accessibility(qpdf_data qpdf);
    QPDF_DLL
    QPDF_BOOL qpdf_allow_extract_all(qpdf_data qpdf);
    QPDF_DLL
    QPDF_BOOL qpdf_allow_print_low_res(qpdf_data qpdf);
    QPDF_DLL
    QPDF_BOOL qpdf_allow_print_high_res(qpdf_data qpdf);
    QPDF_DLL
    QPDF_BOOL qpdf_allow_modify_assembly(qpdf_data qpdf);
    QPDF_DLL
    QPDF_BOOL qpdf_allow_modify_form(qpdf_data qpdf);
    QPDF_DLL
    QPDF_BOOL qpdf_allow_modify_annotation(qpdf_data qpdf);
    QPDF_DLL
    QPDF_BOOL qpdf_allow_modify_other(qpdf_data qpdf);
    QPDF_DLL
    QPDF_BOOL qpdf_allow_modify_all(qpdf_data qpdf);

    /* WRITE FUNCTIONS */

    /* Set up for writing.  No writing is actually performed until the
     * call to qpdf_write().
     */

    /* Supply the name of the file to be written and initialize the
     * qpdf_data object to handle writing operations.  This function
     * also attempts to create the file.  The PDF data is not written
     * until the call to qpdf_write.  qpdf_init_write may be called
     * multiple times for the same qpdf_data object.  When
     * qpdf_init_write is called, all information from previous calls
     * to functions that set write parameters (qpdf_set_linearization,
     * etc.) is lost, so any write parameter functions must be called
     * again.
     */
    QPDF_DLL
    QPDF_ERROR_CODE qpdf_init_write(qpdf_data qpdf, char const* filename);

    /* Initialize for writing but indicate that the PDF file should be
     * written to memory.  Call qpdf_get_buffer_length and
     * qpdf_get_buffer to retrieve the resulting buffer.  The memory
     * containing the PDF file will be destroyed when qpdf_cleanup is
     * called.
     */
    QPDF_DLL
    QPDF_ERROR_CODE qpdf_init_write_memory(qpdf_data qpdf);

    /* Retrieve the buffer used if the file was written to memory.
     * qpdf_get_buffer returns a null pointer if data was not written
     * to memory.  The memory is freed when qpdf_cleanup is called or
     * if a subsequent call to qpdf_init_write or
     * qpdf_init_write_memory is called. */
    QPDF_DLL
    size_t qpdf_get_buffer_length(qpdf_data qpdf);
    QPDF_DLL
    unsigned char const* qpdf_get_buffer(qpdf_data qpdf);

    QPDF_DLL
    void qpdf_set_object_stream_mode(qpdf_data qpdf,
				     enum qpdf_object_stream_e mode);

    QPDF_DLL
    void qpdf_set_stream_data_mode(qpdf_data qpdf,
				   enum qpdf_stream_data_e mode);

    QPDF_DLL
    void qpdf_set_compress_streams(qpdf_data qpdf, QPDF_BOOL value);


    QPDF_DLL
    void qpdf_set_decode_level(qpdf_data qpdf,
                               enum qpdf_stream_decode_level_e level);

    QPDF_DLL
    void qpdf_set_preserve_unreferenced_objects(
        qpdf_data qpdf, QPDF_BOOL value);

    QPDF_DLL
    void qpdf_set_newline_before_endstream(qpdf_data qpdf, QPDF_BOOL value);

    QPDF_DLL
    void qpdf_set_content_normalization(qpdf_data qpdf, QPDF_BOOL value);

    QPDF_DLL
    void qpdf_set_qdf_mode(qpdf_data qpdf, QPDF_BOOL value);

    QPDF_DLL
    void qpdf_set_deterministic_ID(qpdf_data qpdf, QPDF_BOOL value);

    /* Never use qpdf_set_static_ID except in test suites to suppress
     * generation of a random /ID.  See also qpdf_set_deterministic_ID.
     */
    QPDF_DLL
    void qpdf_set_static_ID(qpdf_data qpdf, QPDF_BOOL value);

    /* Never use qpdf_set_static_aes_IV except in test suites to
     * create predictable AES encrypted output.
     */
    QPDF_DLL
    void qpdf_set_static_aes_IV(qpdf_data qpdf, QPDF_BOOL value);

    QPDF_DLL
    void qpdf_set_suppress_original_object_IDs(
	qpdf_data qpdf, QPDF_BOOL value);

    QPDF_DLL
    void qpdf_set_preserve_encryption(qpdf_data qpdf, QPDF_BOOL value);

    QPDF_DLL
    void qpdf_set_r2_encryption_parameters(
	qpdf_data qpdf, char const* user_password, char const* owner_password,
	QPDF_BOOL allow_print, QPDF_BOOL allow_modify,
	QPDF_BOOL allow_extract, QPDF_BOOL allow_annotate);

    QPDF_DLL
    void qpdf_set_r3_encryption_parameters2(
	qpdf_data qpdf, char const* user_password, char const* owner_password,
	QPDF_BOOL allow_accessibility, QPDF_BOOL allow_extract,
        QPDF_BOOL allow_assemble, QPDF_BOOL allow_annotate_and_form,
        QPDF_BOOL allow_form_filling, QPDF_BOOL allow_modify_other,
	enum qpdf_r3_print_e print);

    QPDF_DLL
    void qpdf_set_r4_encryption_parameters2(
	qpdf_data qpdf, char const* user_password, char const* owner_password,
	QPDF_BOOL allow_accessibility, QPDF_BOOL allow_extract,
        QPDF_BOOL allow_assemble, QPDF_BOOL allow_annotate_and_form,
        QPDF_BOOL allow_form_filling, QPDF_BOOL allow_modify_other,
	enum qpdf_r3_print_e print,
        QPDF_BOOL encrypt_metadata, QPDF_BOOL use_aes);

    QPDF_DLL
    void qpdf_set_r5_encryption_parameters2(
	qpdf_data qpdf, char const* user_password, char const* owner_password,
	QPDF_BOOL allow_accessibility, QPDF_BOOL allow_extract,
        QPDF_BOOL allow_assemble, QPDF_BOOL allow_annotate_and_form,
        QPDF_BOOL allow_form_filling, QPDF_BOOL allow_modify_other,
	enum qpdf_r3_print_e print, QPDF_BOOL encrypt_metadata);

    QPDF_DLL
    void qpdf_set_r6_encryption_parameters2(
	qpdf_data qpdf, char const* user_password, char const* owner_password,
	QPDF_BOOL allow_accessibility, QPDF_BOOL allow_extract,
        QPDF_BOOL allow_assemble, QPDF_BOOL allow_annotate_and_form,
        QPDF_BOOL allow_form_filling, QPDF_BOOL allow_modify_other,
	enum qpdf_r3_print_e print, QPDF_BOOL encrypt_metadata);

    /* Pre 8.4.0 encryption API */
    QPDF_DLL
    void qpdf_set_r3_encryption_parameters(
	qpdf_data qpdf, char const* user_password, char const* owner_password,
	QPDF_BOOL allow_accessibility, QPDF_BOOL allow_extract,
	enum qpdf_r3_print_e print, enum qpdf_r3_modify_e modify);

    QPDF_DLL
    void qpdf_set_r4_encryption_parameters(
	qpdf_data qpdf, char const* user_password, char const* owner_password,
	QPDF_BOOL allow_accessibility, QPDF_BOOL allow_extract,
	enum qpdf_r3_print_e print, enum qpdf_r3_modify_e modify,
	QPDF_BOOL encrypt_metadata, QPDF_BOOL use_aes);

    QPDF_DLL
    void qpdf_set_r5_encryption_parameters(
	qpdf_data qpdf, char const* user_password, char const* owner_password,
	QPDF_BOOL allow_accessibility, QPDF_BOOL allow_extract,
	enum qpdf_r3_print_e print, enum qpdf_r3_modify_e modify,
	QPDF_BOOL encrypt_metadata);

    QPDF_DLL
    void qpdf_set_r6_encryption_parameters(
	qpdf_data qpdf, char const* user_password, char const* owner_password,
	QPDF_BOOL allow_accessibility, QPDF_BOOL allow_extract,
	enum qpdf_r3_print_e print, enum qpdf_r3_modify_e modify,
	QPDF_BOOL encrypt_metadata);

    QPDF_DLL
    void qpdf_set_linearization(qpdf_data qpdf, QPDF_BOOL value);

    QPDF_DLL
    void qpdf_set_minimum_pdf_version(qpdf_data qpdf, char const* version);

    QPDF_DLL
    void qpdf_set_minimum_pdf_version_and_extension(
        qpdf_data qpdf, char const* version, int extension_level);

    QPDF_DLL
    void qpdf_force_pdf_version(qpdf_data qpdf, char const* version);

    QPDF_DLL
    void qpdf_force_pdf_version_and_extension(
        qpdf_data qpdf, char const* version, int extension_level);

    /* During write, your report_progress function will be called with
     * a value between 0 and 100 representing the approximate write
     * progress. The data object you pass to
     * qpdf_register_progress_reporter will be handed back to your
     * function. This function must be called after qpdf_init_write
     * (or qpdf_init_write_memory) and before qpdf_write. The
     * registered progress reporter applies only to a single write, so
     * you must call it again if you perform a subsequent write with a
     * new writer.
     */
    QPDF_DLL
    void qpdf_register_progress_reporter(
        qpdf_data qpdf,
        void (*report_progress)(int percent, void* data),
        void* data);

    /* Do actual write operation. */
    QPDF_DLL
    QPDF_ERROR_CODE qpdf_write(qpdf_data qpdf);

    /* Object handling.
     *
     * These functions take and return a qpdf_oh object handle, which
     * is just an unsigned integer. The value 0 is never returned, which
     * makes it usable as an uninitialized value. The handles returned by
     * these functions are guaranteed to be unique, i.e. two calls to
     * (the same of different) functions will return distinct handles
     * even when they refer to the same object.
     *
     * Each function below, starting with qpdf_oh, corresponds to a
     * specific method of QPDFObjectHandler. For example,
     * qpdf_oh_is_bool corresponds to QPDFObjectHandle::isBool. If the
     * C++ method is overloaded, the C function's name will be
     * disambiguated. If the C++ method takes optional arguments, the C
     * function will have required arguments in those positions. For
     * details about the method, please see comments in
     * QPDFObjectHandle.hh. Comments here only explain things that are
     * specific to the "C" API.
     *
     * Only a fraction of the methods of QPDFObjectHandle are
     * available here. Most of the basic methods for creating,
     * accessing, and modifying most types of objects are present.
     * Most of the higher-level functions are not implemented.
     * Functions for dealing with content streams as well as objects
     * that only exist in content streams (operators and inline
     * images) are mostly not provided.
     *
     * To refer to a specific QPDFObjectHandle, you need a pair
     * consisting of a qpdf_data and a qpdf_oh, which is just an index
     * into an internal table of objects. All memory allocated by any
     * of these functions is returned when qpdf_cleanup is called.
     *
     * Regarding memory, the same rules apply as the above functions.
     * Specifically, if a function returns a char*, the memory is
     * managed by the library and, unless otherwise specified, is not
     * expected to be valid after the next qpdf call.
     *
     * The qpdf_data object keeps a cache of handles returned by these
     * functions. Once you are finished referencing a handle, you can
     * optionally release it. Releasing handles is optional since they
     * will all get released by qpdf_cleanup, but it can help to
     * reduce the memory footprint of the qpdf_data object to release
     * them when you're done. Releasing a handle does not destroy the
     * object. All QPDFObjectHandle objects are deleted when they are
     * no longer referenced. Releasing an object handle simply
     * invalidates it. For example, if you create an object,
     * add it to an existing dictionary or array, and then release its
     * handle, the object is safely part of the dictionary or array.
     * Similarly, any other object handle refering to the object remains
     * valid. Explicitly releasing an object handle is essentially the
     * same as letting a QPDFObjectHandle go out of scope in the C++
     * API.
     *
     * Please see "ERROR HANDLING" above for details on how error
     * conditions are handled.
     */

    /* For examples of using this API, see examples/pdf-c-objects.c */

    typedef unsigned int qpdf_oh;

    /* Releasing objects -- see comments above. These functions have no
     * equivalent in the C++ API.
     */
    QPDF_DLL
    void qpdf_oh_release(qpdf_data qpdf, qpdf_oh oh);
    QPDF_DLL
    void qpdf_oh_release_all(qpdf_data qpdf);

    /* Clone an object handle */
    QPDF_DLL
    qpdf_oh qpdf_oh_new_object(qpdf_data qpdf, qpdf_oh oh);

    /* Get trailer and root objects */
    QPDF_DLL
    qpdf_oh qpdf_get_trailer(qpdf_data qpdf);
    QPDF_DLL
    qpdf_oh qpdf_get_root(qpdf_data qpdf);

    /* Retrieve and replace indirect objects */
    QPDF_DLL
    qpdf_oh qpdf_get_object_by_id(qpdf_data qpdf, int objid, int generation);
    QPDF_DLL
    qpdf_oh qpdf_make_indirect_object(qpdf_data qpdf, qpdf_oh oh);
    QPDF_DLL
    void qpdf_replace_object(
        qpdf_data qpdf, int objid, int generation, qpdf_oh oh);

    /* Wrappers around QPDFObjectHandle methods. Be sure to read
     * corresponding comments in QPDFObjectHandle.hh to understand
     * what each function does and what kinds of objects it applies
     * to.
     */

    QPDF_DLL
    QPDF_BOOL qpdf_oh_is_initialized(qpdf_data qpdf, qpdf_oh oh);
    QPDF_DLL
    QPDF_BOOL qpdf_oh_is_bool(qpdf_data qpdf, qpdf_oh oh);
    QPDF_DLL
    QPDF_BOOL qpdf_oh_is_null(qpdf_data qpdf, qpdf_oh oh);
    QPDF_DLL
    QPDF_BOOL qpdf_oh_is_integer(qpdf_data qpdf, qpdf_oh oh);
    QPDF_DLL
    QPDF_BOOL qpdf_oh_is_real(qpdf_data qpdf, qpdf_oh oh);
    QPDF_DLL
    QPDF_BOOL qpdf_oh_is_name(qpdf_data qpdf, qpdf_oh oh);
    QPDF_DLL
    QPDF_BOOL qpdf_oh_is_string(qpdf_data qpdf, qpdf_oh oh);
    QPDF_DLL
    QPDF_BOOL qpdf_oh_is_operator(qpdf_data qpdf, qpdf_oh oh);
    QPDF_DLL
    QPDF_BOOL qpdf_oh_is_inline_image(qpdf_data qpdf, qpdf_oh oh);
    QPDF_DLL
    QPDF_BOOL qpdf_oh_is_array(qpdf_data qpdf, qpdf_oh oh);
    QPDF_DLL
    QPDF_BOOL qpdf_oh_is_dictionary(qpdf_data qpdf, qpdf_oh oh);
    QPDF_DLL
    QPDF_BOOL qpdf_oh_is_stream(qpdf_data qpdf, qpdf_oh oh);
    QPDF_DLL
    QPDF_BOOL qpdf_oh_is_indirect(qpdf_data qpdf, qpdf_oh oh);
    QPDF_DLL
    QPDF_BOOL qpdf_oh_is_scalar(qpdf_data qpdf, qpdf_oh oh);
    QPDF_DLL
    enum qpdf_object_type_e qpdf_oh_get_type_code(qpdf_data qpdf, qpdf_oh oh);
    QPDF_DLL
    char const* qpdf_oh_get_type_name(qpdf_data qpdf, qpdf_oh oh);

    QPDF_DLL
    qpdf_oh qpdf_oh_wrap_in_array(qpdf_data qpdf, qpdf_oh oh);

    QPDF_DLL
    qpdf_oh qpdf_oh_parse(qpdf_data qpdf, char const* object_str);

    QPDF_DLL
    QPDF_BOOL qpdf_oh_get_bool_value(qpdf_data qpdf, qpdf_oh oh);

    QPDF_DLL
    long long qpdf_oh_get_int_value(qpdf_data qpdf, qpdf_oh oh);
    QPDF_DLL
    int qpdf_oh_get_int_value_as_int(qpdf_data qpdf, qpdf_oh oh);
    QPDF_DLL
    unsigned long long qpdf_oh_get_uint_value(qpdf_data qpdf, qpdf_oh oh);
    QPDF_DLL
    unsigned int qpdf_oh_get_uint_value_as_uint(qpdf_data qpdf, qpdf_oh oh);

    QPDF_DLL
    char const* qpdf_oh_get_real_value(qpdf_data qpdf, qpdf_oh oh);

    QPDF_DLL
    QPDF_BOOL qpdf_oh_is_number(qpdf_data qpdf, qpdf_oh oh);
    QPDF_DLL
    double qpdf_oh_get_numeric_value(qpdf_data qpdf, qpdf_oh oh);

    QPDF_DLL
    char const* qpdf_oh_get_name(qpdf_data qpdf, qpdf_oh oh);

    QPDF_DLL
    char const* qpdf_oh_get_string_value(qpdf_data qpdf, qpdf_oh oh);
    QPDF_DLL
    char const* qpdf_oh_get_utf8_value(qpdf_data qpdf, qpdf_oh oh);

    QPDF_DLL
    int qpdf_oh_get_array_n_items(qpdf_data qpdf, qpdf_oh oh);
    QPDF_DLL
    qpdf_oh qpdf_oh_get_array_item(qpdf_data qpdf, qpdf_oh oh, int n);

    /* "C"-specific dictionary key iteration */

    /* Iteration is allowed on only one dictionary at a time. */
    QPDF_DLL
    void qpdf_oh_begin_dict_key_iter(qpdf_data qpdf, qpdf_oh dict);
    QPDF_DLL
    QPDF_BOOL qpdf_oh_dict_more_keys(qpdf_data qpdf);
    /* The memory returned by qpdf_oh_dict_next_key is owned by
     * qpdf_data. It is good until the next call to
     * qpdf_oh_dict_next_key with the same qpdf_data object. Calling
     * the function again, even with a different dict, invalidates
     * previous return values.
     */
    QPDF_DLL
    char const* qpdf_oh_dict_next_key(qpdf_data qpdf);

    /* end "C"-specific dictionary key iteration */

    QPDF_DLL
    QPDF_BOOL qpdf_oh_has_key(qpdf_data qpdf, qpdf_oh oh, char const* key);
    QPDF_DLL
    qpdf_oh qpdf_oh_get_key(qpdf_data qpdf, qpdf_oh oh, char const* key);

    QPDF_DLL
    QPDF_BOOL qpdf_oh_is_or_has_name(
        qpdf_data qpdf, qpdf_oh oh, char const* key);

    QPDF_DLL
    qpdf_oh qpdf_oh_new_uninitialized(qpdf_data qpdf);
    QPDF_DLL
    qpdf_oh qpdf_oh_new_null(qpdf_data qpdf);
    QPDF_DLL
    qpdf_oh qpdf_oh_new_bool(qpdf_data qpdf, QPDF_BOOL value);
    QPDF_DLL
    qpdf_oh qpdf_oh_new_integer(qpdf_data qpdf, long long value);
    QPDF_DLL
    qpdf_oh qpdf_oh_new_real_from_string(qpdf_data qpdf, char const* value);
    QPDF_DLL
    qpdf_oh qpdf_oh_new_real_from_double(qpdf_data qpdf,
                                         double value, int decimal_places);
    QPDF_DLL
    qpdf_oh qpdf_oh_new_name(qpdf_data qpdf, char const* name);
    QPDF_DLL
    qpdf_oh qpdf_oh_new_string(qpdf_data qpdf, char const* str);
    QPDF_DLL
    qpdf_oh qpdf_oh_new_unicode_string(qpdf_data qpdf, char const* utf8_str);
    QPDF_DLL
    qpdf_oh qpdf_oh_new_array(qpdf_data qpdf);
    QPDF_DLL
    qpdf_oh qpdf_oh_new_dictionary(qpdf_data qpdf);

    /* Create a new stream. Use qpdf_oh_get_dict to get (and
     * subsequently modify) the stream dictionary if needed. See
     * comments in QPDFObjectHandle.hh for newStream() for additional
     * notes. You must call qpdf_oh_replace_stream_data to provide
     * data for the stream. See STREAM FUNCTIONS below.
    */
    QPDF_DLL
    qpdf_oh qpdf_oh_new_stream(qpdf_data qpdf);

    QPDF_DLL
    void qpdf_oh_make_direct(qpdf_data qpdf, qpdf_oh oh);

    QPDF_DLL
    void qpdf_oh_set_array_item(qpdf_data qpdf, qpdf_oh oh,
                                int at, qpdf_oh item);
    QPDF_DLL
    void qpdf_oh_insert_item(qpdf_data qpdf, qpdf_oh oh, int at, qpdf_oh item);
    QPDF_DLL
    void qpdf_oh_append_item(qpdf_data qpdf, qpdf_oh oh, qpdf_oh item);
    QPDF_DLL
    void qpdf_oh_erase_item(qpdf_data qpdf, qpdf_oh oh, int at);

    QPDF_DLL
    void qpdf_oh_replace_key(qpdf_data qpdf, qpdf_oh oh,
                             char const* key, qpdf_oh item);
    QPDF_DLL
    void qpdf_oh_remove_key(qpdf_data qpdf, qpdf_oh oh, char const* key);
    QPDF_DLL
    void qpdf_oh_replace_or_remove_key(qpdf_data qpdf, qpdf_oh oh,
                                       char const* key, qpdf_oh item);

    QPDF_DLL
    qpdf_oh qpdf_oh_get_dict(qpdf_data qpdf, qpdf_oh oh);

    QPDF_DLL
    int qpdf_oh_get_object_id(qpdf_data qpdf, qpdf_oh oh);
    QPDF_DLL
    int qpdf_oh_get_generation(qpdf_data qpdf, qpdf_oh oh);

    QPDF_DLL
    char const* qpdf_oh_unparse(qpdf_data qpdf, qpdf_oh oh);
    QPDF_DLL
    char const* qpdf_oh_unparse_resolved(qpdf_data qpdf, qpdf_oh oh);
    QPDF_DLL
    char const* qpdf_oh_unparse_binary(qpdf_data qpdf, qpdf_oh oh);

    /* Note about foreign objects: the C API does not have enough
     * information in the value of a qpdf_oh to know what QPDF object
     * it belongs to. To uniquely specify a qpdf object handle from a
     * specific qpdf_data instance, you always pair the qpdf_oh with
     * the correct qpdf_data. Otherwise, you are likely to get
     * completely the wrong object if you are not lucky enough to get
     * an error about the object being invalid.
     */

    /* Copy foreign object: the qpdf_oh returned belongs to `qpdf`,
     * while `foreign_oh` belongs to `other_qpdf`.
     */
    QPDF_DLL
    qpdf_oh qpdf_oh_copy_foreign_object(
        qpdf_data qpdf, qpdf_data other_qpdf, qpdf_oh foreign_oh);

    /* STREAM FUNCTIONS */

    /* These functions provide basic access to streams and stream
     * data. They are not as comprehensive as what is in
     * QPDFObjectHandle, but they do allow for working with streams
     * and stream data as caller-managed memory.
     */

    /* Get stream data as a buffer. The buffer is allocated with
     * malloc and must be freed by the caller. The size of the buffer
     * is stored in *len. The arguments are similar to those in
     * QPDFObjectHandle::pipeStreamData. To get raw stream data, pass
     * qpdf_dl_none as decode_level. Otherwise, filtering is attempted
     * and *filtered is set to indicate whether it was successful. If
     * *filtered is QPDF_FALSE, then raw, unfiltered stream data was
     * returned. You may pass a null pointer as filtered if you don't
     * care about the result. If you pass a null pointer as bufp (and
     * len), the value of filtered will be set to whether the stream
     * can be filterable.
     */
    QPDF_DLL
    QPDF_ERROR_CODE qpdf_oh_get_stream_data(
        qpdf_data qpdf, qpdf_oh stream_oh,
        enum qpdf_stream_decode_level_e decode_level, QPDF_BOOL* filtered,
        unsigned char** bufp, size_t* len);

    /* This function returns the concatenation of all of a page's
     * content streams as a single, dynamically allocated buffer. As
     * with qpdf_oh_get_stream_data, the buffer is allocated with
     * malloc and must be freed by the caller.
     */
    QPDF_DLL
    QPDF_ERROR_CODE qpdf_oh_get_page_content_data(
        qpdf_data qpdf, qpdf_oh page_oh,
        unsigned char** bufp, size_t* len);

    /* The data pointed to by bufp will be copied by the library. It
     * does not need to remain valid after the call returns.
     */
    QPDF_DLL
    void qpdf_oh_replace_stream_data(
        qpdf_data qpdf, qpdf_oh stream_oh,
        unsigned char const* buf, size_t len,
        qpdf_oh filter, qpdf_oh decode_parms);

    /* PAGE FUNCTIONS */

    /* The first time a page function is called, qpdf will traverse
     * the /Pages tree. Subsequent calls to retrieve the number of
     * pages or a specific page run in constant time as they are
     * accessing the pages cache. If you manipulate the page tree
     * outside of these functions, you should call
     * qpdf_update_all_pages_cache. See comments for getAllPages() and
     * updateAllPagesCache() in QPDF.hh.
     */

    /* For each function, the corresponding method in QPDF.hh is
     * referenced. Please see comments in QPDF.hh for details.
     */

    /* calls getAllPages(). On error, returns -1 and sets error for
     * qpdf_get_error. */
    QPDF_DLL
    int qpdf_get_num_pages(qpdf_data qpdf);
    /* returns uninitialized object if out of range */
    QPDF_DLL
    qpdf_oh qpdf_get_page_n(qpdf_data qpdf, size_t zero_based_index);

    /* updateAllPagesCache() */
    QPDF_DLL
    QPDF_ERROR_CODE qpdf_update_all_pages_cache(qpdf_data qpdf);

    /* findPage() -- return zero-based index. If page is not found,
     * return -1 and save the error to be retrieved with
     * qpdf_get_error.
     */
    QPDF_DLL
    int qpdf_find_page_by_id(qpdf_data qpdf, int objid, int generation);
    QPDF_DLL
    int qpdf_find_page_by_oh(qpdf_data qpdf, qpdf_oh oh);

    /* pushInheritedAttributesToPage() */
    QPDF_DLL
    QPDF_ERROR_CODE qpdf_push_inherited_attributes_to_page(qpdf_data qpdf);

    /* Functions that add pages may add pages from other files. If
     * adding a page from the same file, newpage_qpdf and qpdf are the
     * same.
     /*/

    /* addPage() */
    QPDF_DLL
    QPDF_ERROR_CODE qpdf_add_page(
        qpdf_data qpdf,
        qpdf_data newpage_qpdf, qpdf_oh newpage,
        QPDF_BOOL first);
    /* addPageAt() */
    QPDF_DLL
    QPDF_ERROR_CODE qpdf_add_page_at(
        qpdf_data qpdf,
        qpdf_data newpage_qpdf, qpdf_oh newpage,
        QPDF_BOOL before, qpdf_oh refpage);
    /* removePage() */
    QPDF_DLL
    QPDF_ERROR_CODE qpdf_remove_page(qpdf_data qpdf, qpdf_oh page);
#ifdef __cplusplus
}
#endif


#endif /* QPDF_C_H */