qpdf/include/qpdf/qpdf-c.h

1015 lines
42 KiB
C++

/* Copyright (c) 2005-2024 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. Starting with qpdf 11.7, it is possible to write your own `extern "C"` functions that
* interoperate with the C API.
*
* 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 many operations, 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. You can write your own `extern "C"` functions in
* C++ that interoperate with the C API by using qpdf_c_get_qpdf and qpdf_c_wrap which were
* introduced in qpdf 11.7.0.
*
* 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.
*
* Since it is possible for a PDF string to contain null characters, a function that returns
* data originating from a PDF string may also contain null characters. To handle that case, you
* call qpdf_get_last_string_length() to get the length of whatever string was just returned.
* See STRING FUNCTIONS below.
*
* 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/Constants.h>
#include <qpdf/DLL.h>
#include <qpdf/Types.h>
#include <qpdf/qpdflogger-c.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. This is guaranteed to be a static value.
*/
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, one of the other qpdf_read_* functions, or qpdf_empty_pdf 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);
/* 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);
/* LOG FUNCTIONS */
/* Set or get the current logger. You need to call qpdflogger_cleanup on the logger handles when
* you are done with the handles. The underlying logger is cleaned up automatically and persists
* if needed after the logger handle is destroyed. See comments in qpdflogger-c.h for details.
*/
QPDF_DLL
void qpdf_set_logger(qpdf_data qpdf, qpdflogger_handle logger);
QPDF_DLL
qpdflogger_handle qpdf_get_logger(qpdf_data qpdf);
/* 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 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);
/* PROCESS FUNCTIONS */
/* This functions process a PDF or JSON input source. */
/* 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);
/* Calling qpdf_empty_pdf initializes this qpdf object with an empty PDF, making it possible to
* create a PDF from scratch using the C API. Added in 10.6.
*/
QPDF_DLL
QPDF_ERROR_CODE qpdf_empty_pdf(qpdf_data qpdf);
/* Create a PDF from a JSON file. This calls createFromJSON in the C++ API.
*/
QPDF_DLL
QPDF_ERROR_CODE
qpdf_create_from_json_file(qpdf_data qpdf, char const* filename);
/* Create a PDF from JSON data in a null-terminated string. This calls createFromJSON in the C++
* API.
*/
QPDF_DLL
QPDF_ERROR_CODE
qpdf_create_from_json_data(qpdf_data qpdf, char const* buffer, unsigned long long size);
/* JSON UPDATE FUNCTIONS */
/* Update a QPDF object from a JSON file or buffer. These functions call updateFromJSON. One of
* the other processing functions has to be called first so that the QPDF object is initialized
* with PDF data.
*/
QPDF_DLL
QPDF_ERROR_CODE
qpdf_update_from_json_file(qpdf_data qpdf, char const* filename);
QPDF_DLL
QPDF_ERROR_CODE
qpdf_update_from_json_data(qpdf_data qpdf, char const* buffer, unsigned long long size);
/* READ FUNCTIONS */
/* Read functions below must be called after qpdf_read or any of the other functions that
* process a PDF. */
/*
* 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);
/* JSON WRITE FUNCTIONS */
/* This function serializes the PDF to JSON. This calls writeJSON from the C++ API.
*
* - version: the JSON version, currently must be 2
* - fn: a function that will be called with blocks of JSON data; will be called with data, a
* length, and the value of the udata parameter to this function
* - udata: will be passed as the third argument to fn with each call; use this for your own
* tracking or pass a null pointer if you don't need it
* - For decode_level, json_stream_data, file_prefix, and wanted_objects, see comments in
* QPDF.hh. For this API, wanted_objects should be a null-terminated array of null-terminated
* strings. Pass a null pointer if you want all objects.
*/
/* Function should return 0 on success. */
typedef int (*qpdf_write_fn_t)(char const* data, size_t len, void* udata);
QPDF_DLL
QPDF_ERROR_CODE qpdf_write_json(
qpdf_data qpdf,
int version,
qpdf_write_fn_t fn,
void* udata,
enum qpdf_stream_decode_level_e decode_level,
enum qpdf_json_stream_data_e json_stream_data,
char const* file_prefix,
char const* const* wanted_objects);
/* 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);
/* The *_insecure functions are identical to the old versions but have been renamed as a an
* alert to the caller that they are insecure. See "Weak Cryptographic" in the manual for
* details.
*/
QPDF_DLL
void qpdf_set_r2_encryption_parameters_insecure(
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_parameters_insecure(
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_parameters_insecure(
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);
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 referring 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. Note that names are to appear in a canonicalized form starting with a leading
* slash and with all PDF escaping resolved. See comments for getName() in QPDFObjectHandle.hh
* for details.
*/
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
QPDF_BOOL
qpdf_oh_is_name_and_equals(qpdf_data qpdf, qpdf_oh oh, char const* name);
QPDF_DLL
QPDF_BOOL qpdf_oh_is_dictionary_of_type(
qpdf_data qpdf, qpdf_oh oh, char const* type, char const* subtype);
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
QPDF_BOOL
qpdf_oh_get_value_as_bool(qpdf_data qpdf, qpdf_oh oh, QPDF_BOOL* value);
QPDF_DLL
long long qpdf_oh_get_int_value(qpdf_data qpdf, qpdf_oh oh);
QPDF_DLL
QPDF_BOOL
qpdf_oh_get_value_as_longlong(qpdf_data qpdf, qpdf_oh oh, long long* value);
QPDF_DLL
int qpdf_oh_get_int_value_as_int(qpdf_data qpdf, qpdf_oh oh);
QPDF_DLL
QPDF_BOOL qpdf_oh_get_value_as_int(qpdf_data qpdf, qpdf_oh oh, int* value);
QPDF_DLL
unsigned long long qpdf_oh_get_uint_value(qpdf_data qpdf, qpdf_oh oh);
QPDF_DLL
QPDF_BOOL qpdf_oh_get_value_as_ulonglong(qpdf_data qpdf, qpdf_oh oh, unsigned long long* value);
QPDF_DLL
unsigned int qpdf_oh_get_uint_value_as_uint(qpdf_data qpdf, qpdf_oh oh);
QPDF_DLL
QPDF_BOOL
qpdf_oh_get_value_as_uint(qpdf_data qpdf, qpdf_oh oh, unsigned int* value);
QPDF_DLL
char const* qpdf_oh_get_real_value(qpdf_data qpdf, qpdf_oh oh);
QPDF_DLL
QPDF_BOOL
qpdf_oh_get_value_as_real(qpdf_data qpdf, qpdf_oh oh, char const** value, size_t* length);
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
QPDF_BOOL
qpdf_oh_get_value_as_number(qpdf_data qpdf, qpdf_oh oh, double* value);
QPDF_DLL
char const* qpdf_oh_get_name(qpdf_data qpdf, qpdf_oh oh);
QPDF_DLL
QPDF_BOOL
qpdf_oh_get_value_as_name(qpdf_data qpdf, qpdf_oh oh, char const** value, size_t* length);
/* 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. The function qpdf_oh_get_binary_string_value takes a length
* pointer, which can be useful if you are retrieving the value of a string that is expected to
* contain binary data, such as a checksum or document ID. It is always valid to call
* qpdf_get_last_string_length, but it is usually not necessary as C strings returned by the
* library are only expected to be able to contain null characters if their values originate
* from PDF strings in the input.
*/
QPDF_DLL
size_t qpdf_get_last_string_length(qpdf_data qpdf);
QPDF_DLL
char const* qpdf_oh_get_string_value(qpdf_data qpdf, qpdf_oh oh);
QPDF_DLL
QPDF_BOOL
qpdf_oh_get_value_as_string(qpdf_data qpdf, qpdf_oh oh, char const** value, size_t* length);
QPDF_DLL
char const* qpdf_oh_get_utf8_value(qpdf_data qpdf, qpdf_oh oh);
QPDF_DLL
QPDF_BOOL
qpdf_oh_get_value_as_utf8(qpdf_data qpdf, qpdf_oh oh, char const** value, size_t* length);
QPDF_DLL
char const* qpdf_oh_get_binary_string_value(qpdf_data qpdf, qpdf_oh oh, size_t* length);
QPDF_DLL
char const* qpdf_oh_get_binary_utf8_value(qpdf_data qpdf, qpdf_oh oh, size_t* length);
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);
/* In all dictionary APIs, keys are specified/represented as canonicalized name strings starting
* with / and with all PDF escaping resolved. See comments for getName() in QPDFObjectHandle for
* details.
*/
/* "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_oh qpdf_oh_get_key_if_dict(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);
/* Use qpdf_oh_new_binary_string for creating a string that may contain arbitrary binary data
* including embedded null characters.
*/
QPDF_DLL
qpdf_oh qpdf_oh_new_binary_string(qpdf_data qpdf, char const* str, size_t length);
QPDF_DLL
qpdf_oh qpdf_oh_new_binary_unicode_string(qpdf_data qpdf, char const* str, size_t length);
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
}
// These C++ functions make it easier to write C++ code that interoperates with the C API.
// See examples/extend-c-api.
# include <functional>
# include <memory>
# include <qpdf/QPDF.hh>
// Retrieve the real QPDF object attached to this qpdf_data.
QPDF_DLL
std::shared_ptr<QPDF> qpdf_c_get_qpdf(qpdf_data qpdf);
// Wrap a C++ function that may throw an exception to translate the exception for retrieval using
// the normal QPDF C API methods.
QPDF_DLL
QPDF_ERROR_CODE qpdf_c_wrap(qpdf_data qpdf, std::function<void()> fn);
#endif
#endif /* QPDF_C_H */