Add support for mov video dan always use faststart to video format
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
#include <jni.h>
|
||||
#include <string>
|
||||
#include <cerrno>
|
||||
|
||||
#include "compressor_common.h"
|
||||
#include "video_compressor.h"
|
||||
@@ -7,6 +8,8 @@
|
||||
|
||||
extern "C" {
|
||||
#include <libavcodec/avcodec.h>
|
||||
#include <libavcodec/bsf.h>
|
||||
#include <libavutil/error.h>
|
||||
}
|
||||
|
||||
static std::string jstring_to_string(JNIEnv *env, jstring value, const char *fallback) {
|
||||
@@ -24,6 +27,42 @@ static std::string jstring_to_string(JNIEnv *env, jstring value, const char *fal
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static bool is_mediacodec_encoder_name(const std::string &encoder) {
|
||||
return encoder == "h264_mediacodec" ||
|
||||
encoder == "hevc_mediacodec";
|
||||
}
|
||||
|
||||
static const char *required_mediacodec_bsf_name(const std::string &encoder) {
|
||||
if (encoder == "h264_mediacodec") {
|
||||
return "h264_mp4toannexb";
|
||||
}
|
||||
|
||||
if (encoder == "hevc_mediacodec") {
|
||||
return "hevc_mp4toannexb";
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static bool required_mediacodec_bsf_available(const std::string &encoder) {
|
||||
const char *bsf_name = required_mediacodec_bsf_name(encoder);
|
||||
if (!bsf_name) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return av_bsf_get_by_name(bsf_name) != nullptr;
|
||||
}
|
||||
|
||||
static std::string fallback_cpu_encoder_for(const std::string &encoder) {
|
||||
if (encoder == "hevc_mediacodec" && avcodec_find_encoder_by_name("libx265")) {
|
||||
return "libx265";
|
||||
}
|
||||
|
||||
return "libx264";
|
||||
}
|
||||
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_com_kikyps_kcompressor_NativeCompressor_isVideoEncoderAvailable(JNIEnv *env,
|
||||
@@ -36,7 +75,19 @@ Java_com_kikyps_kcompressor_NativeCompressor_isVideoEncoderAvailable(JNIEnv *env
|
||||
}
|
||||
|
||||
const AVCodec *codec = avcodec_find_encoder_by_name(encoder.c_str());
|
||||
return codec ? JNI_TRUE : JNI_FALSE;
|
||||
if (!codec) {
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
// MediaCodec encoder di FFmpeg membutuhkan bitstream filter tertentu.
|
||||
// Jika FFmpeg static build dibuat dengan --disable-bsfs atau BSF terkait tidak di-enable,
|
||||
// avcodec_open2() dapat gagal dengan: "Bitstream filter not found".
|
||||
if (is_mediacodec_encoder_name(encoder) &&
|
||||
!required_mediacodec_bsf_available(encoder)) {
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
return JNI_TRUE;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
@@ -71,6 +122,21 @@ Java_com_kikyps_kcompressor_NativeCompressor_compressFd(JNIEnv *env,
|
||||
encoder = "libx264";
|
||||
}
|
||||
|
||||
if (is_mediacodec_encoder_name(encoder) &&
|
||||
!required_mediacodec_bsf_available(encoder)) {
|
||||
std::string old_encoder = encoder;
|
||||
encoder = fallback_cpu_encoder_for(old_encoder);
|
||||
|
||||
callback_progress(
|
||||
env,
|
||||
callback,
|
||||
0,
|
||||
std::string("Hardware GPU tidak aktif: FFmpeg build belum menyertakan bitstream filter ") +
|
||||
required_mediacodec_bsf_name(old_encoder) +
|
||||
". Fallback ke CPU."
|
||||
);
|
||||
}
|
||||
|
||||
if (targetShortSide < 0) targetShortSide = 0;
|
||||
|
||||
if (crf < 0) crf = 26;
|
||||
@@ -88,6 +154,9 @@ Java_com_kikyps_kcompressor_NativeCompressor_compressFd(JNIEnv *env,
|
||||
audioBitrate = 128000;
|
||||
}
|
||||
|
||||
const std::string requested_encoder = encoder;
|
||||
const bool requested_hardware_encoder = is_mediacodec_encoder_name(requested_encoder);
|
||||
|
||||
reset_cancel_requested();
|
||||
|
||||
int ret = compress_video_fd_impl(
|
||||
@@ -105,6 +174,158 @@ Java_com_kikyps_kcompressor_NativeCompressor_compressFd(JNIEnv *env,
|
||||
callback
|
||||
);
|
||||
|
||||
// Runtime fallback:
|
||||
// Beberapa device/FFmpeg build terlihat punya encoder MediaCodec,
|
||||
// tetapi avcodec_open2() tetap gagal, misalnya:
|
||||
// "Bitstream filter not found" atau error vendor MediaCodec.
|
||||
// Dalam kondisi ini, ulangi otomatis memakai CPU agar compress tidak gagal total.
|
||||
if (ret < 0 && requested_hardware_encoder && !is_cancel_requested()) {
|
||||
std::string cpu_encoder = fallback_cpu_encoder_for(requested_encoder);
|
||||
|
||||
callback_progress(
|
||||
env,
|
||||
callback,
|
||||
0,
|
||||
std::string("Hardware GPU gagal. Fallback otomatis ke ") +
|
||||
cpu_encoder +
|
||||
"."
|
||||
);
|
||||
|
||||
reset_cancel_requested();
|
||||
|
||||
ret = compress_video_fd_impl(
|
||||
env,
|
||||
static_cast<int>(inputFd),
|
||||
static_cast<int>(outputFd),
|
||||
static_cast<int>(targetShortSide),
|
||||
static_cast<int>(inputRotationDegrees),
|
||||
static_cast<int>(crf),
|
||||
0,
|
||||
cpu_encoder,
|
||||
preset_str,
|
||||
audio_mode,
|
||||
static_cast<int>(audioBitrate),
|
||||
callback
|
||||
);
|
||||
}
|
||||
|
||||
return static_cast<jint>(ret);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_com_kikyps_kcompressor_NativeCompressor_compressFdToPath(JNIEnv *env,
|
||||
jclass,
|
||||
jint inputFd,
|
||||
jstring outputPath,
|
||||
jint targetShortSide,
|
||||
jint inputRotationDegrees,
|
||||
jint crf,
|
||||
jint videoBitrate,
|
||||
jstring encoderName,
|
||||
jstring preset,
|
||||
jstring audioMode,
|
||||
jint audioBitrate,
|
||||
jobject callback) {
|
||||
std::string output_path = jstring_to_string(env, outputPath, "");
|
||||
std::string encoder = jstring_to_string(env, encoderName, "libx264");
|
||||
std::string preset_str = jstring_to_string(env, preset, "medium");
|
||||
std::string audio_mode = jstring_to_string(env, audioMode, "copy");
|
||||
|
||||
if (output_path.empty()) {
|
||||
callback_progress(env, callback, 0, "Output temp path kosong");
|
||||
return static_cast<jint>(AVERROR(EINVAL));
|
||||
}
|
||||
|
||||
if (encoder != "libx264" &&
|
||||
encoder != "libx265" &&
|
||||
encoder != "h264_mediacodec" &&
|
||||
encoder != "hevc_mediacodec") {
|
||||
encoder = "libx264";
|
||||
}
|
||||
|
||||
if (is_mediacodec_encoder_name(encoder) &&
|
||||
!required_mediacodec_bsf_available(encoder)) {
|
||||
std::string old_encoder = encoder;
|
||||
encoder = fallback_cpu_encoder_for(old_encoder);
|
||||
|
||||
callback_progress(
|
||||
env,
|
||||
callback,
|
||||
0,
|
||||
std::string("Hardware GPU tidak lengkap di build FFmpeg. Fallback ke ") +
|
||||
encoder +
|
||||
"."
|
||||
);
|
||||
}
|
||||
|
||||
if (targetShortSide < 0) targetShortSide = 0;
|
||||
|
||||
if (crf < 0) crf = 26;
|
||||
if (crf > 51) crf = 51;
|
||||
|
||||
if (videoBitrate < 0) {
|
||||
videoBitrate = 0;
|
||||
}
|
||||
|
||||
if (audio_mode != "copy" && audio_mode != "aac" && audio_mode != "mute") {
|
||||
audio_mode = "copy";
|
||||
}
|
||||
|
||||
if (audioBitrate <= 0) {
|
||||
audioBitrate = 128000;
|
||||
}
|
||||
|
||||
const std::string requested_encoder = encoder;
|
||||
const bool requested_hardware_encoder = is_mediacodec_encoder_name(requested_encoder);
|
||||
|
||||
reset_cancel_requested();
|
||||
|
||||
int ret = compress_video_fd_to_path_impl(
|
||||
env,
|
||||
static_cast<int>(inputFd),
|
||||
output_path,
|
||||
static_cast<int>(targetShortSide),
|
||||
static_cast<int>(inputRotationDegrees),
|
||||
static_cast<int>(crf),
|
||||
static_cast<int>(videoBitrate),
|
||||
encoder,
|
||||
preset_str,
|
||||
audio_mode,
|
||||
static_cast<int>(audioBitrate),
|
||||
callback
|
||||
);
|
||||
|
||||
if (ret < 0 && requested_hardware_encoder && !is_cancel_requested()) {
|
||||
std::string cpu_encoder = fallback_cpu_encoder_for(requested_encoder);
|
||||
|
||||
callback_progress(
|
||||
env,
|
||||
callback,
|
||||
0,
|
||||
std::string("Hardware GPU gagal. Fallback otomatis ke ") +
|
||||
cpu_encoder +
|
||||
"."
|
||||
);
|
||||
|
||||
reset_cancel_requested();
|
||||
|
||||
ret = compress_video_fd_to_path_impl(
|
||||
env,
|
||||
static_cast<int>(inputFd),
|
||||
output_path,
|
||||
static_cast<int>(targetShortSide),
|
||||
static_cast<int>(inputRotationDegrees),
|
||||
static_cast<int>(crf),
|
||||
0,
|
||||
cpu_encoder,
|
||||
preset_str,
|
||||
audio_mode,
|
||||
static_cast<int>(audioBitrate),
|
||||
callback
|
||||
);
|
||||
}
|
||||
|
||||
return static_cast<jint>(ret);
|
||||
}
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,60 @@
|
||||
/* Version ID for the JPEG library.
|
||||
* Might be useful for tests like "#if JPEG_LIB_VERSION >= 60".
|
||||
*/
|
||||
#define JPEG_LIB_VERSION 80
|
||||
|
||||
/* libjpeg-turbo version */
|
||||
#define LIBJPEG_TURBO_VERSION 3.1.90
|
||||
|
||||
/* libjpeg-turbo version in integer form */
|
||||
#define LIBJPEG_TURBO_VERSION_NUMBER 3001090
|
||||
|
||||
/* Support arithmetic encoding when using 8-bit samples */
|
||||
#define C_ARITH_CODING_SUPPORTED 1
|
||||
|
||||
/* Support arithmetic decoding when using 8-bit samples */
|
||||
#define D_ARITH_CODING_SUPPORTED 1
|
||||
|
||||
/* Support in-memory source/destination managers */
|
||||
#define MEM_SRCDST_SUPPORTED 1
|
||||
|
||||
/* Use accelerated SIMD routines when using 8-bit samples */
|
||||
/* #undef WITH_SIMD */
|
||||
|
||||
/* This version of libjpeg-turbo supports run-time selection of data precision,
|
||||
* so BITS_IN_JSAMPLE is no longer used to specify the data precision at build
|
||||
* time. However, some downstream software expects the macro to be defined.
|
||||
* Since 12-bit data precision is an opt-in feature that requires explicitly
|
||||
* calling 12-bit-specific libjpeg API functions and using 12-bit-specific data
|
||||
* types, the unmodified portion of the libjpeg API still behaves as if it were
|
||||
* built for 8-bit precision, and JSAMPLE is still literally an 8-bit data
|
||||
* type. Thus, it is correct to define BITS_IN_JSAMPLE to 8 here.
|
||||
*/
|
||||
#ifndef BITS_IN_JSAMPLE
|
||||
#define BITS_IN_JSAMPLE 8
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#undef RIGHT_SHIFT_IS_UNSIGNED
|
||||
|
||||
/* Define "boolean" as unsigned char, not int, per Windows custom */
|
||||
#ifndef __RPCNDR_H__ /* don't conflict if rpcndr.h already read */
|
||||
typedef unsigned char boolean;
|
||||
#endif
|
||||
#define HAVE_BOOLEAN /* prevent jmorecfg.h from redefining it */
|
||||
|
||||
/* Define "INT32" as int, not long, per Windows custom */
|
||||
#if !(defined(_BASETSD_H_) || defined(_BASETSD_H)) /* don't conflict if basetsd.h already read */
|
||||
typedef short INT16;
|
||||
typedef signed int INT32;
|
||||
#endif
|
||||
#define XMD_H /* prevent jmorecfg.h from redefining it */
|
||||
|
||||
#else
|
||||
|
||||
/* Define if your (broken) compiler shifts signed values as if they were
|
||||
unsigned. */
|
||||
/* #undef RIGHT_SHIFT_IS_UNSIGNED */
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,336 @@
|
||||
/*
|
||||
* jerror.h
|
||||
*
|
||||
* This file was part of the Independent JPEG Group's software:
|
||||
* Copyright (C) 1994-1997, Thomas G. Lane.
|
||||
* Modified 1997-2009 by Guido Vollbeding.
|
||||
* Lossless JPEG Modifications:
|
||||
* Copyright (C) 1999, Ken Murchison.
|
||||
* libjpeg-turbo Modifications:
|
||||
* Copyright (C) 2014, 2017, 2021-2023, 2026, D. R. Commander.
|
||||
* For conditions of distribution and use, see the accompanying README.ijg
|
||||
* file.
|
||||
*
|
||||
* This file defines the error and message codes for the JPEG library.
|
||||
* Edit this file to add new codes, or to translate the message strings to
|
||||
* some other language.
|
||||
* A set of error-reporting macros are defined too. Some applications using
|
||||
* the JPEG library may wish to include this file to get the error codes
|
||||
* and/or the macros.
|
||||
*/
|
||||
|
||||
/*
|
||||
* To define the enum list of message codes, include this file without
|
||||
* defining macro JMESSAGE. To create a message string table, include it
|
||||
* again with a suitable JMESSAGE definition (see jerror.c for an example).
|
||||
*/
|
||||
#ifndef JMESSAGE
|
||||
#ifndef JERROR_H
|
||||
/* First time through, define the enum list */
|
||||
#define JMAKE_ENUM_LIST
|
||||
#else
|
||||
/* Repeated inclusions of this file are no-ops unless JMESSAGE is defined */
|
||||
#define JMESSAGE(code, string)
|
||||
#endif /* JERROR_H */
|
||||
#endif /* JMESSAGE */
|
||||
|
||||
#ifdef JMAKE_ENUM_LIST
|
||||
|
||||
typedef enum {
|
||||
|
||||
#define JMESSAGE(code, string) code,
|
||||
|
||||
#endif /* JMAKE_ENUM_LIST */
|
||||
|
||||
JMESSAGE(JMSG_NOMESSAGE, "Bogus message code %d") /* Must be first entry! */
|
||||
|
||||
/* For maintenance convenience, list is alphabetical by message code name */
|
||||
#if JPEG_LIB_VERSION < 70
|
||||
JMESSAGE(JERR_ARITH_NOTIMPL, "Sorry, arithmetic coding is not implemented")
|
||||
#endif
|
||||
JMESSAGE(JERR_BAD_ALIGN_TYPE, "ALIGN_TYPE is wrong, please fix")
|
||||
JMESSAGE(JERR_BAD_ALLOC_CHUNK, "MAX_ALLOC_CHUNK is wrong, please fix")
|
||||
JMESSAGE(JERR_BAD_BUFFER_MODE, "Bogus buffer control mode")
|
||||
JMESSAGE(JERR_BAD_COMPONENT_ID, "Invalid component ID %d in SOS")
|
||||
#if JPEG_LIB_VERSION >= 70
|
||||
JMESSAGE(JERR_BAD_CROP_SPEC, "Invalid crop request")
|
||||
#endif
|
||||
JMESSAGE(JERR_BAD_DCT_COEF,
|
||||
"DCT coefficient (lossy) or spatial difference (lossless) out of range")
|
||||
JMESSAGE(JERR_BAD_DCTSIZE, "IDCT output block size %d not supported")
|
||||
#if JPEG_LIB_VERSION >= 70
|
||||
JMESSAGE(JERR_BAD_DROP_SAMPLING,
|
||||
"Component index %d: mismatching sampling ratio %d:%d, %d:%d, %c")
|
||||
#endif
|
||||
JMESSAGE(JERR_BAD_HUFF_TABLE, "Bogus Huffman table definition")
|
||||
JMESSAGE(JERR_BAD_IN_COLORSPACE, "Bogus input colorspace")
|
||||
JMESSAGE(JERR_BAD_J_COLORSPACE, "Bogus JPEG colorspace")
|
||||
JMESSAGE(JERR_BAD_LENGTH, "Bogus marker length")
|
||||
JMESSAGE(JERR_BAD_LIB_VERSION,
|
||||
"Wrong JPEG library version: library is %d, caller expects %d")
|
||||
JMESSAGE(JERR_BAD_MCU_SIZE, "Sampling factors too large for interleaved scan")
|
||||
JMESSAGE(JERR_BAD_POOL_ID, "Invalid memory pool code %d")
|
||||
JMESSAGE(JERR_BAD_PRECISION, "Unsupported JPEG data precision %d")
|
||||
JMESSAGE(JERR_BAD_PROGRESSION,
|
||||
"Invalid progressive/lossless parameters Ss=%d Se=%d Ah=%d Al=%d")
|
||||
JMESSAGE(JERR_BAD_PROG_SCRIPT,
|
||||
"Invalid progressive/lossless parameters at scan script entry %d")
|
||||
JMESSAGE(JERR_BAD_SAMPLING, "Bogus sampling factors")
|
||||
JMESSAGE(JERR_BAD_SCAN_SCRIPT, "Invalid scan script at entry %d")
|
||||
JMESSAGE(JERR_BAD_STATE, "Improper call to JPEG library in state %d")
|
||||
JMESSAGE(JERR_BAD_STRUCT_SIZE,
|
||||
"JPEG parameter struct mismatch: library thinks size is %u, caller expects %u")
|
||||
JMESSAGE(JERR_BAD_VIRTUAL_ACCESS, "Bogus virtual array access")
|
||||
JMESSAGE(JERR_BUFFER_SIZE, "Buffer passed to JPEG library is too small")
|
||||
JMESSAGE(JERR_CANT_SUSPEND, "Suspension not allowed here")
|
||||
JMESSAGE(JERR_CCIR601_NOTIMPL, "CCIR601 sampling not implemented yet")
|
||||
JMESSAGE(JERR_COMPONENT_COUNT, "Too many color components: %d, max %d")
|
||||
JMESSAGE(JERR_CONVERSION_NOTIMPL, "Unsupported color conversion request")
|
||||
JMESSAGE(JERR_DAC_INDEX, "Bogus DAC index %d")
|
||||
JMESSAGE(JERR_DAC_VALUE, "Bogus DAC value 0x%x")
|
||||
JMESSAGE(JERR_DHT_INDEX, "Bogus DHT index %d")
|
||||
JMESSAGE(JERR_DQT_INDEX, "Bogus DQT index %d")
|
||||
JMESSAGE(JERR_EMPTY_IMAGE, "Empty JPEG image (DNL not supported)")
|
||||
JMESSAGE(JERR_EMS_READ, "Read from EMS failed")
|
||||
JMESSAGE(JERR_EMS_WRITE, "Write to EMS failed")
|
||||
JMESSAGE(JERR_EOI_EXPECTED, "Didn't expect more than one scan")
|
||||
JMESSAGE(JERR_FILE_READ, "Input file read error")
|
||||
JMESSAGE(JERR_FILE_WRITE, "Output file write error --- out of disk space?")
|
||||
JMESSAGE(JERR_FRACT_SAMPLE_NOTIMPL, "Fractional sampling not implemented yet")
|
||||
JMESSAGE(JERR_HUFF_CLEN_OVERFLOW, "Huffman code size table overflow")
|
||||
JMESSAGE(JERR_HUFF_MISSING_CODE, "Missing Huffman code table entry")
|
||||
JMESSAGE(JERR_IMAGE_TOO_BIG, "Maximum supported image dimension is %u pixels")
|
||||
JMESSAGE(JERR_INPUT_EMPTY, "Empty input file")
|
||||
JMESSAGE(JERR_INPUT_EOF, "Premature end of input file")
|
||||
JMESSAGE(JERR_MISMATCHED_QUANT_TABLE,
|
||||
"Cannot transcode due to multiple use of quantization table %d")
|
||||
JMESSAGE(JERR_MISSING_DATA, "Scan script does not transmit all data")
|
||||
JMESSAGE(JERR_MODE_CHANGE, "Invalid color quantization mode change")
|
||||
JMESSAGE(JERR_NOTIMPL, "Requested features are incompatible")
|
||||
JMESSAGE(JERR_NOT_COMPILED, "Requested feature was omitted at compile time")
|
||||
#if JPEG_LIB_VERSION >= 70
|
||||
JMESSAGE(JERR_NO_ARITH_TABLE, "Arithmetic table 0x%02x was not defined")
|
||||
#endif
|
||||
JMESSAGE(JERR_NO_BACKING_STORE, "Memory limit exceeded")
|
||||
JMESSAGE(JERR_NO_HUFF_TABLE, "Huffman table 0x%02x was not defined")
|
||||
JMESSAGE(JERR_NO_IMAGE, "JPEG datastream contains no image")
|
||||
JMESSAGE(JERR_NO_QUANT_TABLE, "Quantization table 0x%02x was not defined")
|
||||
JMESSAGE(JERR_NO_SOI, "Not a JPEG file: starts with 0x%02x 0x%02x")
|
||||
JMESSAGE(JERR_OUT_OF_MEMORY, "Insufficient memory (case %d)")
|
||||
JMESSAGE(JERR_QUANT_COMPONENTS,
|
||||
"Cannot quantize more than %d color components")
|
||||
JMESSAGE(JERR_QUANT_FEW_COLORS, "Cannot quantize to fewer than %d colors")
|
||||
JMESSAGE(JERR_QUANT_MANY_COLORS, "Cannot quantize to more than %d colors")
|
||||
JMESSAGE(JERR_SOF_DUPLICATE, "Invalid JPEG file structure: two SOF markers")
|
||||
JMESSAGE(JERR_SOF_NO_SOS, "Invalid JPEG file structure: missing SOS marker")
|
||||
JMESSAGE(JERR_SOF_UNSUPPORTED, "Unsupported JPEG process: SOF type 0x%02x")
|
||||
JMESSAGE(JERR_SOI_DUPLICATE, "Invalid JPEG file structure: two SOI markers")
|
||||
JMESSAGE(JERR_SOS_NO_SOF, "Invalid JPEG file structure: SOS before SOF")
|
||||
JMESSAGE(JERR_TFILE_CREATE, "Failed to create temporary file %s")
|
||||
JMESSAGE(JERR_TFILE_READ, "Read failed on temporary file")
|
||||
JMESSAGE(JERR_TFILE_SEEK, "Seek failed on temporary file")
|
||||
JMESSAGE(JERR_TFILE_WRITE,
|
||||
"Write failed on temporary file --- out of disk space?")
|
||||
JMESSAGE(JERR_TOO_LITTLE_DATA, "Application transferred too few scanlines")
|
||||
JMESSAGE(JERR_UNKNOWN_MARKER, "Unsupported marker type 0x%02x")
|
||||
JMESSAGE(JERR_VIRTUAL_BUG, "Virtual array controller messed up")
|
||||
JMESSAGE(JERR_WIDTH_OVERFLOW, "Image too wide for this implementation")
|
||||
JMESSAGE(JERR_XMS_READ, "Read from XMS failed")
|
||||
JMESSAGE(JERR_XMS_WRITE, "Write to XMS failed")
|
||||
JMESSAGE(JMSG_COPYRIGHT, JCOPYRIGHT)
|
||||
JMESSAGE(JMSG_VERSION, JVERSION)
|
||||
JMESSAGE(JTRC_16BIT_TABLES,
|
||||
"Caution: quantization tables are too coarse for baseline JPEG")
|
||||
JMESSAGE(JTRC_ADOBE,
|
||||
"Adobe APP14 marker: version %d, flags 0x%04x 0x%04x, transform %d")
|
||||
JMESSAGE(JTRC_APP0, "Unknown APP0 marker (not JFIF), length %u")
|
||||
JMESSAGE(JTRC_APP14, "Unknown APP14 marker (not Adobe), length %u")
|
||||
JMESSAGE(JTRC_DAC, "Define Arithmetic Table 0x%02x: 0x%02x")
|
||||
JMESSAGE(JTRC_DHT, "Define Huffman Table 0x%02x")
|
||||
JMESSAGE(JTRC_DQT, "Define Quantization Table %d precision %d")
|
||||
JMESSAGE(JTRC_DRI, "Define Restart Interval %u")
|
||||
JMESSAGE(JTRC_EMS_CLOSE, "Freed EMS handle %u")
|
||||
JMESSAGE(JTRC_EMS_OPEN, "Obtained EMS handle %u")
|
||||
JMESSAGE(JTRC_EOI, "End Of Image")
|
||||
JMESSAGE(JTRC_HUFFBITS, " %3d %3d %3d %3d %3d %3d %3d %3d")
|
||||
JMESSAGE(JTRC_JFIF, "JFIF APP0 marker: version %d.%02d, density %dx%d %d")
|
||||
JMESSAGE(JTRC_JFIF_BADTHUMBNAILSIZE,
|
||||
"Warning: thumbnail image size does not match data length %u")
|
||||
JMESSAGE(JTRC_JFIF_EXTENSION, "JFIF extension marker: type 0x%02x, length %u")
|
||||
JMESSAGE(JTRC_JFIF_THUMBNAIL, " with %d x %d thumbnail image")
|
||||
JMESSAGE(JTRC_MISC_MARKER, "Miscellaneous marker 0x%02x, length %u")
|
||||
JMESSAGE(JTRC_PARMLESS_MARKER, "Unexpected marker 0x%02x")
|
||||
JMESSAGE(JTRC_QUANTVALS, " %4u %4u %4u %4u %4u %4u %4u %4u")
|
||||
JMESSAGE(JTRC_QUANT_3_NCOLORS, "Quantizing to %d = %d*%d*%d colors")
|
||||
JMESSAGE(JTRC_QUANT_NCOLORS, "Quantizing to %d colors")
|
||||
JMESSAGE(JTRC_QUANT_SELECTED, "Selected %d colors for quantization")
|
||||
JMESSAGE(JTRC_RECOVERY_ACTION, "At marker 0x%02x, recovery action %d")
|
||||
JMESSAGE(JTRC_RST, "RST%d")
|
||||
JMESSAGE(JTRC_SMOOTH_NOTIMPL,
|
||||
"Smoothing not supported with nonstandard sampling ratios")
|
||||
JMESSAGE(JTRC_SOF, "Start Of Frame 0x%02x: width=%u, height=%u, components=%d")
|
||||
JMESSAGE(JTRC_SOF_COMPONENT, " Component %d: %dhx%dv q=%d")
|
||||
JMESSAGE(JTRC_SOI, "Start of Image")
|
||||
JMESSAGE(JTRC_SOS, "Start Of Scan: %d components")
|
||||
JMESSAGE(JTRC_SOS_COMPONENT, " Component %d: dc=%d ac=%d")
|
||||
JMESSAGE(JTRC_SOS_PARAMS, " Ss=%d, Se=%d, Ah=%d, Al=%d")
|
||||
JMESSAGE(JTRC_TFILE_CLOSE, "Closed temporary file %s")
|
||||
JMESSAGE(JTRC_TFILE_OPEN, "Opened temporary file %s")
|
||||
JMESSAGE(JTRC_THUMB_JPEG,
|
||||
"JFIF extension marker: JPEG-compressed thumbnail image, length %u")
|
||||
JMESSAGE(JTRC_THUMB_PALETTE,
|
||||
"JFIF extension marker: palette thumbnail image, length %u")
|
||||
JMESSAGE(JTRC_THUMB_RGB,
|
||||
"JFIF extension marker: RGB thumbnail image, length %u")
|
||||
JMESSAGE(JTRC_UNKNOWN_IDS,
|
||||
"Unrecognized component IDs %d %d %d, assuming YCbCr (lossy) or RGB (lossless)")
|
||||
JMESSAGE(JTRC_XMS_CLOSE, "Freed XMS handle %u")
|
||||
JMESSAGE(JTRC_XMS_OPEN, "Obtained XMS handle %u")
|
||||
JMESSAGE(JWRN_ADOBE_XFORM, "Unknown Adobe color transform code %d")
|
||||
#if JPEG_LIB_VERSION >= 70
|
||||
JMESSAGE(JWRN_ARITH_BAD_CODE, "Corrupt JPEG data: bad arithmetic code")
|
||||
#endif
|
||||
JMESSAGE(JWRN_BOGUS_PROGRESSION,
|
||||
"Inconsistent progression sequence for component %d coefficient %d")
|
||||
JMESSAGE(JWRN_EXTRANEOUS_DATA,
|
||||
"Corrupt JPEG data: %u extraneous bytes before marker 0x%02x")
|
||||
JMESSAGE(JWRN_HIT_MARKER, "Corrupt JPEG data: premature end of data segment")
|
||||
JMESSAGE(JWRN_HUFF_BAD_CODE, "Corrupt JPEG data: bad Huffman code")
|
||||
JMESSAGE(JWRN_JFIF_MAJOR, "Warning: unknown JFIF revision number %d.%02d")
|
||||
JMESSAGE(JWRN_JPEG_EOF, "Premature end of JPEG file")
|
||||
JMESSAGE(JWRN_MUST_RESYNC,
|
||||
"Corrupt JPEG data: found marker 0x%02x instead of RST%d")
|
||||
JMESSAGE(JWRN_NOT_SEQUENTIAL, "Invalid SOS parameters for sequential JPEG")
|
||||
JMESSAGE(JWRN_TOO_MUCH_DATA, "Application transferred too many scanlines")
|
||||
#if JPEG_LIB_VERSION < 70
|
||||
JMESSAGE(JERR_BAD_CROP_SPEC, "Invalid crop request")
|
||||
#if defined(C_ARITH_CODING_SUPPORTED) || defined(D_ARITH_CODING_SUPPORTED)
|
||||
JMESSAGE(JERR_NO_ARITH_TABLE, "Arithmetic table 0x%02x was not defined")
|
||||
JMESSAGE(JWRN_ARITH_BAD_CODE, "Corrupt JPEG data: bad arithmetic code")
|
||||
#endif
|
||||
#endif
|
||||
JMESSAGE(JWRN_BOGUS_ICC, "Corrupt JPEG data: bad ICC marker")
|
||||
#if JPEG_LIB_VERSION < 70
|
||||
JMESSAGE(JERR_BAD_DROP_SAMPLING,
|
||||
"Component index %d: mismatching sampling ratio %d:%d, %d:%d, %c")
|
||||
#endif
|
||||
JMESSAGE(JERR_BAD_RESTART,
|
||||
"Invalid restart interval %d; must be an integer multiple of the number of MCUs in an MCU row (%d)")
|
||||
|
||||
#ifdef JMAKE_ENUM_LIST
|
||||
|
||||
JMSG_LASTMSGCODE
|
||||
} J_MESSAGE_CODE;
|
||||
|
||||
#undef JMAKE_ENUM_LIST
|
||||
#endif /* JMAKE_ENUM_LIST */
|
||||
|
||||
/* Zap JMESSAGE macro so that future re-inclusions do nothing by default */
|
||||
#undef JMESSAGE
|
||||
|
||||
|
||||
#ifndef JERROR_H
|
||||
#define JERROR_H
|
||||
|
||||
/* Macros to simplify using the error and trace message stuff */
|
||||
/* The first parameter is either type of cinfo pointer */
|
||||
|
||||
/* Fatal errors (print message and exit) */
|
||||
#define ERREXIT(cinfo, code) \
|
||||
((cinfo)->err->msg_code = (code), \
|
||||
(*(cinfo)->err->error_exit) ((j_common_ptr)(cinfo)))
|
||||
#define ERREXIT1(cinfo, code, p1) \
|
||||
((cinfo)->err->msg_code = (code), \
|
||||
(cinfo)->err->msg_parm.i[0] = (p1), \
|
||||
(*(cinfo)->err->error_exit) ((j_common_ptr)(cinfo)))
|
||||
#define ERREXIT2(cinfo, code, p1, p2) \
|
||||
((cinfo)->err->msg_code = (code), \
|
||||
(cinfo)->err->msg_parm.i[0] = (p1), \
|
||||
(cinfo)->err->msg_parm.i[1] = (p2), \
|
||||
(*(cinfo)->err->error_exit) ((j_common_ptr)(cinfo)))
|
||||
#define ERREXIT3(cinfo, code, p1, p2, p3) \
|
||||
((cinfo)->err->msg_code = (code), \
|
||||
(cinfo)->err->msg_parm.i[0] = (p1), \
|
||||
(cinfo)->err->msg_parm.i[1] = (p2), \
|
||||
(cinfo)->err->msg_parm.i[2] = (p3), \
|
||||
(*(cinfo)->err->error_exit) ((j_common_ptr)(cinfo)))
|
||||
#define ERREXIT4(cinfo, code, p1, p2, p3, p4) \
|
||||
((cinfo)->err->msg_code = (code), \
|
||||
(cinfo)->err->msg_parm.i[0] = (p1), \
|
||||
(cinfo)->err->msg_parm.i[1] = (p2), \
|
||||
(cinfo)->err->msg_parm.i[2] = (p3), \
|
||||
(cinfo)->err->msg_parm.i[3] = (p4), \
|
||||
(*(cinfo)->err->error_exit) ((j_common_ptr)(cinfo)))
|
||||
#define ERREXIT6(cinfo, code, p1, p2, p3, p4, p5, p6) \
|
||||
((cinfo)->err->msg_code = (code), \
|
||||
(cinfo)->err->msg_parm.i[0] = (p1), \
|
||||
(cinfo)->err->msg_parm.i[1] = (p2), \
|
||||
(cinfo)->err->msg_parm.i[2] = (p3), \
|
||||
(cinfo)->err->msg_parm.i[3] = (p4), \
|
||||
(cinfo)->err->msg_parm.i[4] = (p5), \
|
||||
(cinfo)->err->msg_parm.i[5] = (p6), \
|
||||
(*(cinfo)->err->error_exit) ((j_common_ptr)(cinfo)))
|
||||
#define ERREXITS(cinfo, code, str) \
|
||||
((cinfo)->err->msg_code = (code), \
|
||||
strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX - 1), \
|
||||
(cinfo)->err->msg_parm.s[JMSG_STR_PARM_MAX - 1] = '\0', \
|
||||
(*(cinfo)->err->error_exit) ((j_common_ptr)(cinfo)))
|
||||
|
||||
#define MAKESTMT(stuff) do { stuff } while (0)
|
||||
|
||||
/* Nonfatal errors (we can keep going, but the data is probably corrupt) */
|
||||
#define WARNMS(cinfo, code) \
|
||||
((cinfo)->err->msg_code = (code), \
|
||||
(*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), -1))
|
||||
#define WARNMS1(cinfo, code, p1) \
|
||||
((cinfo)->err->msg_code = (code), \
|
||||
(cinfo)->err->msg_parm.i[0] = (p1), \
|
||||
(*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), -1))
|
||||
#define WARNMS2(cinfo, code, p1, p2) \
|
||||
((cinfo)->err->msg_code = (code), \
|
||||
(cinfo)->err->msg_parm.i[0] = (p1), \
|
||||
(cinfo)->err->msg_parm.i[1] = (p2), \
|
||||
(*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), -1))
|
||||
|
||||
/* Informational/debugging messages */
|
||||
#define TRACEMS(cinfo, lvl, code) \
|
||||
((cinfo)->err->msg_code = (code), \
|
||||
(*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), (lvl)))
|
||||
#define TRACEMS1(cinfo, lvl, code, p1) \
|
||||
((cinfo)->err->msg_code = (code), \
|
||||
(cinfo)->err->msg_parm.i[0] = (p1), \
|
||||
(*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), (lvl)))
|
||||
#define TRACEMS2(cinfo, lvl, code, p1, p2) \
|
||||
((cinfo)->err->msg_code = (code), \
|
||||
(cinfo)->err->msg_parm.i[0] = (p1), \
|
||||
(cinfo)->err->msg_parm.i[1] = (p2), \
|
||||
(*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), (lvl)))
|
||||
#define TRACEMS3(cinfo, lvl, code, p1, p2, p3) \
|
||||
MAKESTMT(int *_mp = (cinfo)->err->msg_parm.i; \
|
||||
_mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); \
|
||||
(cinfo)->err->msg_code = (code); \
|
||||
(*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), (lvl)); )
|
||||
#define TRACEMS4(cinfo, lvl, code, p1, p2, p3, p4) \
|
||||
MAKESTMT(int *_mp = (cinfo)->err->msg_parm.i; \
|
||||
_mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \
|
||||
(cinfo)->err->msg_code = (code); \
|
||||
(*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), (lvl)); )
|
||||
#define TRACEMS5(cinfo, lvl, code, p1, p2, p3, p4, p5) \
|
||||
MAKESTMT(int *_mp = (cinfo)->err->msg_parm.i; \
|
||||
_mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \
|
||||
_mp[4] = (p5); \
|
||||
(cinfo)->err->msg_code = (code); \
|
||||
(*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), (lvl)); )
|
||||
#define TRACEMS8(cinfo, lvl, code, p1, p2, p3, p4, p5, p6, p7, p8) \
|
||||
MAKESTMT(int *_mp = (cinfo)->err->msg_parm.i; \
|
||||
_mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \
|
||||
_mp[4] = (p5); _mp[5] = (p6); _mp[6] = (p7); _mp[7] = (p8); \
|
||||
(cinfo)->err->msg_code = (code); \
|
||||
(*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), (lvl)); )
|
||||
#define TRACEMSS(cinfo, lvl, code, str) \
|
||||
((cinfo)->err->msg_code = (code), \
|
||||
strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \
|
||||
(cinfo)->err->msg_parm.s[JMSG_STR_PARM_MAX - 1] = '\0', \
|
||||
(*(cinfo)->err->emit_message) ((j_common_ptr)(cinfo), (lvl)))
|
||||
|
||||
#endif /* JERROR_H */
|
||||
@@ -0,0 +1,389 @@
|
||||
/*
|
||||
* jmorecfg.h
|
||||
*
|
||||
* This file was part of the Independent JPEG Group's software:
|
||||
* Copyright (C) 1991-1997, Thomas G. Lane.
|
||||
* Modified 1997-2009 by Guido Vollbeding.
|
||||
* Lossless JPEG Modifications:
|
||||
* Copyright (C) 1999, Ken Murchison.
|
||||
* libjpeg-turbo Modifications:
|
||||
* Copyright (C) 2009, 2011, 2014-2015, 2018, 2020, 2022, 2026,
|
||||
* D. R. Commander.
|
||||
* For conditions of distribution and use, see the accompanying README.ijg
|
||||
* file.
|
||||
*
|
||||
* This file contains additional configuration options that customize the
|
||||
* JPEG software for special applications or support machine-dependent
|
||||
* optimizations. Most users will not need to touch this file.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Maximum number of components (color channels) allowed in JPEG image.
|
||||
* To meet the letter of Rec. ITU-T T.81 | ISO/IEC 10918-1, set this to 255.
|
||||
* However, darn few applications need more than 4 channels (maybe 5 for CMYK +
|
||||
* alpha mask). We recommend 10 as a reasonable compromise; use 4 if you are
|
||||
* really short on memory. (Each allowed component costs a hundred or so
|
||||
* bytes of storage, whether actually used in an image or not.)
|
||||
*/
|
||||
|
||||
#define MAX_COMPONENTS 10 /* maximum number of image components */
|
||||
|
||||
|
||||
/*
|
||||
* Basic data types.
|
||||
* You may need to change these if you have a machine with unusual data
|
||||
* type sizes; for example, "char" not 8 bits, "short" not 16 bits,
|
||||
* or "long" not 32 bits. We don't care whether "int" is 16 or 32 bits,
|
||||
* but it had better be at least 16.
|
||||
*/
|
||||
|
||||
/* Representation of a single sample (pixel element value).
|
||||
* We frequently allocate large arrays of these, so it's important to keep
|
||||
* them small. But if you have memory to burn and access to char or short
|
||||
* arrays is very slow on your hardware, you might want to change these.
|
||||
*/
|
||||
|
||||
/* JSAMPLE should be the smallest type that will hold the values 0..255. */
|
||||
|
||||
typedef unsigned char JSAMPLE;
|
||||
#define GETJSAMPLE(value) ((int)(value))
|
||||
|
||||
#define MAXJSAMPLE 255
|
||||
#define CENTERJSAMPLE 128
|
||||
|
||||
|
||||
/* J12SAMPLE should be the smallest type that will hold the values 0..4095. */
|
||||
|
||||
typedef short J12SAMPLE;
|
||||
|
||||
#define MAXJ12SAMPLE 4095
|
||||
#define CENTERJ12SAMPLE 2048
|
||||
|
||||
|
||||
/* J16SAMPLE should be the smallest type that will hold the values 0..65535. */
|
||||
|
||||
typedef unsigned short J16SAMPLE;
|
||||
|
||||
#define MAXJ16SAMPLE 65535
|
||||
#define CENTERJ16SAMPLE 32768
|
||||
|
||||
|
||||
/* Representation of a DCT frequency coefficient.
|
||||
* This should be a signed value of at least 16 bits; "short" is usually OK.
|
||||
* Again, we allocate large arrays of these, but you can change to int
|
||||
* if you have memory to burn and "short" is really slow.
|
||||
*/
|
||||
|
||||
typedef short JCOEF;
|
||||
|
||||
|
||||
/* Compressed datastreams are represented as arrays of JOCTET.
|
||||
* These must be EXACTLY 8 bits wide, at least once they are written to
|
||||
* external storage. Note that when using the stdio data source/destination
|
||||
* managers, this is also the data type passed to fread/fwrite.
|
||||
*/
|
||||
|
||||
typedef unsigned char JOCTET;
|
||||
#define GETJOCTET(value) (value)
|
||||
|
||||
|
||||
/* These typedefs are used for various table entries and so forth.
|
||||
* They must be at least as wide as specified; but making them too big
|
||||
* won't cost a huge amount of memory, so we don't provide special
|
||||
* extraction code like we did for JSAMPLE. (In other words, these
|
||||
* typedefs live at a different point on the speed/space tradeoff curve.)
|
||||
*/
|
||||
|
||||
/* UINT8 must hold at least the values 0..255. */
|
||||
|
||||
typedef unsigned char UINT8;
|
||||
|
||||
/* UINT16 must hold at least the values 0..65535. */
|
||||
|
||||
typedef unsigned short UINT16;
|
||||
|
||||
/* INT16 must hold at least the values -32768..32767. */
|
||||
|
||||
#ifndef XMD_H /* X11/xmd.h correctly defines INT16 */
|
||||
typedef short INT16;
|
||||
#endif
|
||||
|
||||
/* INT32 must hold at least signed 32-bit values.
|
||||
*
|
||||
* NOTE: The INT32 typedef dates back to libjpeg v5 (1994.) Integers were
|
||||
* sometimes 16-bit back then (MS-DOS), which is why INT32 is typedef'd to
|
||||
* long. It also wasn't common (or at least as common) in 1994 for INT32 to be
|
||||
* defined by platform headers. Since then, however, INT32 is defined in
|
||||
* several other common places:
|
||||
*
|
||||
* Xmd.h (X11 header) typedefs INT32 to int on 64-bit platforms and long on
|
||||
* 32-bit platforms (i.e always a 32-bit signed type.)
|
||||
*
|
||||
* basetsd.h (Win32 header) typedefs INT32 to int (always a 32-bit signed type
|
||||
* on modern platforms.)
|
||||
*
|
||||
* qglobal.h (Qt header) typedefs INT32 to int (always a 32-bit signed type on
|
||||
* modern platforms.)
|
||||
*
|
||||
* This is a recipe for conflict, since "long" and "int" aren't always
|
||||
* compatible types. Since the definition of INT32 has technically been part
|
||||
* of the libjpeg API for more than 20 years, we can't remove it, but we do not
|
||||
* use it internally any longer. We instead define a separate type (JLONG)
|
||||
* for internal use, which ensures that internal behavior will always be the
|
||||
* same regardless of any external headers that may be included.
|
||||
*/
|
||||
|
||||
#ifndef XMD_H /* X11/xmd.h correctly defines INT32 */
|
||||
#ifndef _BASETSD_H_ /* Microsoft defines it in basetsd.h */
|
||||
#ifndef _BASETSD_H /* MinGW is slightly different */
|
||||
#ifndef QGLOBAL_H /* Qt defines it in qglobal.h */
|
||||
typedef long INT32;
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Datatype used for image dimensions. The JPEG standard only supports
|
||||
* images up to 64K*64K due to 16-bit fields in SOF markers. Therefore
|
||||
* "unsigned int" is sufficient on all machines. However, if you need to
|
||||
* handle larger images and you don't mind deviating from the spec, you
|
||||
* can change this datatype. (Note that changing this datatype will
|
||||
* potentially require modifying the SIMD code. The x86-64 SIMD extensions,
|
||||
* in particular, assume a 32-bit JDIMENSION.)
|
||||
*/
|
||||
|
||||
typedef unsigned int JDIMENSION;
|
||||
|
||||
#define JPEG_MAX_DIMENSION 65500L /* a tad under 64K to prevent overflows */
|
||||
|
||||
|
||||
/* These macros are used in all function definitions and extern declarations.
|
||||
* You could modify them if you need to change function linkage conventions;
|
||||
* in particular, you'll need to do that to make the library a Windows DLL.
|
||||
* Another application is to make all functions global for use with debuggers
|
||||
* or code profilers that require it.
|
||||
*/
|
||||
|
||||
/* a function called through method pointers: */
|
||||
#define METHODDEF(type) static type
|
||||
/* a function used only in its module: */
|
||||
#define LOCAL(type) static type
|
||||
/* a function referenced thru EXTERNs: */
|
||||
#define GLOBAL(type) type
|
||||
/* a reference to a GLOBAL function: */
|
||||
#define EXTERN(type) extern type
|
||||
|
||||
|
||||
/* Originally, this macro was used as a way of defining function prototypes
|
||||
* for both modern compilers as well as older compilers that did not support
|
||||
* prototype parameters. libjpeg-turbo has never supported these older,
|
||||
* non-ANSI compilers, but the macro is still included because there is some
|
||||
* software out there that uses it.
|
||||
*/
|
||||
|
||||
#define JMETHOD(type, methodname, arglist) type (*methodname) arglist
|
||||
|
||||
|
||||
/* libjpeg-turbo no longer supports platforms that have far symbols (MS-DOS),
|
||||
* but again, some software relies on this macro.
|
||||
*/
|
||||
|
||||
#undef FAR
|
||||
#define FAR
|
||||
|
||||
|
||||
/*
|
||||
* On a few systems, type boolean and/or its values FALSE, TRUE may appear
|
||||
* in standard header files. Or you may have conflicts with application-
|
||||
* specific header files that you want to include together with these files.
|
||||
* Defining HAVE_BOOLEAN before including jpeglib.h should make it work.
|
||||
*/
|
||||
|
||||
#ifndef HAVE_BOOLEAN
|
||||
typedef int boolean;
|
||||
#endif
|
||||
#ifndef FALSE /* in case these macros already exist */
|
||||
#define FALSE 0 /* values of boolean */
|
||||
#endif
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* The remaining options affect code selection within the JPEG library,
|
||||
* but they don't need to be visible to most applications using the library.
|
||||
* To minimize application namespace pollution, the symbols won't be
|
||||
* defined unless JPEG_INTERNALS or JPEG_INTERNAL_OPTIONS has been defined.
|
||||
*/
|
||||
|
||||
#ifdef JPEG_INTERNALS
|
||||
#define JPEG_INTERNAL_OPTIONS
|
||||
#endif
|
||||
|
||||
#ifdef JPEG_INTERNAL_OPTIONS
|
||||
|
||||
|
||||
/*
|
||||
* These defines indicate whether to include various optional functions.
|
||||
* Undefining some of these symbols will produce a smaller but less capable
|
||||
* library. Note that you can leave certain source files out of the
|
||||
* compilation/linking process if you've #undef'd the corresponding symbols.
|
||||
* (You may HAVE to do that if your compiler doesn't like null source files.)
|
||||
*/
|
||||
|
||||
/* Capability options common to encoder and decoder: */
|
||||
|
||||
#define DCT_ISLOW_SUPPORTED /* accurate integer method */
|
||||
#define DCT_IFAST_SUPPORTED /* less accurate int method [legacy feature] */
|
||||
#define DCT_FLOAT_SUPPORTED /* floating-point method [legacy feature] */
|
||||
|
||||
/* Encoder capability options: */
|
||||
|
||||
#define C_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */
|
||||
#define C_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires
|
||||
C_MULTISCAN_FILES_SUPPORTED and
|
||||
ENTROPY_OPT_SUPPORTED) */
|
||||
#define C_LOSSLESS_SUPPORTED /* Lossless JPEG? */
|
||||
#define ENTROPY_OPT_SUPPORTED /* Optimization of entropy coding parms? */
|
||||
/* Note: if you selected 12-bit data precision, it is dangerous to turn off
|
||||
* ENTROPY_OPT_SUPPORTED. The standard Huffman tables are only good for 8-bit
|
||||
* precision, so jchuff.c normally uses entropy optimization to compute
|
||||
* usable tables for higher precision. If you don't want to do optimization,
|
||||
* you'll have to supply different default Huffman tables.
|
||||
* The exact same statements apply for lossless JPEG: the default tables don't
|
||||
* work for lossless mode. (This may get fixed, however.)
|
||||
*/
|
||||
#define INPUT_SMOOTHING_SUPPORTED /* Input image smoothing option? */
|
||||
|
||||
/* Decoder capability options: */
|
||||
|
||||
#define D_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */
|
||||
#define D_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires
|
||||
D_MULTISCAN_FILES_SUPPORTED) */
|
||||
#define D_LOSSLESS_SUPPORTED /* Lossless JPEG? (Requires
|
||||
D_MULTISCAN_FILES_SUPPORTED) */
|
||||
#define SAVE_MARKERS_SUPPORTED /* jpeg_save_markers() needed? */
|
||||
#define BLOCK_SMOOTHING_SUPPORTED /* Block smoothing? (Progressive only) */
|
||||
#define IDCT_SCALING_SUPPORTED /* Output rescaling via IDCT? (Requires
|
||||
DCT_ISLOW_SUPPORTED) */
|
||||
#define UPSAMPLE_MERGING_SUPPORTED /* Fast path for sloppy upsampling? */
|
||||
#define QUANT_1PASS_SUPPORTED /* 1-pass color quantization? */
|
||||
#define QUANT_2PASS_SUPPORTED /* 2-pass color quantization? */
|
||||
|
||||
/* more capability options later, no doubt */
|
||||
|
||||
|
||||
/*
|
||||
* The RGB_RED, RGB_GREEN, RGB_BLUE, and RGB_PIXELSIZE macros are a vestigial
|
||||
* feature of libjpeg. The idea was that, if an application developer needed
|
||||
* to compress from/decompress to a BGR/BGRX/RGBX/XBGR/XRGB buffer, they could
|
||||
* change these macros, rebuild libjpeg, and link their application statically
|
||||
* with it. In reality, few people ever did this, because there were some
|
||||
* severe restrictions involved (cjpeg and djpeg no longer worked properly,
|
||||
* compressing/decompressing RGB JPEGs no longer worked properly, and the color
|
||||
* quantizer wouldn't work with pixel sizes other than 3.) Furthermore, since
|
||||
* all of the O/S-supplied versions of libjpeg were built with the default
|
||||
* values of RGB_RED, RGB_GREEN, RGB_BLUE, and RGB_PIXELSIZE, many applications
|
||||
* have come to regard these values as immutable.
|
||||
*
|
||||
* The libjpeg-turbo colorspace extensions provide a much cleaner way of
|
||||
* compressing from/decompressing to buffers with arbitrary component orders
|
||||
* and pixel sizes. Thus, we do not support changing the values of RGB_RED,
|
||||
* RGB_GREEN, RGB_BLUE, or RGB_PIXELSIZE. In addition to the restrictions
|
||||
* listed above, changing these values will also break the SIMD extensions and
|
||||
* the regression tests.
|
||||
*/
|
||||
|
||||
#define RGB_RED 0 /* Offset of Red in an RGB scanline element */
|
||||
#define RGB_GREEN 1 /* Offset of Green */
|
||||
#define RGB_BLUE 2 /* Offset of Blue */
|
||||
#define RGB_PIXELSIZE 3 /* JSAMPLEs per RGB scanline element */
|
||||
|
||||
#define JPEG_NUMCS 17
|
||||
|
||||
#define EXT_RGB_RED 0
|
||||
#define EXT_RGB_GREEN 1
|
||||
#define EXT_RGB_BLUE 2
|
||||
#define EXT_RGB_PIXELSIZE 3
|
||||
|
||||
#define EXT_RGBX_RED 0
|
||||
#define EXT_RGBX_GREEN 1
|
||||
#define EXT_RGBX_BLUE 2
|
||||
#define EXT_RGBX_PIXELSIZE 4
|
||||
|
||||
#define EXT_BGR_RED 2
|
||||
#define EXT_BGR_GREEN 1
|
||||
#define EXT_BGR_BLUE 0
|
||||
#define EXT_BGR_PIXELSIZE 3
|
||||
|
||||
#define EXT_BGRX_RED 2
|
||||
#define EXT_BGRX_GREEN 1
|
||||
#define EXT_BGRX_BLUE 0
|
||||
#define EXT_BGRX_PIXELSIZE 4
|
||||
|
||||
#define EXT_XBGR_RED 3
|
||||
#define EXT_XBGR_GREEN 2
|
||||
#define EXT_XBGR_BLUE 1
|
||||
#define EXT_XBGR_PIXELSIZE 4
|
||||
|
||||
#define EXT_XRGB_RED 1
|
||||
#define EXT_XRGB_GREEN 2
|
||||
#define EXT_XRGB_BLUE 3
|
||||
#define EXT_XRGB_PIXELSIZE 4
|
||||
|
||||
static const int rgb_red[JPEG_NUMCS] = {
|
||||
-1, -1, RGB_RED, -1, -1, -1, EXT_RGB_RED, EXT_RGBX_RED,
|
||||
EXT_BGR_RED, EXT_BGRX_RED, EXT_XBGR_RED, EXT_XRGB_RED,
|
||||
EXT_RGBX_RED, EXT_BGRX_RED, EXT_XBGR_RED, EXT_XRGB_RED,
|
||||
-1
|
||||
};
|
||||
|
||||
static const int rgb_green[JPEG_NUMCS] = {
|
||||
-1, -1, RGB_GREEN, -1, -1, -1, EXT_RGB_GREEN, EXT_RGBX_GREEN,
|
||||
EXT_BGR_GREEN, EXT_BGRX_GREEN, EXT_XBGR_GREEN, EXT_XRGB_GREEN,
|
||||
EXT_RGBX_GREEN, EXT_BGRX_GREEN, EXT_XBGR_GREEN, EXT_XRGB_GREEN,
|
||||
-1
|
||||
};
|
||||
|
||||
static const int rgb_blue[JPEG_NUMCS] = {
|
||||
-1, -1, RGB_BLUE, -1, -1, -1, EXT_RGB_BLUE, EXT_RGBX_BLUE,
|
||||
EXT_BGR_BLUE, EXT_BGRX_BLUE, EXT_XBGR_BLUE, EXT_XRGB_BLUE,
|
||||
EXT_RGBX_BLUE, EXT_BGRX_BLUE, EXT_XBGR_BLUE, EXT_XRGB_BLUE,
|
||||
-1
|
||||
};
|
||||
|
||||
static const int rgb_pixelsize[JPEG_NUMCS] = {
|
||||
-1, -1, RGB_PIXELSIZE, -1, -1, -1, EXT_RGB_PIXELSIZE, EXT_RGBX_PIXELSIZE,
|
||||
EXT_BGR_PIXELSIZE, EXT_BGRX_PIXELSIZE, EXT_XBGR_PIXELSIZE, EXT_XRGB_PIXELSIZE,
|
||||
EXT_RGBX_PIXELSIZE, EXT_BGRX_PIXELSIZE, EXT_XBGR_PIXELSIZE, EXT_XRGB_PIXELSIZE,
|
||||
-1
|
||||
};
|
||||
|
||||
/* Definitions for speed-related optimizations. */
|
||||
|
||||
/* On some machines (notably 68000 series) "int" is 32 bits, but multiplying
|
||||
* two 16-bit shorts is faster than multiplying two ints. Define MULTIPLIER
|
||||
* as short on such a machine. MULTIPLIER must be at least 16 bits wide.
|
||||
*/
|
||||
|
||||
#ifndef MULTIPLIER
|
||||
#ifndef WITH_SIMD
|
||||
#define MULTIPLIER int /* type for fastest integer multiply */
|
||||
#else
|
||||
#define MULTIPLIER short /* prefer 16-bit with SIMD for parellelism */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/* FAST_FLOAT should be either float or double, whichever is done faster
|
||||
* by your compiler. (Note that this type is only used in the floating point
|
||||
* DCT routines, so it only matters if you've defined DCT_FLOAT_SUPPORTED.)
|
||||
*/
|
||||
|
||||
#ifndef FAST_FLOAT
|
||||
#define FAST_FLOAT float
|
||||
#endif
|
||||
|
||||
#endif /* JPEG_INTERNAL_OPTIONS */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,101 @@
|
||||
// Copyright (c) 2005-2021 Jay Berkenbilt
|
||||
// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger
|
||||
//
|
||||
// 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 BUFFER_HH
|
||||
#define BUFFER_HH
|
||||
|
||||
#include <qpdf/DLL.h>
|
||||
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
class Buffer
|
||||
{
|
||||
public:
|
||||
QPDF_DLL
|
||||
Buffer();
|
||||
|
||||
// Create a Buffer object whose memory is owned by the class and will be freed when the Buffer
|
||||
// object is destroyed.
|
||||
QPDF_DLL
|
||||
Buffer(size_t size);
|
||||
QPDF_DLL
|
||||
Buffer(std::string&& content);
|
||||
|
||||
// Create a Buffer object whose memory is owned by the caller and will not be freed when the
|
||||
// Buffer is destroyed.
|
||||
QPDF_DLL
|
||||
Buffer(unsigned char* buf, size_t size);
|
||||
QPDF_DLL
|
||||
Buffer(std::string& content);
|
||||
|
||||
Buffer(Buffer const&) = delete;
|
||||
Buffer& operator=(Buffer const&) = delete;
|
||||
|
||||
QPDF_DLL
|
||||
Buffer(Buffer&&) noexcept;
|
||||
QPDF_DLL
|
||||
Buffer& operator=(Buffer&&) noexcept;
|
||||
QPDF_DLL
|
||||
~Buffer();
|
||||
QPDF_DLL
|
||||
size_t getSize() const;
|
||||
QPDF_DLL
|
||||
unsigned char const* getBuffer() const;
|
||||
QPDF_DLL
|
||||
unsigned char* getBuffer();
|
||||
|
||||
// Create a new copy of the Buffer. The new Buffer owns an independent copy of the data.
|
||||
QPDF_DLL
|
||||
Buffer copy() const;
|
||||
|
||||
// Move the content of the Buffer. After calling this method, the Buffer will be empty if the
|
||||
// buffer owns its memory. Otherwise, the Buffer will be unchanged.
|
||||
QPDF_DLL
|
||||
std::string move();
|
||||
|
||||
// Return a string_view to the data.
|
||||
QPDF_DLL
|
||||
std::string_view view() const;
|
||||
|
||||
// Return a pointer to the data. NB: Unlike getBuffer, this method returns a valid pointer even
|
||||
// if the Buffer is empty.
|
||||
QPDF_DLL
|
||||
char const* data() const;
|
||||
|
||||
// Return a pointer to the data. NB: Unlike getBuffer, this method returns a valid pointer even
|
||||
// if the Buffer is empty.
|
||||
QPDF_DLL
|
||||
char* data();
|
||||
|
||||
QPDF_DLL
|
||||
bool empty() const;
|
||||
|
||||
QPDF_DLL
|
||||
size_t size() const;
|
||||
|
||||
private:
|
||||
class Members;
|
||||
|
||||
std::unique_ptr<Members> m;
|
||||
};
|
||||
|
||||
#endif // BUFFER_HH
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
// Copyright (c) 2005-2021 Jay Berkenbilt
|
||||
// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger
|
||||
//
|
||||
// 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_BUFFERINPUTSOURCE_HH
|
||||
#define QPDF_BUFFERINPUTSOURCE_HH
|
||||
|
||||
#include <qpdf/Buffer.hh>
|
||||
#include <qpdf/InputSource.hh>
|
||||
|
||||
#include <memory>
|
||||
|
||||
class QPDF_DLL_CLASS BufferInputSource: public InputSource
|
||||
{
|
||||
public:
|
||||
// If own_memory is true, BufferInputSource will delete the buffer when finished with it.
|
||||
// Otherwise, the caller owns the memory.
|
||||
QPDF_DLL
|
||||
BufferInputSource(std::string const& description, Buffer* buf, bool own_memory = false);
|
||||
|
||||
// NB This overload copies the string contents.
|
||||
QPDF_DLL
|
||||
BufferInputSource(std::string const& description, std::string const& contents);
|
||||
QPDF_DLL
|
||||
~BufferInputSource() override;
|
||||
QPDF_DLL
|
||||
qpdf_offset_t findAndSkipNextEOL() override;
|
||||
QPDF_DLL
|
||||
std::string const& getName() const override;
|
||||
QPDF_DLL
|
||||
qpdf_offset_t tell() override;
|
||||
QPDF_DLL
|
||||
void seek(qpdf_offset_t offset, int whence) override;
|
||||
QPDF_DLL
|
||||
void rewind() override;
|
||||
QPDF_DLL
|
||||
size_t read(char* buffer, size_t length) override;
|
||||
QPDF_DLL
|
||||
void unreadCh(char ch) override;
|
||||
|
||||
private:
|
||||
#ifndef QPDF_FUTURE
|
||||
bool own_memory;
|
||||
std::string description;
|
||||
Buffer* buf;
|
||||
qpdf_offset_t cur_offset;
|
||||
qpdf_offset_t max_offset;
|
||||
#else
|
||||
class Members;
|
||||
|
||||
std::unique_ptr<Members> m;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // QPDF_BUFFERINPUTSOURCE_HH
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
// Copyright (c) 2005-2021 Jay Berkenbilt
|
||||
// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger
|
||||
//
|
||||
// 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_CLOSEDFILEINPUTSOURCE_HH
|
||||
#define QPDF_CLOSEDFILEINPUTSOURCE_HH
|
||||
|
||||
#include <qpdf/InputSource.hh>
|
||||
|
||||
#include <memory>
|
||||
|
||||
class FileInputSource;
|
||||
|
||||
// This is an input source that reads from files, like FileInputSource, except that it opens and
|
||||
// closes the file surrounding every operation. This decreases efficiency, but it allows many more
|
||||
// of these to exist at once than the maximum number of open file descriptors. This is used for
|
||||
// merging large numbers of files.
|
||||
class QPDF_DLL_CLASS ClosedFileInputSource: public InputSource
|
||||
{
|
||||
public:
|
||||
QPDF_DLL
|
||||
ClosedFileInputSource(char const* filename);
|
||||
|
||||
ClosedFileInputSource(ClosedFileInputSource const&) = delete;
|
||||
ClosedFileInputSource& operator=(ClosedFileInputSource const&) = delete;
|
||||
|
||||
QPDF_DLL
|
||||
~ClosedFileInputSource() override;
|
||||
QPDF_DLL
|
||||
qpdf_offset_t findAndSkipNextEOL() override;
|
||||
QPDF_DLL
|
||||
std::string const& getName() const override;
|
||||
QPDF_DLL
|
||||
qpdf_offset_t tell() override;
|
||||
QPDF_DLL
|
||||
void seek(qpdf_offset_t offset, int whence) override;
|
||||
QPDF_DLL
|
||||
void rewind() override;
|
||||
QPDF_DLL
|
||||
size_t read(char* buffer, size_t length) override;
|
||||
QPDF_DLL
|
||||
void unreadCh(char ch) override;
|
||||
|
||||
// The file stays open between calls to stayOpen(true) and stayOpen(false). You can use this to
|
||||
// surround multiple operations on a single ClosedFileInputSource to reduce the overhead of a
|
||||
// separate open/close on each call.
|
||||
QPDF_DLL
|
||||
void stayOpen(bool);
|
||||
|
||||
private:
|
||||
QPDF_DLL_PRIVATE
|
||||
void before();
|
||||
QPDF_DLL_PRIVATE
|
||||
void after();
|
||||
|
||||
std::string filename;
|
||||
qpdf_offset_t offset{0};
|
||||
std::shared_ptr<FileInputSource> fis;
|
||||
bool stay_open{false};
|
||||
};
|
||||
|
||||
#endif // QPDF_CLOSEDFILEINPUTSOURCE_HH
|
||||
@@ -0,0 +1,297 @@
|
||||
/* Copyright (c) 2005-2021 Jay Berkenbilt
|
||||
* Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger
|
||||
*
|
||||
* 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 QPDFCONSTANTS_H
|
||||
#define QPDFCONSTANTS_H
|
||||
|
||||
/*
|
||||
* REMEMBER:
|
||||
*
|
||||
* Keep this file 'C' compatible so it can be used from the C and C++
|
||||
* interfaces.
|
||||
*/
|
||||
|
||||
/* ****************************** NOTE ******************************
|
||||
|
||||
Tl;Dr: new values must be added to the end such that no constant's
|
||||
numerical value changes, even across major releases.
|
||||
|
||||
Details:
|
||||
|
||||
As new values are added to existing enumerated types in this file,
|
||||
it is important not to change the actual values of any constants.
|
||||
This means that, in the absence of explicit assignment of values,
|
||||
the order of entries can't change even across major releases. Why?
|
||||
Here are the reasons:
|
||||
|
||||
* Many of these constants are used by the C API. The C API is used
|
||||
through foreign function call interfaces by users of other languages
|
||||
who may not have access to or the ability to parse a C header file.
|
||||
As such, users are likely to hard-code numerical values or create
|
||||
their own constants whose values match. If we change values here,
|
||||
their code would break, and there would be no way to detect it short
|
||||
of noticing a bug. Furthermore, it would be difficult to write code
|
||||
that properly handled more than one version of the qpdf shared
|
||||
object (e.g. DLL) since the information about what version of qpdf
|
||||
is involved is only available at runtime.
|
||||
|
||||
- It has happened from time to time that a user builds an application
|
||||
with an incorrectly installed qpdf, such as having mismatched header
|
||||
files and library files. In the event that they are only using qpdf
|
||||
interfaces that have been stable across the versions in question,
|
||||
this turns out to be harmless. If they happen to use non-compatible
|
||||
interfaces, this results usually in a failure to load or an obvious
|
||||
runtime error. If we change values of constants, it is possible that
|
||||
code that links and runs may have mismatched values for constants.
|
||||
This would create a bug that would be extremely difficult to track
|
||||
down and impossible for qpdf maintainers to reproduce.
|
||||
|
||||
*/
|
||||
|
||||
/* Exit Codes from QPDFJob and the qpdf CLI */
|
||||
|
||||
enum qpdf_exit_code_e {
|
||||
qpdf_exit_success = 0,
|
||||
/* Normal exit codes */
|
||||
qpdf_exit_error = 2,
|
||||
qpdf_exit_warning = 3,
|
||||
/* For --is-encrypted and --requires-password */
|
||||
qpdf_exit_is_not_encrypted = 2,
|
||||
qpdf_exit_correct_password = 3,
|
||||
};
|
||||
|
||||
/* Error Codes */
|
||||
|
||||
enum qpdf_error_code_e {
|
||||
qpdf_e_success = 0,
|
||||
qpdf_e_internal, /* logic/programming error -- indicates bug */
|
||||
qpdf_e_system, /* I/O error, memory error, etc. */
|
||||
qpdf_e_unsupported, /* PDF feature not (yet) supported by qpdf */
|
||||
qpdf_e_password, /* incorrect password for encrypted file */
|
||||
qpdf_e_damaged_pdf, /* syntax errors or other damage in PDF */
|
||||
qpdf_e_pages, /* erroneous or unsupported pages structure */
|
||||
qpdf_e_object, /* type/bounds errors accessing objects */
|
||||
qpdf_e_json, /* error in qpdf JSON */
|
||||
qpdf_e_linearization, /* linearization warning */
|
||||
};
|
||||
|
||||
/* Object Types */
|
||||
|
||||
/* PDF objects represented by QPDFObjectHandle or, in the C API, by
|
||||
* qpdf_oh, have a unique type code that has one of the values in the
|
||||
* list below. As new object types are added to qpdf, additional items
|
||||
* may be added to the list, so code that switches on these values
|
||||
* should take that into consideration. (Maintainer note: it would be
|
||||
* better to call this qpdf_ot_* rather than ot_* to reduce likelihood
|
||||
* of name collision, but changing the names of the values breaks
|
||||
* backward compatibility.)
|
||||
*/
|
||||
enum qpdf_object_type_e {
|
||||
/* Object types internal to qpdf */
|
||||
ot_uninitialized,
|
||||
ot_reserved,
|
||||
/* Object types that can occur in the main document */
|
||||
ot_null,
|
||||
ot_boolean,
|
||||
ot_integer,
|
||||
ot_real,
|
||||
ot_string,
|
||||
ot_name,
|
||||
ot_array,
|
||||
ot_dictionary,
|
||||
ot_stream,
|
||||
/* Additional object types that can occur in content streams */
|
||||
ot_operator,
|
||||
ot_inlineimage,
|
||||
/* Object types internal to qpdf */
|
||||
ot_unresolved,
|
||||
ot_destroyed,
|
||||
ot_reference,
|
||||
};
|
||||
|
||||
/* Write Parameters. See QPDFWriter.hh for details. */
|
||||
|
||||
enum qpdf_object_stream_e {
|
||||
qpdf_o_disable = 0, /* disable object streams */
|
||||
qpdf_o_preserve, /* preserve object streams */
|
||||
qpdf_o_generate /* generate object streams */
|
||||
};
|
||||
enum qpdf_stream_data_e {
|
||||
qpdf_s_uncompress = 0, /* uncompress stream data */
|
||||
qpdf_s_preserve, /* preserve stream data compression */
|
||||
qpdf_s_compress /* compress stream data */
|
||||
};
|
||||
|
||||
/* Stream data flags */
|
||||
|
||||
/* See pipeStreamData in QPDFObjectHandle.hh for details on these flags. */
|
||||
enum qpdf_stream_encode_flags_e {
|
||||
qpdf_ef_compress = 1 << 0, /* compress uncompressed streams */
|
||||
qpdf_ef_normalize = 1 << 1, /* normalize content stream */
|
||||
};
|
||||
enum qpdf_stream_decode_level_e {
|
||||
/* These must be in order from less to more decoding. */
|
||||
qpdf_dl_none = 0, /* preserve all stream filters */
|
||||
qpdf_dl_generalized, /* decode general-purpose filters */
|
||||
qpdf_dl_specialized, /* also decode other non-lossy filters */
|
||||
qpdf_dl_all /* also decode lossy filters */
|
||||
};
|
||||
/* For JSON encoding */
|
||||
enum qpdf_json_stream_data_e {
|
||||
qpdf_sj_none = 0,
|
||||
qpdf_sj_inline,
|
||||
qpdf_sj_file,
|
||||
};
|
||||
|
||||
/* R3 Encryption Parameters */
|
||||
|
||||
enum qpdf_r3_print_e {
|
||||
qpdf_r3p_full = 0, /* allow all printing */
|
||||
qpdf_r3p_low, /* allow only low-resolution printing */
|
||||
qpdf_r3p_none /* allow no printing */
|
||||
};
|
||||
|
||||
/* qpdf_r3_modify_e doesn't allow the full flexibility of the spec. It
|
||||
* corresponds to options in Acrobat 5's menus. The new interface in
|
||||
* QPDFWriter offers more granularity and no longer uses this type.
|
||||
*/
|
||||
enum qpdf_r3_modify_e /* Allowed changes: */
|
||||
{
|
||||
qpdf_r3m_all = 0, /* All editing */
|
||||
qpdf_r3m_annotate, /* Comments, fill forms, signing, assembly */
|
||||
qpdf_r3m_form, /* Fill forms, signing, assembly */
|
||||
qpdf_r3m_assembly, /* Only document assembly */
|
||||
qpdf_r3m_none /* No modifications */
|
||||
};
|
||||
|
||||
/* Form field flags from the PDF spec */
|
||||
|
||||
enum pdf_form_field_flag_e {
|
||||
/* flags that apply to all form fields */
|
||||
ff_all_read_only = 1 << 0,
|
||||
ff_all_required = 1 << 1,
|
||||
ff_all_no_export = 1 << 2,
|
||||
|
||||
/* flags that apply to fields of type /Btn (button) */
|
||||
ff_btn_no_toggle_off = 1 << 14,
|
||||
ff_btn_radio = 1 << 15,
|
||||
ff_btn_pushbutton = 1 << 16,
|
||||
ff_btn_radios_in_unison = 1 << 17,
|
||||
|
||||
/* flags that apply to fields of type /Tx (text) */
|
||||
ff_tx_multiline = 1 << 12,
|
||||
ff_tx_password = 1 << 13,
|
||||
ff_tx_file_select = 1 << 20,
|
||||
ff_tx_do_not_spell_check = 1 << 22,
|
||||
ff_tx_do_not_scroll = 1 << 23,
|
||||
ff_tx_comb = 1 << 24,
|
||||
ff_tx_rich_text = 1 << 25,
|
||||
|
||||
/* flags that apply to fields of type /Ch (choice) */
|
||||
ff_ch_combo = 1 << 17,
|
||||
ff_ch_edit = 1 << 18,
|
||||
ff_ch_sort = 1 << 19,
|
||||
ff_ch_multi_select = 1 << 21,
|
||||
ff_ch_do_not_spell_check = 1 << 22,
|
||||
ff_ch_commit_on_sel_change = 1 << 26
|
||||
};
|
||||
|
||||
/* Annotation flags from the PDF spec */
|
||||
|
||||
enum pdf_annotation_flag_e {
|
||||
an_invisible = 1 << 0,
|
||||
an_hidden = 1 << 1,
|
||||
an_print = 1 << 2,
|
||||
an_no_zoom = 1 << 3,
|
||||
an_no_rotate = 1 << 4,
|
||||
an_no_view = 1 << 5,
|
||||
an_read_only = 1 << 6,
|
||||
an_locked = 1 << 7,
|
||||
an_toggle_no_view = 1 << 8,
|
||||
an_locked_contents = 1 << 9
|
||||
};
|
||||
|
||||
/* Encryption/password status for QPDFJob */
|
||||
enum qpdf_encryption_status_e { qpdf_es_encrypted = 1 << 0, qpdf_es_password_incorrect = 1 << 1 };
|
||||
|
||||
/* Page label types */
|
||||
enum qpdf_page_label_e {
|
||||
pl_none,
|
||||
pl_digits,
|
||||
pl_alpha_lower,
|
||||
pl_alpha_upper,
|
||||
pl_roman_lower,
|
||||
pl_roman_upper,
|
||||
};
|
||||
|
||||
/**
|
||||
* @enum qpdf_result_e
|
||||
* @brief Enum representing result codes for qpdf C-API functions.
|
||||
*
|
||||
* Results <= qpdf_r_no_warn indicate success without warnings,
|
||||
* qpdf_r_no_warn < result <= qpdf_r_success indicates success with warnings, and
|
||||
* qpdf_r_success < result indicates failure.
|
||||
*/
|
||||
enum qpdf_result_e {
|
||||
/* success */
|
||||
qpdf_r_ok = 0,
|
||||
qpdf_r_no_warn = 0xff, /// any result <= qpdf_no_warn indicates success without warning
|
||||
qpdf_r_success = 0xffff, /// any result <= qpdf_r_success indicates success
|
||||
/* failure */
|
||||
qpdf_r_bad_parameter = 0x10000,
|
||||
|
||||
qpdf_r_no_warn_mask = 0x7fffff00,
|
||||
qpdf_r_success_mask = 0x7fff0000,
|
||||
};
|
||||
|
||||
/**
|
||||
* @enum qpdf_param_e
|
||||
* @brief This enumeration defines various parameters and configuration options for qpdf C-API
|
||||
* functions.
|
||||
*
|
||||
* The enum values are grouped into sections based on their functionality, such as global
|
||||
* options or global limits. For the meaning of individual parameters see `qpdf/global.cc`
|
||||
*/
|
||||
enum qpdf_param_e {
|
||||
/* global state */
|
||||
qpdf_p_limit_errors = 0x10020,
|
||||
|
||||
/* global options */
|
||||
qpdf_p_inspection_mode = 0x11000,
|
||||
qpdf_p_default_limits = 0x11100,
|
||||
/* global limits */
|
||||
|
||||
/* parser limits */
|
||||
qpdf_p_parser_max_nesting = 0x13000,
|
||||
qpdf_p_parser_max_errors,
|
||||
qpdf_p_parser_max_container_size,
|
||||
qpdf_p_parser_max_container_size_damaged,
|
||||
|
||||
/* stream and filter limits */
|
||||
qpdf_p_max_stream_filters = 0x14000,
|
||||
|
||||
/* next section = 0x20000 */
|
||||
qpdf_enum_max = 0x7fffffff,
|
||||
};
|
||||
|
||||
#endif /* QPDFCONSTANTS_H */
|
||||
@@ -0,0 +1,140 @@
|
||||
/* Copyright (c) 2005-2021 Jay Berkenbilt
|
||||
* Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger
|
||||
*
|
||||
* 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_DLL_HH
|
||||
#define QPDF_DLL_HH
|
||||
|
||||
/* The first version of qpdf to include the version constants is 10.6.0. */
|
||||
#define QPDF_MAJOR_VERSION 12
|
||||
#define QPDF_MINOR_VERSION 3
|
||||
#define QPDF_PATCH_VERSION 2
|
||||
|
||||
#ifdef QPDF_FUTURE
|
||||
# define QPDF_VERSION "12.3.2+future"
|
||||
#else
|
||||
# define QPDF_VERSION "12.3.2"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This file defines symbols that control the which functions,
|
||||
* classes, and methods are exposed to the public ABI (application
|
||||
* binary interface). See below for a detailed explanation.
|
||||
*/
|
||||
|
||||
#if defined _WIN32 || defined __CYGWIN__
|
||||
# ifdef libqpdf_EXPORTS
|
||||
# define QPDF_DLL __declspec(dllexport)
|
||||
# else
|
||||
# define QPDF_DLL
|
||||
# endif
|
||||
# define QPDF_DLL_PRIVATE
|
||||
#elif defined __GNUC__
|
||||
# define QPDF_DLL __attribute__((visibility("default")))
|
||||
# define QPDF_DLL_PRIVATE __attribute__((visibility("hidden")))
|
||||
#else
|
||||
# define QPDF_DLL
|
||||
# define QPDF_DLL_PRIVATE
|
||||
#endif
|
||||
#ifdef __GNUC__
|
||||
# define QPDF_DLL_CLASS QPDF_DLL
|
||||
#else
|
||||
# define QPDF_DLL_CLASS
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
||||
Here's what's happening. See also https://gcc.gnu.org/wiki/Visibility
|
||||
for a more in-depth discussion.
|
||||
|
||||
* Everything in the public ABI must be exported. Things not in the
|
||||
public ABI should not be exported.
|
||||
|
||||
* A class's runtime type information is need if the class is going to
|
||||
be used as an exception, inherited from, or tested with
|
||||
dynamic_class. To do these things across a shared object boundary,
|
||||
runtime type information must be exported.
|
||||
|
||||
* On Windows:
|
||||
|
||||
* For a symbol (function, method, etc.) to be exported into the
|
||||
public ABI, it must be explicitly marked for export.
|
||||
|
||||
* If you mark a class for export, all symbols in the class,
|
||||
including private methods, are exported into the DLL, and there is
|
||||
no way to exclude something from export.
|
||||
|
||||
* A class's run-time type information is made available based on the
|
||||
presence of a compiler flag (with MSVC), which is always on for
|
||||
qpdf builds.
|
||||
|
||||
* Marking classes for export should be done only when *building* the
|
||||
DLL, not when *using* the DLL.
|
||||
|
||||
* It is possible to mark symbols for import for DLL users, but it is
|
||||
not necessary, and doing it right is complex in our case of being
|
||||
multi-platform and building both static and shared libraries that
|
||||
use the same headers, so we don't bother.
|
||||
|
||||
* If we don't export base classes with mingw, the vtables don't end
|
||||
up in the DLL.
|
||||
|
||||
* On Linux (and other similar systems):
|
||||
|
||||
* Common compilers such as gcc and clang export all symbols into the
|
||||
public ABI by default. The qpdf build overrides this by using
|
||||
"visibility=hidden", which makes it behave more like Windows in
|
||||
that things have to be explicitly exported to appear in the public
|
||||
ABI.
|
||||
|
||||
* As with Windows, marking a class for export causes everything in
|
||||
the class, including private methods, the be exported. However,
|
||||
unlike in Windows:
|
||||
|
||||
* It is possible to explicitly mark symbols as private
|
||||
|
||||
* The only way to get the runtime type and vtable information into
|
||||
the ABI is to mark the class as exported.
|
||||
|
||||
* It is harmless and sometimes necessary to include the visibility
|
||||
marks when using the library as well as when building it. In
|
||||
particular, clang on MacOS requires the visibility marks to
|
||||
match in both cases.
|
||||
|
||||
What does this mean:
|
||||
|
||||
* On Windows, we never have to export a class, and while there is no
|
||||
way to "unexport" something, we also have no need to do it.
|
||||
|
||||
* On non-Windows, we have to export some classes, and when we do, we
|
||||
have to "unexport" some of their parts.
|
||||
|
||||
* We only use the libqpdf_EXPORTS as a conditional for defining the
|
||||
symbols for Windows builds.
|
||||
|
||||
To achieve this, we use QPDF_DLL_CLASS to export classes, QPDF_DLL to
|
||||
export methods, and QPDF_DLL_PRIVATE to unexport private methods in
|
||||
exported classes.
|
||||
|
||||
*/
|
||||
|
||||
#endif /* QPDF_DLL_HH */
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
// Copyright (c) 2005-2021 Jay Berkenbilt
|
||||
// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger
|
||||
//
|
||||
// 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_FILEINPUTSOURCE_HH
|
||||
#define QPDF_FILEINPUTSOURCE_HH
|
||||
|
||||
#include <qpdf/InputSource.hh>
|
||||
|
||||
class QPDF_DLL_CLASS FileInputSource: public InputSource
|
||||
{
|
||||
public:
|
||||
FileInputSource() = default;
|
||||
QPDF_DLL
|
||||
FileInputSource(char const* filename);
|
||||
QPDF_DLL
|
||||
FileInputSource(char const* description, FILE* filep, bool close_file);
|
||||
QPDF_DLL
|
||||
void setFilename(char const* filename);
|
||||
QPDF_DLL
|
||||
void setFile(char const* description, FILE* filep, bool close_file);
|
||||
|
||||
FileInputSource(FileInputSource const&) = delete;
|
||||
FileInputSource& operator=(FileInputSource const&) = delete;
|
||||
|
||||
QPDF_DLL
|
||||
~FileInputSource() override;
|
||||
QPDF_DLL
|
||||
qpdf_offset_t findAndSkipNextEOL() override;
|
||||
QPDF_DLL
|
||||
std::string const& getName() const override;
|
||||
QPDF_DLL
|
||||
qpdf_offset_t tell() override;
|
||||
QPDF_DLL
|
||||
void seek(qpdf_offset_t offset, int whence) override;
|
||||
QPDF_DLL
|
||||
void rewind() override;
|
||||
QPDF_DLL
|
||||
size_t read(char* buffer, size_t length) override;
|
||||
QPDF_DLL
|
||||
void unreadCh(char ch) override;
|
||||
|
||||
private:
|
||||
bool close_file{false};
|
||||
std::string filename;
|
||||
FILE* file{nullptr};
|
||||
};
|
||||
|
||||
#endif // QPDF_FILEINPUTSOURCE_HH
|
||||
+100
@@ -0,0 +1,100 @@
|
||||
// Copyright (c) 2005-2021 Jay Berkenbilt
|
||||
// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger
|
||||
//
|
||||
// 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_INPUTSOURCE_HH
|
||||
#define QPDF_INPUTSOURCE_HH
|
||||
|
||||
#include <qpdf/DLL.h>
|
||||
#include <qpdf/Types.h>
|
||||
|
||||
#include <cstdio>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
// Remember to use QPDF_DLL_CLASS on anything derived from InputSource so it will work with
|
||||
// dynamic_cast across the shared object boundary.
|
||||
class QPDF_DLL_CLASS InputSource
|
||||
{
|
||||
public:
|
||||
InputSource() = default;
|
||||
|
||||
virtual ~InputSource() = default;
|
||||
|
||||
class QPDF_DLL_CLASS Finder
|
||||
{
|
||||
public:
|
||||
QPDF_DLL
|
||||
Finder() = default;
|
||||
QPDF_DLL
|
||||
virtual ~Finder() = default;
|
||||
virtual bool check() = 0;
|
||||
};
|
||||
|
||||
QPDF_DLL
|
||||
void setLastOffset(qpdf_offset_t);
|
||||
QPDF_DLL
|
||||
qpdf_offset_t getLastOffset() const;
|
||||
QPDF_DLL
|
||||
std::string readLine(size_t max_line_length);
|
||||
|
||||
// Find first or last occurrence of a sequence of characters starting within the range defined
|
||||
// by offset and len such that, when the input source is positioned at the beginning of that
|
||||
// sequence, finder.check() returns true. If len is 0, the search proceeds until EOF. If a
|
||||
// qualifying pattern is found, these methods return true and leave the input source positioned
|
||||
// wherever check() left it at the end of the matching pattern.
|
||||
QPDF_DLL
|
||||
bool findFirst(char const* start_chars, qpdf_offset_t offset, size_t len, Finder& finder);
|
||||
QPDF_DLL
|
||||
bool findLast(char const* start_chars, qpdf_offset_t offset, size_t len, Finder& finder);
|
||||
|
||||
virtual qpdf_offset_t findAndSkipNextEOL() = 0;
|
||||
virtual std::string const& getName() const = 0;
|
||||
virtual qpdf_offset_t tell() = 0;
|
||||
virtual void seek(qpdf_offset_t offset, int whence) = 0;
|
||||
virtual void rewind() = 0;
|
||||
virtual size_t read(char* buffer, size_t length) = 0;
|
||||
|
||||
// Note: you can only unread the character you just read. The specific character is ignored by
|
||||
// some implementations, and the implementation doesn't check this. Use of unreadCh is
|
||||
// semantically equivalent to seek(-1, SEEK_CUR) but is much more efficient.
|
||||
virtual void unreadCh(char ch) = 0;
|
||||
|
||||
// The following methods are for internal use by qpdf only.
|
||||
inline size_t read(std::string& str, size_t count, qpdf_offset_t at = -1);
|
||||
inline std::string read(size_t count, qpdf_offset_t at = -1);
|
||||
size_t read_line(std::string& str, size_t count, qpdf_offset_t at = -1);
|
||||
std::string read_line(size_t count, qpdf_offset_t at = -1);
|
||||
inline qpdf_offset_t fastTell();
|
||||
inline bool fastRead(char&);
|
||||
inline void fastUnread(bool);
|
||||
inline void loadBuffer();
|
||||
|
||||
protected:
|
||||
qpdf_offset_t last_offset{0};
|
||||
|
||||
private:
|
||||
// State for fast... methods
|
||||
static const qpdf_offset_t buf_size = 128;
|
||||
char buffer[buf_size];
|
||||
qpdf_offset_t buf_len = 0;
|
||||
qpdf_offset_t buf_idx = 0;
|
||||
qpdf_offset_t buf_start = 0;
|
||||
};
|
||||
|
||||
#endif // QPDF_INPUTSOURCE_HH
|
||||
@@ -0,0 +1,404 @@
|
||||
// Copyright (c) 2005-2021 Jay Berkenbilt
|
||||
// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger
|
||||
//
|
||||
// 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 JSON_HH
|
||||
#define JSON_HH
|
||||
|
||||
#include <qpdf/DLL.h>
|
||||
#include <qpdf/Types.h>
|
||||
|
||||
#include <functional>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class Pipeline;
|
||||
class InputSource;
|
||||
|
||||
// This is a simple JSON serializer and parser, primarily designed for serializing QPDF Objects as
|
||||
// JSON. While it may work as a general-purpose JSON parser/serializer, there are better options.
|
||||
// JSON objects contain their data as smart pointers. When one JSON object is added to another, this
|
||||
// pointer is copied. This means you can create temporary JSON objects on the stack, add them to
|
||||
// other objects, and let them go out of scope safely. It also means that if a JSON object is added
|
||||
// in more than one place, all copies share the underlying data. This makes them similar in
|
||||
// structure and behavior to QPDFObjectHandle and may feel natural within the QPDF codebase, but it
|
||||
// is also a good reason not to use this as a general-purpose JSON package.
|
||||
class JSON
|
||||
{
|
||||
public:
|
||||
static int constexpr LATEST = 2;
|
||||
|
||||
JSON() = default;
|
||||
|
||||
QPDF_DLL
|
||||
std::string unparse() const;
|
||||
|
||||
// Write the JSON object through a pipeline. The `depth` parameter specifies how deeply nested
|
||||
// this is in another JSON structure, which makes it possible to write clean-looking JSON
|
||||
// incrementally.
|
||||
QPDF_DLL
|
||||
void write(Pipeline*, size_t depth = 0) const;
|
||||
|
||||
// Helper methods for writing JSON incrementally.
|
||||
//
|
||||
// "first" -- Several methods take a `bool& first` parameter. The open methods always set it to
|
||||
// true, and the methods to output items always set it to false. This way, the item and close
|
||||
// methods can always know whether or not a first item is being written. The intended mode of
|
||||
// operation is to start with a new `bool first = true` each time a new container is opened and
|
||||
// to pass that `first` through to all the methods that are called to add top-level items to the
|
||||
// container as well as to close the container. This lets the JSON object use it to keep track
|
||||
// of when it's writing a first object and when it's not. If incrementally writing multiple
|
||||
// levels of depth, a new `first` should be used for each new container that is opened.
|
||||
//
|
||||
// "depth" -- Indicate the level of depth. This is used for consistent indentation. When writing
|
||||
// incrementally, whenever you call a method to add an item to a container, the value of `depth`
|
||||
// should be one more than whatever value is passed to the container open and close methods.
|
||||
|
||||
// Open methods ignore the value of first and set it to false
|
||||
QPDF_DLL
|
||||
static void writeDictionaryOpen(Pipeline*, bool& first, size_t depth = 0);
|
||||
QPDF_DLL
|
||||
static void writeArrayOpen(Pipeline*, bool& first, size_t depth = 0);
|
||||
// Close methods don't modify first. A true value indicates that we are closing an empty object.
|
||||
QPDF_DLL
|
||||
static void writeDictionaryClose(Pipeline*, bool first, size_t depth = 0);
|
||||
QPDF_DLL
|
||||
static void writeArrayClose(Pipeline*, bool first, size_t depth = 0);
|
||||
// The item methods use the value of first to determine if this is the first item and always set
|
||||
// it to false.
|
||||
QPDF_DLL
|
||||
static void writeDictionaryItem(
|
||||
Pipeline*, bool& first, std::string const& key, JSON const& value, size_t depth = 0);
|
||||
// Write just the key of a new dictionary item, useful if writing nested structures. Calls
|
||||
// writeNext.
|
||||
QPDF_DLL
|
||||
static void
|
||||
writeDictionaryKey(Pipeline* p, bool& first, std::string const& key, size_t depth = 0);
|
||||
QPDF_DLL
|
||||
static void writeArrayItem(Pipeline*, bool& first, JSON const& element, size_t depth = 0);
|
||||
// If writing nested structures incrementally, call writeNext before opening a new array or
|
||||
// container in the midst of an existing one. The `first` you pass to writeNext should be the
|
||||
// one for the parent object. The depth should be the one for the child object. Then start a new
|
||||
// `first` for the nested item. Note that writeDictionaryKey and writeArrayItem call writeNext
|
||||
// for you, so this is most important when writing subsequent items or container openers to an
|
||||
// array.
|
||||
QPDF_DLL
|
||||
static void writeNext(Pipeline* p, bool& first, size_t depth = 0);
|
||||
|
||||
// The JSON spec calls dictionaries "objects", but that creates too much confusion when
|
||||
// referring to instances of the JSON class.
|
||||
QPDF_DLL
|
||||
static JSON makeDictionary();
|
||||
// addDictionaryMember returns the newly added item.
|
||||
QPDF_DLL
|
||||
JSON addDictionaryMember(std::string const& key, JSON const&);
|
||||
QPDF_DLL
|
||||
static JSON makeArray();
|
||||
// addArrayElement returns the newly added item.
|
||||
QPDF_DLL
|
||||
JSON addArrayElement(JSON const&);
|
||||
QPDF_DLL
|
||||
static JSON makeString(std::string const& utf8);
|
||||
QPDF_DLL
|
||||
static JSON makeInt(long long int value);
|
||||
QPDF_DLL
|
||||
static JSON makeReal(double value);
|
||||
QPDF_DLL
|
||||
static JSON makeNumber(std::string const& encoded);
|
||||
QPDF_DLL
|
||||
static JSON makeBool(bool value);
|
||||
QPDF_DLL
|
||||
static JSON makeNull();
|
||||
|
||||
// A blob serializes as a string. The function will be called by JSON with a pipeline and should
|
||||
// write binary data to the pipeline but not call finish(). JSON will call finish() at the right
|
||||
// time.
|
||||
QPDF_DLL
|
||||
static JSON makeBlob(std::function<void(Pipeline*)>);
|
||||
|
||||
QPDF_DLL
|
||||
bool isArray() const;
|
||||
|
||||
QPDF_DLL
|
||||
bool isDictionary() const;
|
||||
|
||||
// Accessors. Accessor behavior:
|
||||
//
|
||||
// - If argument is wrong type, including null, return false
|
||||
// - If argument is right type, return true and initialize the value
|
||||
|
||||
QPDF_DLL
|
||||
bool getString(std::string& utf8) const;
|
||||
QPDF_DLL
|
||||
bool getNumber(std::string& value) const;
|
||||
QPDF_DLL
|
||||
bool getBool(bool& value) const;
|
||||
QPDF_DLL
|
||||
bool isNull() const;
|
||||
QPDF_DLL
|
||||
JSON getDictItem(std::string const& key) const;
|
||||
QPDF_DLL
|
||||
bool forEachDictItem(std::function<void(std::string const& key, JSON value)> fn) const;
|
||||
QPDF_DLL
|
||||
bool forEachArrayItem(std::function<void(JSON value)> fn) const;
|
||||
|
||||
// Check this JSON object against a "schema". This is not a schema according to any standard.
|
||||
// It's just a template of what the JSON is supposed to contain. The checking does the
|
||||
// following:
|
||||
//
|
||||
// * The schema is a nested structure containing dictionaries, single-element arrays, and
|
||||
// strings only.
|
||||
// * Recursively walk the schema. In the items below, "schema object" refers to an object in
|
||||
// the schema, and "checked object" refers to the corresponding part of the object being
|
||||
// checked.
|
||||
// * If the schema object is a dictionary, the checked object must have a dictionary in the
|
||||
// same place with the same keys. If flags contains f_optional, a key in the schema does not
|
||||
// have to be present in the object. Otherwise, all keys have to be present. Any key in the
|
||||
// object must be present in the schema.
|
||||
// * If the schema object is an array of length 1, the checked object may either be a single
|
||||
// item or an array of items. The single item or each element of the checked object's
|
||||
// array is validated against the single element of the schema's array. The rationale behind
|
||||
// this logic is that a single element may appear wherever the schema allows a
|
||||
// variable-length array. This makes it possible to start allowing an array in the future
|
||||
// where a single element was previously required without breaking backward compatibility.
|
||||
// * If the schema object is an array of length > 1, the checked object must be an array of
|
||||
// the same length. In this case, each element of the checked object array is validated
|
||||
// against the corresponding element of the schema array.
|
||||
// * Otherwise, the value must be a string whose value is a description of the object's
|
||||
// corresponding value, which may have any type.
|
||||
//
|
||||
// QPDF's JSON output conforms to certain strict compatibility rules as discussed in the manual.
|
||||
// The idea is that a JSON structure created manually in qpdf.cc doubles as both JSON help
|
||||
// information and a schema for validating the JSON that qpdf generates. Any discrepancies are a
|
||||
// bug in qpdf.
|
||||
//
|
||||
// Flags is a bitwise or of values from check_flags_e.
|
||||
enum check_flags_e {
|
||||
f_none = 0,
|
||||
f_optional = 1 << 0,
|
||||
};
|
||||
QPDF_DLL
|
||||
bool checkSchema(JSON schema, unsigned long flags, std::list<std::string>& errors);
|
||||
|
||||
// Same as passing 0 for flags
|
||||
QPDF_DLL
|
||||
bool checkSchema(JSON schema, std::list<std::string>& errors);
|
||||
|
||||
// A pointer to a Reactor class can be passed to parse, which will enable the caller to react
|
||||
// to incremental events in the construction of the JSON object. This makes it possible to
|
||||
// implement SAX-like handling of very large JSON objects.
|
||||
class QPDF_DLL_CLASS Reactor
|
||||
{
|
||||
public:
|
||||
virtual ~Reactor() = default;
|
||||
|
||||
// The start/end methods are called when parsing of a dictionary or array is started or
|
||||
// ended. The item methods are called when an item is added to a dictionary or array. When
|
||||
// adding a container to another container, the item method is called with an empty
|
||||
// container before the lower container's start method is called. See important notes in
|
||||
// "Item methods" below.
|
||||
|
||||
// During parsing of a JSON string, the parser is operating on a single object at a time.
|
||||
// When a dictionary or array is started, a new context begins, and when that dictionary or
|
||||
// array is ended, the previous context is resumed. So, for
|
||||
// example, if you have `{"a": [1]}`, you will receive the
|
||||
// following method calls
|
||||
//
|
||||
// dictionaryStart -- current object is the top-level dictionary
|
||||
// dictionaryItem -- called with "a" and an empty array
|
||||
// arrayStart -- current object is the array
|
||||
// arrayItem -- called with the "1" object
|
||||
// containerEnd -- now current object is the dictionary again
|
||||
// containerEnd -- current object is undefined
|
||||
//
|
||||
// If the top-level item in a JSON string is a scalar, the topLevelScalar() method will be
|
||||
// called. No argument is passed since the object is the same as what is returned by
|
||||
// parse().
|
||||
|
||||
QPDF_DLL
|
||||
virtual void dictionaryStart() = 0;
|
||||
QPDF_DLL
|
||||
virtual void arrayStart() = 0;
|
||||
QPDF_DLL
|
||||
virtual void containerEnd(JSON const& value) = 0;
|
||||
QPDF_DLL
|
||||
virtual void topLevelScalar() = 0;
|
||||
|
||||
// Item methods:
|
||||
//
|
||||
// The return value of the item methods indicate whether the item has been "consumed". If
|
||||
// the item method returns true, then the item will not be added to the containing JSON
|
||||
// object. This is what allows arbitrarily large JSON objects
|
||||
// to be parsed and not have to be kept in memory.
|
||||
//
|
||||
// NOTE: When a dictionary or an array is added to a container, the dictionaryItem or
|
||||
// arrayItem method is called when the child item's start delimiter is encountered, so the
|
||||
// JSON object passed in at that time will always be in its initial, empty state.
|
||||
// Additionally, the child item's start method is not called until after the parent item's
|
||||
// item method is called. This makes it possible to keep track of the current depth level by
|
||||
// incrementing level on start methods and decrementing on end methods.
|
||||
|
||||
QPDF_DLL
|
||||
virtual bool dictionaryItem(std::string const& key, JSON const& value) = 0;
|
||||
QPDF_DLL
|
||||
virtual bool arrayItem(JSON const& value) = 0;
|
||||
};
|
||||
|
||||
// Create a JSON object from a string.
|
||||
QPDF_DLL
|
||||
static JSON parse(std::string const&);
|
||||
// Create a JSON object from an input source. See above for information about how to use the
|
||||
// Reactor.
|
||||
QPDF_DLL
|
||||
static JSON parse(InputSource&, Reactor* reactor = nullptr);
|
||||
|
||||
// parse calls setOffsets to set the inclusive start and non-inclusive end offsets of an object
|
||||
// relative to its input string. Otherwise, both values are 0.
|
||||
QPDF_DLL
|
||||
void setStart(qpdf_offset_t);
|
||||
QPDF_DLL
|
||||
void setEnd(qpdf_offset_t);
|
||||
QPDF_DLL
|
||||
qpdf_offset_t getStart() const;
|
||||
QPDF_DLL
|
||||
qpdf_offset_t getEnd() const;
|
||||
|
||||
// The following class does not form part of the public API and is for internal use only.
|
||||
|
||||
class Writer;
|
||||
|
||||
private:
|
||||
static void writeClose(Pipeline* p, bool first, size_t depth, char const* delimeter);
|
||||
|
||||
enum value_type_e {
|
||||
vt_none,
|
||||
vt_dictionary,
|
||||
vt_array,
|
||||
vt_string,
|
||||
vt_number,
|
||||
vt_bool,
|
||||
vt_null,
|
||||
vt_blob,
|
||||
};
|
||||
|
||||
struct JSON_value
|
||||
{
|
||||
JSON_value(value_type_e type_code) :
|
||||
type_code(type_code)
|
||||
{
|
||||
}
|
||||
virtual ~JSON_value() = default;
|
||||
virtual void write(Pipeline*, size_t depth) const = 0;
|
||||
const value_type_e type_code{vt_none};
|
||||
};
|
||||
struct JSON_dictionary: public JSON_value
|
||||
{
|
||||
JSON_dictionary() :
|
||||
JSON_value(vt_dictionary)
|
||||
{
|
||||
}
|
||||
~JSON_dictionary() override = default;
|
||||
void write(Pipeline*, size_t depth) const override;
|
||||
std::map<std::string, JSON> members;
|
||||
};
|
||||
struct JSON_array;
|
||||
struct JSON_string: public JSON_value
|
||||
{
|
||||
JSON_string(std::string const& utf8);
|
||||
~JSON_string() override = default;
|
||||
void write(Pipeline*, size_t depth) const override;
|
||||
std::string utf8;
|
||||
};
|
||||
struct JSON_number: public JSON_value
|
||||
{
|
||||
JSON_number(long long val);
|
||||
JSON_number(double val);
|
||||
JSON_number(std::string const& val);
|
||||
~JSON_number() override = default;
|
||||
void write(Pipeline*, size_t depth) const override;
|
||||
std::string encoded;
|
||||
};
|
||||
struct JSON_bool: public JSON_value
|
||||
{
|
||||
JSON_bool(bool val);
|
||||
~JSON_bool() override = default;
|
||||
void write(Pipeline*, size_t depth) const override;
|
||||
bool value;
|
||||
};
|
||||
struct JSON_null: public JSON_value
|
||||
{
|
||||
JSON_null() :
|
||||
JSON_value(vt_null)
|
||||
{
|
||||
}
|
||||
~JSON_null() override = default;
|
||||
void write(Pipeline*, size_t depth) const override;
|
||||
};
|
||||
struct JSON_blob: public JSON_value
|
||||
{
|
||||
JSON_blob(std::function<void(Pipeline*)> fn);
|
||||
~JSON_blob() override = default;
|
||||
void write(Pipeline*, size_t depth) const override;
|
||||
std::function<void(Pipeline*)> fn;
|
||||
};
|
||||
|
||||
JSON(std::unique_ptr<JSON_value>);
|
||||
|
||||
static void checkSchemaInternal(
|
||||
JSON_value* this_v,
|
||||
JSON_value* sch_v,
|
||||
unsigned long flags,
|
||||
std::list<std::string>& errors,
|
||||
std::string prefix);
|
||||
|
||||
class Members
|
||||
{
|
||||
friend class JSON;
|
||||
|
||||
public:
|
||||
~Members() = default;
|
||||
|
||||
private:
|
||||
Members(std::unique_ptr<JSON_value>);
|
||||
Members(Members const&) = delete;
|
||||
|
||||
std::unique_ptr<JSON_value> value;
|
||||
// start and end are only populated for objects created by parse
|
||||
qpdf_offset_t start{0};
|
||||
qpdf_offset_t end{0};
|
||||
};
|
||||
|
||||
std::shared_ptr<Members> m;
|
||||
};
|
||||
|
||||
struct JSON::JSON_array: public JSON_value
|
||||
{
|
||||
JSON_array() :
|
||||
JSON_value(vt_array)
|
||||
{
|
||||
}
|
||||
~JSON_array() override = default;
|
||||
void write(Pipeline*, size_t depth) const override;
|
||||
std::vector<JSON> elements;
|
||||
};
|
||||
|
||||
#endif // JSON_HH
|
||||
+155
@@ -0,0 +1,155 @@
|
||||
// Copyright (c) 2005-2021 Jay Berkenbilt
|
||||
// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger
|
||||
//
|
||||
// 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 OBJECTHANDLE_HH
|
||||
#define OBJECTHANDLE_HH
|
||||
|
||||
#include <qpdf/Constants.h>
|
||||
#include <qpdf/DLL.h>
|
||||
#include <qpdf/Types.h>
|
||||
|
||||
#include <qpdf/JSON.hh>
|
||||
#include <qpdf/QPDFExc.hh>
|
||||
#include <qpdf/QPDFObjGen.hh>
|
||||
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
|
||||
class QPDF;
|
||||
class QPDF_Dictionary;
|
||||
class QPDFObject;
|
||||
class QPDFObjectHandle;
|
||||
|
||||
namespace qpdf
|
||||
{
|
||||
class Array;
|
||||
class BaseDictionary;
|
||||
class Dictionary;
|
||||
class Integer;
|
||||
class Stream;
|
||||
|
||||
enum typed : std::uint8_t { strict = 0, any_flag = 1, optional = 2, any = 3, error = 4 };
|
||||
|
||||
// Basehandle is only used as a base-class for QPDFObjectHandle like classes. Currently the only
|
||||
// methods exposed in public API are operators to convert derived objects to QPDFObjectHandle,
|
||||
// QPDFObjGen and bool.
|
||||
class BaseHandle
|
||||
{
|
||||
friend class ::QPDF;
|
||||
|
||||
public:
|
||||
explicit inline operator bool() const;
|
||||
inline operator QPDFObjectHandle() const;
|
||||
QPDF_DLL
|
||||
operator QPDFObjGen() const;
|
||||
|
||||
// The rest of the header file is for qpdf internal use only.
|
||||
|
||||
// Return true if both object handles refer to the same underlying object.
|
||||
bool
|
||||
operator==(BaseHandle const& other) const
|
||||
{
|
||||
return obj == other.obj;
|
||||
}
|
||||
|
||||
// For arrays, return the number of items in the array.
|
||||
// For null-like objects, return 0.
|
||||
// For all other objects, return 1.
|
||||
size_t size() const;
|
||||
|
||||
// Return 'true' if size() == 0.
|
||||
bool
|
||||
empty() const
|
||||
{
|
||||
return size() == 0;
|
||||
}
|
||||
|
||||
QPDFObjectHandle operator[](size_t n) const;
|
||||
QPDFObjectHandle operator[](int n) const;
|
||||
|
||||
QPDFObjectHandle& at(std::string const& key) const;
|
||||
bool contains(std::string const& key) const;
|
||||
size_t erase(std::string const& key);
|
||||
QPDFObjectHandle& find(std::string const& key) const;
|
||||
bool replace(std::string const& key, QPDFObjectHandle value);
|
||||
QPDFObjectHandle const& operator[](std::string const& key) const;
|
||||
|
||||
std::shared_ptr<QPDFObject> copy(bool shallow = false) const;
|
||||
// Recursively remove association with any QPDF object. This method may only be called
|
||||
// during final destruction.
|
||||
void disconnect(bool only_direct = true);
|
||||
inline QPDFObjGen id_gen() const;
|
||||
inline bool indirect() const;
|
||||
inline bool null() const;
|
||||
inline qpdf_offset_t offset() const;
|
||||
inline QPDF* qpdf() const;
|
||||
inline qpdf_object_type_e raw_type_code() const;
|
||||
inline qpdf_object_type_e resolved_type_code() const;
|
||||
inline qpdf_object_type_e type_code() const;
|
||||
std::string unparse() const;
|
||||
void write_json(int json_version, JSON::Writer& p) const;
|
||||
static void warn(QPDF*, QPDFExc&&);
|
||||
void warn(QPDFExc&&) const;
|
||||
void warn(std::string const& warning) const;
|
||||
|
||||
inline std::shared_ptr<QPDFObject> const& obj_sp() const;
|
||||
inline QPDFObjectHandle oh() const;
|
||||
|
||||
protected:
|
||||
BaseHandle() = default;
|
||||
BaseHandle(std::shared_ptr<QPDFObject> const& obj) :
|
||||
obj(obj) {};
|
||||
BaseHandle(std::shared_ptr<QPDFObject>&& obj) :
|
||||
obj(std::move(obj)) {};
|
||||
BaseHandle(BaseHandle const&) = default;
|
||||
BaseHandle& operator=(BaseHandle const&) = default;
|
||||
BaseHandle(BaseHandle&&) = default;
|
||||
BaseHandle& operator=(BaseHandle&&) = default;
|
||||
|
||||
inline BaseHandle(QPDFObjectHandle const& oh);
|
||||
inline BaseHandle(QPDFObjectHandle&& oh);
|
||||
|
||||
~BaseHandle() = default;
|
||||
|
||||
template <typename T>
|
||||
T* as() const;
|
||||
|
||||
inline void assign(qpdf_object_type_e required, BaseHandle const& other);
|
||||
inline void assign(qpdf_object_type_e required, BaseHandle&& other);
|
||||
|
||||
inline void nullify();
|
||||
|
||||
std::string description() const;
|
||||
|
||||
inline QPDFObjectHandle const& get(std::string const& key) const;
|
||||
|
||||
void no_ci_warn_if(bool condition, std::string const& warning) const;
|
||||
void no_ci_stop_if(bool condition, std::string const& warning) const;
|
||||
void no_ci_stop_damaged_if(bool condition, std::string const& warning) const;
|
||||
std::invalid_argument invalid_error(std::string const& method) const;
|
||||
std::runtime_error type_error(char const* expected_type) const;
|
||||
QPDFExc type_error(char const* expected_type, std::string const& message) const;
|
||||
char const* type_name() const;
|
||||
|
||||
std::shared_ptr<QPDFObject> obj;
|
||||
};
|
||||
|
||||
} // namespace qpdf
|
||||
|
||||
#endif // QPDFOBJECTHANDLE_HH
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
// Copyright (c) 2005-2021 Jay Berkenbilt
|
||||
// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger
|
||||
//
|
||||
// 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 PDFVERSION_HH
|
||||
#define PDFVERSION_HH
|
||||
|
||||
#include <qpdf/DLL.h>
|
||||
#include <string>
|
||||
|
||||
// Represent a PDF version. PDF versions are typically major.minor, but PDF 1.7 has several
|
||||
// extension levels as the ISO 32000 spec was in progress. This class helps with comparison of
|
||||
// versions.
|
||||
class PDFVersion
|
||||
{
|
||||
public:
|
||||
PDFVersion() = default;
|
||||
PDFVersion(PDFVersion const&) = default;
|
||||
PDFVersion& operator=(PDFVersion const&) = default;
|
||||
|
||||
QPDF_DLL
|
||||
PDFVersion(int major, int minor, int extension = 0);
|
||||
QPDF_DLL
|
||||
bool operator<(PDFVersion const& rhs) const;
|
||||
QPDF_DLL
|
||||
bool operator==(PDFVersion const& rhs) const;
|
||||
|
||||
// Replace this version with the other one if the other one is greater.
|
||||
QPDF_DLL
|
||||
void updateIfGreater(PDFVersion const& other);
|
||||
|
||||
// Initialize a string and integer suitable for passing to QPDFWriter::setMinimumPDFVersion or
|
||||
// QPDFWriter::forcePDFVersion.
|
||||
QPDF_DLL
|
||||
void getVersion(std::string& version, int& extension_level) const;
|
||||
|
||||
QPDF_DLL
|
||||
int getMajor() const;
|
||||
QPDF_DLL
|
||||
int getMinor() const;
|
||||
QPDF_DLL
|
||||
int getExtensionLevel() const;
|
||||
|
||||
private:
|
||||
int major_version{0};
|
||||
int minor_version{0};
|
||||
int extension_level{0};
|
||||
};
|
||||
|
||||
#endif // PDFVERSION_HH
|
||||
@@ -0,0 +1,115 @@
|
||||
// Copyright (c) 2005-2021 Jay Berkenbilt
|
||||
// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger
|
||||
//
|
||||
// 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 PIPELINE_HH
|
||||
#define PIPELINE_HH
|
||||
|
||||
#include <qpdf/DLL.h>
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
// Generalized Pipeline interface. By convention, subclasses of Pipeline are called Pl_Something.
|
||||
//
|
||||
// When an instance of Pipeline is created with a pointer to a next pipeline, that pipeline writes
|
||||
// its data to the next one when it finishes with it. In order to make possible a usage style in
|
||||
// which a pipeline may be passed to a function which may stick other pipelines in front of it, the
|
||||
// allocator of a pipeline is responsible for its destruction. In other words, one pipeline object
|
||||
// does not attempt to manage the memory of its successor.
|
||||
//
|
||||
// The client is required to call finish() before destroying a Pipeline in order to avoid loss of
|
||||
// data. A Pipeline class should not throw an exception in the destructor if this hasn't been done
|
||||
// though since doing so causes too much trouble when deleting pipelines during error conditions.
|
||||
//
|
||||
// Some pipelines are reusable (i.e., you can call write() after calling finish() and can call
|
||||
// finish() multiple times) while others are not. It is up to the caller to use a pipeline
|
||||
// according to its own restrictions.
|
||||
//
|
||||
// Remember to use QPDF_DLL_CLASS on anything derived from Pipeline so it will work with
|
||||
// dynamic_cast across the shared object boundary.
|
||||
class QPDF_DLL_CLASS Pipeline
|
||||
{
|
||||
public:
|
||||
QPDF_DLL
|
||||
Pipeline(char const* identifier, Pipeline* next);
|
||||
|
||||
virtual ~Pipeline() = default;
|
||||
|
||||
// Subclasses should implement write and finish to do their jobs and then, if they are not
|
||||
// end-of-line pipelines, call getNext()->write or getNext()->finish.
|
||||
QPDF_DLL
|
||||
virtual void write(unsigned char const* data, size_t len) = 0;
|
||||
QPDF_DLL
|
||||
virtual void finish() = 0;
|
||||
QPDF_DLL
|
||||
std::string getIdentifier() const;
|
||||
|
||||
// These are convenience methods for making it easier to write certain other types of data to
|
||||
// pipelines without having to cast. The methods that take char const* expect null-terminated C
|
||||
// strings and do not write the null terminators.
|
||||
QPDF_DLL
|
||||
void writeCStr(char const* cstr);
|
||||
QPDF_DLL
|
||||
void writeString(std::string const&);
|
||||
// This allows *p << "x" << "y" but is not intended to be a general purpose << compatible with
|
||||
// ostream and does not have local awareness or the ability to be "imbued" with properties.
|
||||
QPDF_DLL
|
||||
Pipeline& operator<<(char const* cstr);
|
||||
QPDF_DLL
|
||||
Pipeline& operator<<(std::string const&);
|
||||
QPDF_DLL
|
||||
Pipeline& operator<<(short);
|
||||
QPDF_DLL
|
||||
Pipeline& operator<<(int);
|
||||
QPDF_DLL
|
||||
Pipeline& operator<<(long);
|
||||
QPDF_DLL
|
||||
Pipeline& operator<<(long long);
|
||||
QPDF_DLL
|
||||
Pipeline& operator<<(unsigned short);
|
||||
QPDF_DLL
|
||||
Pipeline& operator<<(unsigned int);
|
||||
QPDF_DLL
|
||||
Pipeline& operator<<(unsigned long);
|
||||
QPDF_DLL
|
||||
Pipeline& operator<<(unsigned long long);
|
||||
|
||||
// Overloaded write to reduce casting
|
||||
QPDF_DLL
|
||||
void write(char const* data, size_t len);
|
||||
|
||||
protected:
|
||||
QPDF_DLL
|
||||
Pipeline* getNext(bool allow_null = false);
|
||||
|
||||
Pipeline*
|
||||
next() const noexcept
|
||||
{
|
||||
return next_;
|
||||
}
|
||||
std::string identifier;
|
||||
|
||||
private:
|
||||
Pipeline(Pipeline const&) = delete;
|
||||
Pipeline& operator=(Pipeline const&) = delete;
|
||||
|
||||
Pipeline* next_;
|
||||
};
|
||||
|
||||
#endif // PIPELINE_HH
|
||||
@@ -0,0 +1,76 @@
|
||||
// Copyright (c) 2005-2021 Jay Berkenbilt
|
||||
// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger
|
||||
//
|
||||
// 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 PL_BUFFER_HH
|
||||
#define PL_BUFFER_HH
|
||||
|
||||
#include <qpdf/Buffer.hh>
|
||||
#include <qpdf/Pipeline.hh>
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
// This pipeline accumulates the data passed to it into a memory buffer. Each subsequent use of
|
||||
// this buffer appends to the data accumulated so far. getBuffer() may be called only after calling
|
||||
// finish() and before calling any subsequent write(). At that point, a dynamically allocated
|
||||
// Buffer object is returned and the internal buffer is reset. The caller is responsible for
|
||||
// deleting the returned Buffer.
|
||||
//
|
||||
// For this pipeline, "next" may be null. If a next pointer is provided, this pipeline will also
|
||||
// pass the data through to it.
|
||||
class QPDF_DLL_CLASS Pl_Buffer: public Pipeline
|
||||
{
|
||||
public:
|
||||
QPDF_DLL
|
||||
Pl_Buffer(char const* identifier, Pipeline* next = nullptr);
|
||||
QPDF_DLL
|
||||
~Pl_Buffer() override;
|
||||
QPDF_DLL
|
||||
void write(unsigned char const*, size_t) override;
|
||||
QPDF_DLL
|
||||
void finish() override;
|
||||
|
||||
// Each call to getBuffer() resets this object -- see notes above.
|
||||
// The caller is responsible for deleting the returned Buffer object. See also
|
||||
// getBufferSharedPointer() and getMallocBuffer().
|
||||
QPDF_DLL
|
||||
Buffer* getBuffer();
|
||||
|
||||
// Same as getBuffer but wraps the result in a shared pointer.
|
||||
QPDF_DLL
|
||||
std::shared_ptr<Buffer> getBufferSharedPointer();
|
||||
|
||||
// getMallocBuffer behaves in the same was as getBuffer except the buffer is allocated with
|
||||
// malloc(), making it suitable for use when calling from other languages. If there is no data,
|
||||
// *buf is set to a null pointer and *len is set to 0. Otherwise, *buf is a buffer of size *len
|
||||
// allocated with malloc(). It is the caller's responsibility to call free() on the buffer.
|
||||
QPDF_DLL
|
||||
void getMallocBuffer(unsigned char** buf, size_t* len);
|
||||
|
||||
// Same as getBuffer but returns the result as a string.
|
||||
QPDF_DLL
|
||||
std::string getString();
|
||||
|
||||
private:
|
||||
class Members;
|
||||
|
||||
std::unique_ptr<Members> m;
|
||||
};
|
||||
|
||||
#endif // PL_BUFFER_HH
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
// Copyright (c) 2005-2021 Jay Berkenbilt
|
||||
// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger
|
||||
//
|
||||
// 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 PL_CONCATENATE_HH
|
||||
#define PL_CONCATENATE_HH
|
||||
|
||||
#include <qpdf/Pipeline.hh>
|
||||
|
||||
// This pipeline will drop all regular finish calls rather than passing them onto next. To finish
|
||||
// downstream streams, call manualFinish. This makes it possible to pipe multiple streams (e.g.
|
||||
// with QPDFObjectHandle::pipeStreamData) to a downstream like Pl_Flate that can't handle multiple
|
||||
// calls to finish().
|
||||
class QPDF_DLL_CLASS Pl_Concatenate: public Pipeline
|
||||
{
|
||||
public:
|
||||
QPDF_DLL
|
||||
Pl_Concatenate(char const* identifier, Pipeline* next);
|
||||
|
||||
QPDF_DLL
|
||||
~Pl_Concatenate() override;
|
||||
|
||||
QPDF_DLL
|
||||
void write(unsigned char const* data, size_t len) override;
|
||||
|
||||
QPDF_DLL
|
||||
void finish() override;
|
||||
|
||||
// At the very end, call manualFinish to actually finish the rest of the pipeline.
|
||||
QPDF_DLL
|
||||
void manualFinish();
|
||||
|
||||
private:
|
||||
class QPDF_DLL_PRIVATE Members
|
||||
{
|
||||
friend class Pl_Concatenate;
|
||||
|
||||
public:
|
||||
~Members() = default;
|
||||
|
||||
private:
|
||||
Members() = default;
|
||||
Members(Members const&) = delete;
|
||||
};
|
||||
|
||||
std::unique_ptr<Members> m{nullptr};
|
||||
};
|
||||
|
||||
#endif // PL_CONCATENATE_HH
|
||||
@@ -0,0 +1,52 @@
|
||||
// Copyright (c) 2005-2021 Jay Berkenbilt
|
||||
// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger
|
||||
//
|
||||
// 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 PL_COUNT_HH
|
||||
#define PL_COUNT_HH
|
||||
|
||||
#include <qpdf/Pipeline.hh>
|
||||
#include <qpdf/Types.h>
|
||||
|
||||
// This pipeline is reusable; i.e., it is safe to call write() after calling finish().
|
||||
class QPDF_DLL_CLASS Pl_Count: public Pipeline
|
||||
{
|
||||
public:
|
||||
QPDF_DLL
|
||||
Pl_Count(char const* identifier, Pipeline* next);
|
||||
QPDF_DLL
|
||||
~Pl_Count() override;
|
||||
QPDF_DLL
|
||||
void write(unsigned char const*, size_t) override;
|
||||
QPDF_DLL
|
||||
void finish() override;
|
||||
// Returns the number of bytes written
|
||||
QPDF_DLL
|
||||
qpdf_offset_t getCount() const;
|
||||
// Returns the last character written, or '\0' if no characters have been written (in which case
|
||||
// getCount() returns 0)
|
||||
QPDF_DLL
|
||||
unsigned char getLastChar() const;
|
||||
|
||||
private:
|
||||
class Members;
|
||||
|
||||
std::unique_ptr<Members> m;
|
||||
};
|
||||
|
||||
#endif // PL_COUNT_HH
|
||||
@@ -0,0 +1,101 @@
|
||||
// Copyright (c) 2005-2021 Jay Berkenbilt
|
||||
// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger
|
||||
//
|
||||
// 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 PL_DCT_HH
|
||||
#define PL_DCT_HH
|
||||
|
||||
#include <qpdf/Pipeline.hh>
|
||||
|
||||
#include <cstddef>
|
||||
#include <functional>
|
||||
|
||||
// jpeglib.h must be included after cstddef or else it messes up the definition of size_t.
|
||||
#include <jpeglib.h>
|
||||
|
||||
class QPDF_DLL_CLASS Pl_DCT: public Pipeline
|
||||
{
|
||||
public:
|
||||
// Constructor for decompressing image data
|
||||
QPDF_DLL
|
||||
Pl_DCT(char const* identifier, Pipeline* next);
|
||||
|
||||
// Limit the memory used by jpeglib when decompressing data.
|
||||
// NB This is a static option affecting all Pl_DCT instances.
|
||||
QPDF_DLL
|
||||
static void setMemoryLimit(long limit);
|
||||
|
||||
// Limit the number of scans used by jpeglib when decompressing progressive jpegs.
|
||||
// NB This is a static option affecting all Pl_DCT instances.
|
||||
QPDF_DLL
|
||||
static void setScanLimit(int limit);
|
||||
|
||||
// Treat corrupt data as a runtime error rather than attempting to decompress regardless. This
|
||||
// is the qpdf default behaviour. To attempt to decompress corrupt data set 'treat_as_error' to
|
||||
// false.
|
||||
// NB This is a static option affecting all Pl_DCT instances.
|
||||
QPDF_DLL
|
||||
static void setThrowOnCorruptData(bool treat_as_error);
|
||||
|
||||
class QPDF_DLL_CLASS CompressConfig
|
||||
{
|
||||
public:
|
||||
QPDF_DLL
|
||||
CompressConfig() = default;
|
||||
QPDF_DLL
|
||||
virtual ~CompressConfig() = default;
|
||||
virtual void apply(jpeg_compress_struct*) = 0;
|
||||
};
|
||||
|
||||
QPDF_DLL
|
||||
static std::unique_ptr<CompressConfig>
|
||||
make_compress_config(std::function<void(jpeg_compress_struct*)>);
|
||||
|
||||
// Constructor for compressing image data
|
||||
QPDF_DLL
|
||||
Pl_DCT(
|
||||
char const* identifier,
|
||||
Pipeline* next,
|
||||
JDIMENSION image_width,
|
||||
JDIMENSION image_height,
|
||||
int components,
|
||||
J_COLOR_SPACE color_space,
|
||||
CompressConfig* config_callback = nullptr);
|
||||
|
||||
QPDF_DLL
|
||||
~Pl_DCT() override;
|
||||
|
||||
QPDF_DLL
|
||||
void write(unsigned char const* data, size_t len) override;
|
||||
QPDF_DLL
|
||||
void finish() override;
|
||||
|
||||
private:
|
||||
QPDF_DLL_PRIVATE
|
||||
void compress(void* cinfo);
|
||||
QPDF_DLL_PRIVATE
|
||||
void decompress(void* cinfo);
|
||||
|
||||
enum action_e { a_compress, a_decompress };
|
||||
|
||||
class Members;
|
||||
|
||||
std::unique_ptr<Members> m;
|
||||
};
|
||||
|
||||
#endif // PL_DCT_HH
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
// Copyright (c) 2005-2021 Jay Berkenbilt
|
||||
// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger
|
||||
//
|
||||
// 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 PL_DISCARD_HH
|
||||
#define PL_DISCARD_HH
|
||||
|
||||
#include <qpdf/Pipeline.hh>
|
||||
|
||||
// This pipeline discards its output. It is an end-of-line pipeline (with no next).
|
||||
//
|
||||
// This pipeline is reusable; i.e., it is safe to call write() after calling finish().
|
||||
class QPDF_DLL_CLASS Pl_Discard: public Pipeline
|
||||
{
|
||||
public:
|
||||
QPDF_DLL
|
||||
Pl_Discard();
|
||||
QPDF_DLL
|
||||
~Pl_Discard() override;
|
||||
QPDF_DLL
|
||||
void write(unsigned char const*, size_t) override;
|
||||
QPDF_DLL
|
||||
void finish() override;
|
||||
};
|
||||
|
||||
#endif // PL_DISCARD_HH
|
||||
@@ -0,0 +1,126 @@
|
||||
// Copyright (c) 2005-2021 Jay Berkenbilt
|
||||
// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger
|
||||
//
|
||||
// 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 PL_FLATE_HH
|
||||
#define PL_FLATE_HH
|
||||
|
||||
#include <qpdf/Pipeline.hh>
|
||||
#include <qpdf/QPDFLogger.hh>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
class QPDF_DLL_CLASS Pl_Flate: public Pipeline
|
||||
{
|
||||
public:
|
||||
static unsigned int const def_bufsize = 65536;
|
||||
|
||||
enum action_e { a_inflate, a_deflate };
|
||||
|
||||
QPDF_DLL
|
||||
Pl_Flate(
|
||||
char const* identifier,
|
||||
Pipeline* next,
|
||||
action_e action,
|
||||
unsigned int out_bufsize = def_bufsize);
|
||||
QPDF_DLL
|
||||
~Pl_Flate() override;
|
||||
|
||||
// Limit the memory used.
|
||||
// NB This is a static option affecting all Pl_Flate instances.
|
||||
QPDF_DLL
|
||||
static unsigned long long memory_limit();
|
||||
QPDF_DLL
|
||||
static void memory_limit(unsigned long long limit);
|
||||
|
||||
QPDF_DLL
|
||||
void write(unsigned char const* data, size_t len) override;
|
||||
QPDF_DLL
|
||||
void finish() override;
|
||||
|
||||
// Globally set compression level from 1 (fastest, least
|
||||
// compression) to 9 (slowest, most compression). Use -1 to set
|
||||
// the default compression level. This is passed directly to zlib.
|
||||
// This method returns a pointer to the current Pl_Flate object so
|
||||
// you can create a pipeline with
|
||||
// Pl_Flate(...)->setCompressionLevel(...)
|
||||
QPDF_DLL
|
||||
static void setCompressionLevel(int);
|
||||
|
||||
QPDF_DLL
|
||||
void setWarnCallback(std::function<void(char const*, int)> callback);
|
||||
|
||||
// Returns true if qpdf was built with zopfli support.
|
||||
QPDF_DLL
|
||||
static bool zopfli_supported();
|
||||
|
||||
// Returns true if zopfli is enabled. Zopfli is enabled if QPDF_ZOPFLI is set to a value other
|
||||
// than "disabled" and zopfli support is compiled in.
|
||||
QPDF_DLL
|
||||
static bool zopfli_enabled();
|
||||
|
||||
// If zopfli is supported, returns true. Otherwise, check the QPDF_ZOPFLI
|
||||
// environment variable as follows:
|
||||
// - "disabled" or "silent": return true
|
||||
// - "force": qpdf_exit_error, throw an exception
|
||||
// - Any other value: issue a warning, and return false
|
||||
QPDF_DLL
|
||||
static bool zopfli_check_env(QPDFLogger* logger = nullptr);
|
||||
|
||||
private:
|
||||
QPDF_DLL_PRIVATE
|
||||
void handleData(unsigned char const* data, size_t len, int flush);
|
||||
QPDF_DLL_PRIVATE
|
||||
void checkError(char const* prefix, int error_code);
|
||||
QPDF_DLL_PRIVATE
|
||||
void warn(char const*, int error_code);
|
||||
QPDF_DLL_PRIVATE
|
||||
void finish_zopfli();
|
||||
|
||||
QPDF_DLL_PRIVATE
|
||||
static int compression_level;
|
||||
|
||||
class QPDF_DLL_PRIVATE Members
|
||||
{
|
||||
friend class Pl_Flate;
|
||||
|
||||
public:
|
||||
Members(size_t out_bufsize, action_e action);
|
||||
~Members();
|
||||
|
||||
private:
|
||||
Members(Members const&) = delete;
|
||||
|
||||
std::shared_ptr<unsigned char> outbuf;
|
||||
size_t out_bufsize;
|
||||
action_e action;
|
||||
bool initialized;
|
||||
void* zdata;
|
||||
unsigned long long written{0};
|
||||
std::function<void(char const*, int)> callback;
|
||||
std::unique_ptr<std::string> zopfli_buf;
|
||||
};
|
||||
|
||||
std::unique_ptr<Members> m;
|
||||
};
|
||||
|
||||
#endif // PL_FLATE_HH
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
// Copyright (c) 2005-2021 Jay Berkenbilt
|
||||
// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger
|
||||
//
|
||||
// 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 PL_FUNCTION_HH
|
||||
#define PL_FUNCTION_HH
|
||||
|
||||
#include <qpdf/Pipeline.hh>
|
||||
|
||||
#include <functional>
|
||||
|
||||
// This pipeline calls an arbitrary function with whatever data is passed to it. This pipeline can
|
||||
// be reused.
|
||||
//
|
||||
// For this pipeline, "next" may be null. If a next pointer is provided, this pipeline will also
|
||||
// pass the data through to it and will forward finish() to it.
|
||||
//
|
||||
// It is okay to not call finish() on this pipeline if it has no "next".
|
||||
//
|
||||
// It is okay to keep calling write() after a previous write throws an exception as long as the
|
||||
// delegated function allows it.
|
||||
class QPDF_DLL_CLASS Pl_Function: public Pipeline
|
||||
{
|
||||
public:
|
||||
typedef std::function<void(unsigned char const*, size_t)> writer_t;
|
||||
|
||||
// The supplied function is called every time write is called.
|
||||
QPDF_DLL
|
||||
Pl_Function(char const* identifier, Pipeline* next, writer_t fn);
|
||||
|
||||
// The supplied C-style function is called every time write is called. The udata option is
|
||||
// passed into the function with each call. If the function returns a non-zero value, a runtime
|
||||
// error is thrown.
|
||||
typedef int (*writer_c_t)(unsigned char const*, size_t, void*);
|
||||
QPDF_DLL
|
||||
Pl_Function(char const* identifier, Pipeline* next, writer_c_t fn, void* udata);
|
||||
typedef int (*writer_c_char_t)(char const*, size_t, void*);
|
||||
QPDF_DLL
|
||||
Pl_Function(char const* identifier, Pipeline* next, writer_c_char_t fn, void* udata);
|
||||
|
||||
QPDF_DLL
|
||||
~Pl_Function() override;
|
||||
|
||||
QPDF_DLL
|
||||
void write(unsigned char const* buf, size_t len) override;
|
||||
QPDF_DLL
|
||||
void finish() override;
|
||||
|
||||
private:
|
||||
class Members;
|
||||
|
||||
std::unique_ptr<Members> m;
|
||||
};
|
||||
|
||||
#endif // PL_FUNCTION_HH
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
// Copyright (c) 2005-2021 Jay Berkenbilt
|
||||
// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger
|
||||
//
|
||||
// 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 PL_OSTREAM_HH
|
||||
#define PL_OSTREAM_HH
|
||||
|
||||
#include <qpdf/Pipeline.hh>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
// End-of-line pipeline that simply writes its data to a stdio FILE* object.
|
||||
//
|
||||
// This pipeline is reusable.
|
||||
class QPDF_DLL_CLASS Pl_OStream: public Pipeline
|
||||
{
|
||||
public:
|
||||
// os is externally maintained; this class just writes to and flushes it. It does not close it.
|
||||
QPDF_DLL
|
||||
Pl_OStream(char const* identifier, std::ostream& os);
|
||||
QPDF_DLL
|
||||
~Pl_OStream() override;
|
||||
|
||||
QPDF_DLL
|
||||
void write(unsigned char const* buf, size_t len) override;
|
||||
QPDF_DLL
|
||||
void finish() override;
|
||||
|
||||
private:
|
||||
class Members;
|
||||
|
||||
std::unique_ptr<Members> m;
|
||||
};
|
||||
|
||||
#endif // PL_OSTREAM_HH
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
// Copyright (c) 2005-2021 Jay Berkenbilt
|
||||
// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger
|
||||
//
|
||||
// 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 PL_QPDFTOKENIZER_HH
|
||||
#define PL_QPDFTOKENIZER_HH
|
||||
|
||||
#include <qpdf/Pipeline.hh>
|
||||
|
||||
#include <qpdf/Pl_Buffer.hh>
|
||||
#include <qpdf/QPDFObjectHandle.hh>
|
||||
#include <qpdf/QPDFTokenizer.hh>
|
||||
|
||||
#include <memory>
|
||||
|
||||
// Tokenize the incoming text using QPDFTokenizer and pass the tokens in turn to a
|
||||
// QPDFObjectHandle::TokenFilter object. All bytes of incoming content will be included in exactly
|
||||
// one token and passed downstream.
|
||||
//
|
||||
// This is a very low-level interface for working with token filters. Most code will want to use
|
||||
// QPDFObjectHandle::filterPageContents or QPDFObjectHandle::addTokenFilter. See QPDFObjectHandle.hh
|
||||
// for details.
|
||||
class QPDF_DLL_CLASS Pl_QPDFTokenizer: public Pipeline
|
||||
{
|
||||
public:
|
||||
// Whatever pipeline is provided as "next" will be set as the pipeline that the token filter
|
||||
// writes to. If next is not provided, any output written by the filter will be discarded.
|
||||
QPDF_DLL
|
||||
Pl_QPDFTokenizer(
|
||||
char const* identifier, QPDFObjectHandle::TokenFilter* filter, Pipeline* next = nullptr);
|
||||
QPDF_DLL
|
||||
~Pl_QPDFTokenizer() override;
|
||||
QPDF_DLL
|
||||
void write(unsigned char const* buf, size_t len) override;
|
||||
QPDF_DLL
|
||||
void finish() override;
|
||||
|
||||
private:
|
||||
class Members;
|
||||
|
||||
std::unique_ptr<Members> m;
|
||||
};
|
||||
|
||||
#endif // PL_QPDFTOKENIZER_HH
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
// Copyright (c) 2005-2021 Jay Berkenbilt
|
||||
// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger
|
||||
//
|
||||
// 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 PL_RUNLENGTH_HH
|
||||
#define PL_RUNLENGTH_HH
|
||||
|
||||
#include <qpdf/Pipeline.hh>
|
||||
|
||||
class QPDF_DLL_CLASS Pl_RunLength: public Pipeline
|
||||
{
|
||||
public:
|
||||
enum action_e { a_encode, a_decode };
|
||||
|
||||
QPDF_DLL
|
||||
Pl_RunLength(char const* identifier, Pipeline* next, action_e action);
|
||||
QPDF_DLL
|
||||
~Pl_RunLength() override;
|
||||
|
||||
// Limit the memory used.
|
||||
// NB This is a static option affecting all Pl_RunLength instances.
|
||||
QPDF_DLL
|
||||
static void setMemoryLimit(unsigned long long limit);
|
||||
|
||||
QPDF_DLL
|
||||
void write(unsigned char const* data, size_t len) override;
|
||||
QPDF_DLL
|
||||
void finish() override;
|
||||
|
||||
private:
|
||||
QPDF_DLL_PRIVATE
|
||||
void encode(unsigned char const* data, size_t len);
|
||||
QPDF_DLL_PRIVATE
|
||||
void decode(unsigned char const* data, size_t len);
|
||||
QPDF_DLL_PRIVATE
|
||||
void flush_encode();
|
||||
|
||||
enum state_e { st_top, st_copying, st_run };
|
||||
|
||||
class Members;
|
||||
|
||||
std::unique_ptr<Members> m;
|
||||
};
|
||||
|
||||
#endif // PL_RUNLENGTH_HH
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
// Copyright (c) 2005-2021 Jay Berkenbilt
|
||||
// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger
|
||||
//
|
||||
// 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.
|
||||
|
||||
// End-of-line pipeline that simply writes its data to a stdio FILE* object.
|
||||
|
||||
#ifndef PL_STDIOFILE_HH
|
||||
#define PL_STDIOFILE_HH
|
||||
|
||||
#include <qpdf/Pipeline.hh>
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
//
|
||||
// This pipeline is reusable.
|
||||
//
|
||||
class QPDF_DLL_CLASS Pl_StdioFile: public Pipeline
|
||||
{
|
||||
public:
|
||||
// f is externally maintained; this class just writes to and flushes it. It does not close it.
|
||||
QPDF_DLL
|
||||
Pl_StdioFile(char const* identifier, FILE* f);
|
||||
QPDF_DLL
|
||||
~Pl_StdioFile() override;
|
||||
|
||||
QPDF_DLL
|
||||
void write(unsigned char const* buf, size_t len) override;
|
||||
QPDF_DLL
|
||||
void finish() override;
|
||||
|
||||
private:
|
||||
class Members;
|
||||
std::unique_ptr<Members> m;
|
||||
};
|
||||
|
||||
#endif // PL_STDIOFILE_HH
|
||||
@@ -0,0 +1,57 @@
|
||||
// Copyright (c) 2005-2021 Jay Berkenbilt
|
||||
// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger
|
||||
//
|
||||
// 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 PL_STRING_HH
|
||||
#define PL_STRING_HH
|
||||
|
||||
#include <qpdf/Pipeline.hh>
|
||||
|
||||
#include <string>
|
||||
|
||||
// This pipeline accumulates the data passed to it into a std::string, a reference to which is
|
||||
// passed in at construction. Each subsequent use of this pipeline appends to the data accumulated
|
||||
// so far.
|
||||
//
|
||||
// For this pipeline, "next" may be null. If a next pointer is provided, this pipeline will also
|
||||
// pass the data through to it and will forward finish() to it.
|
||||
//
|
||||
// It is okay to not call finish() on this pipeline if it has no "next". This makes it easy to stick
|
||||
// this in front of another pipeline to capture data that is written to the other pipeline without
|
||||
// interfering with when finish is called on the other pipeline and without having to put a
|
||||
// Pl_Concatenate after it.
|
||||
class QPDF_DLL_CLASS Pl_String: public Pipeline
|
||||
{
|
||||
public:
|
||||
QPDF_DLL
|
||||
Pl_String(char const* identifier, Pipeline* next, std::string& s);
|
||||
QPDF_DLL
|
||||
~Pl_String() override;
|
||||
|
||||
QPDF_DLL
|
||||
void write(unsigned char const* buf, size_t len) override;
|
||||
QPDF_DLL
|
||||
void finish() override;
|
||||
|
||||
private:
|
||||
class Members;
|
||||
|
||||
std::unique_ptr<Members> m;
|
||||
};
|
||||
|
||||
#endif // PL_STRING_HH
|
||||
+245
@@ -0,0 +1,245 @@
|
||||
// Copyright (c) 2005-2021 Jay Berkenbilt
|
||||
// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger
|
||||
//
|
||||
// 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 POINTERHOLDER_HH
|
||||
#define POINTERHOLDER_HH
|
||||
|
||||
#define POINTERHOLDER_IS_SHARED_POINTER
|
||||
|
||||
#ifndef POINTERHOLDER_TRANSITION
|
||||
// 0 = no deprecation warnings, backward-compatible API
|
||||
// 1 = make PointerHolder<T>(T*) explicit
|
||||
// 2 = warn for use of getPointer() and getRefcount()
|
||||
// 3 = warn for all use of PointerHolder
|
||||
// 4 = don't define PointerHolder at all
|
||||
# define POINTERHOLDER_TRANSITION 4
|
||||
#endif // !defined(POINTERHOLDER_TRANSITION)
|
||||
|
||||
#if POINTERHOLDER_TRANSITION < 4
|
||||
|
||||
// *** WHAT IS HAPPENING ***
|
||||
|
||||
// In qpdf 11, PointerHolder was replaced with std::shared_ptr
|
||||
// wherever it appeared in the qpdf API. The PointerHolder object is
|
||||
// now derived from std::shared_ptr to provide a backward-compatible
|
||||
// interface and is mutually assignable with std::shared_ptr. Code
|
||||
// that uses containers of PointerHolder will require adjustment.
|
||||
|
||||
// In qpdf 11, a backward-compatible PointerHolder was provided with a
|
||||
// warning if POINTERHOLDER_TRANSITION was not defined. Starting in
|
||||
// qpdf 12, PointerHolder is absent if POINTERHOLDER_TRANSITION is not
|
||||
// defined. In a future version of qpdf, PointerHolder will be removed
|
||||
// outright if it becomes inconvenient to keep it around.
|
||||
|
||||
// *** HOW TO TRANSITION ***
|
||||
|
||||
// The symbol POINTERHOLDER_TRANSITION can be defined to help you
|
||||
// transition your code away from PointerHolder. You can define it
|
||||
// before including any qpdf header files or including its definition
|
||||
// in your build configuration. If not defined, it automatically gets
|
||||
// defined to 4, which excludes PointerHolder entirely.
|
||||
|
||||
// If you want to work gradually to transition your code away from
|
||||
// PointerHolder, you can define POINTERHOLDER_TRANSITION and fix the
|
||||
// code so it compiles without warnings and works correctly. If you
|
||||
// want to be able to continue to support old qpdf versions at the
|
||||
// same time, you can write code like this:
|
||||
|
||||
// #ifndef POINTERHOLDER_IS_SHARED_POINTER
|
||||
// ... use PointerHolder as before 10.6
|
||||
// #else
|
||||
// ... use PointerHolder or shared_ptr as needed
|
||||
// #endif
|
||||
|
||||
// Each level of POINTERHOLDER_TRANSITION exposes differences between
|
||||
// PointerHolder and std::shared_ptr. The easiest way to transition is
|
||||
// to increase POINTERHOLDER_TRANSITION in steps of 1 so that you can
|
||||
// test and handle changes incrementally.
|
||||
|
||||
// POINTERHOLDER_TRANSITION = 1
|
||||
//
|
||||
// PointerHolder<T> has an implicit constructor that takes a T*, so
|
||||
// you can replace a PointerHolder<T>'s pointer by directly assigning
|
||||
// a T* to it or pass a T* to a function that expects a
|
||||
// PointerHolder<T>. std::shared_ptr does not have this (risky)
|
||||
// behavior. When POINTERHOLDER_TRANSITION = 1, PointerHolder<T>'s T*
|
||||
// constructor is declared explicit. For compatibility with
|
||||
// std::shared_ptr, you can still assign nullptr to a PointerHolder.
|
||||
// Constructing all your PointerHolder<T> instances explicitly is
|
||||
// backward compatible, so you can make this change without
|
||||
// conditional compilation and still use the changes with older qpdf
|
||||
// versions.
|
||||
//
|
||||
// Also defined is a make_pointer_holder method that acts like
|
||||
// std::make_shared. You can use this as well, but it is not
|
||||
// compatible with qpdf prior to 10.6 and not necessary with qpdf
|
||||
// newer than 10.6.3. Like std::make_shared<T>, make_pointer_holder<T>
|
||||
// can only be used when the constructor implied by its arguments is
|
||||
// public. If you previously used this, you can replace it width
|
||||
// std::make_shared now.
|
||||
|
||||
// POINTERHOLDER_TRANSITION = 2
|
||||
//
|
||||
// std::shared_ptr has get() and use_count(). PointerHolder has
|
||||
// getPointer() and getRefcount(). In 10.6.0, get() and use_count()
|
||||
// were added as well. When POINTERHOLDER_TRANSITION = 2, getPointer()
|
||||
// and getRefcount() are deprecated. Fix deprecation warnings by
|
||||
// replacing with get() and use_count(). This breaks compatibility
|
||||
// with qpdf older than 10.6. Search for CONST BEHAVIOR for an
|
||||
// additional note.
|
||||
//
|
||||
// Once your code is clean at POINTERHOLDER_TRANSITION = 2, the only
|
||||
// remaining issues that prevent simple replacement of PointerHolder
|
||||
// with std::shared_ptr are shared arrays and containers, and neither
|
||||
// of these are used in the qpdf API.
|
||||
|
||||
// POINTERHOLDER_TRANSITION = 3
|
||||
//
|
||||
// Warn for all use of PointerHolder<T>. This helps you remove all use
|
||||
// of PointerHolder from your code and use std::shared_ptr instead.
|
||||
// You will also have to transition any containers of PointerHolder in
|
||||
// your code.
|
||||
|
||||
// POINTERHOLDER_TRANSITION = 4
|
||||
//
|
||||
// Suppress definition of the PointerHolder<T> type entirely. This is
|
||||
// the default behavior starting with qpdf 12.
|
||||
|
||||
// CONST BEHAVIOR
|
||||
|
||||
// PointerHolder<T> has had a long-standing bug in its const behavior.
|
||||
// const PointerHolder<T>'s getPointer() method returns a T const*.
|
||||
// This is incorrect and is not how regular pointers or standard
|
||||
// library smart pointers behave. Making a PointerHolder<T> const
|
||||
// should prevent reassignment of its pointer but not affect the thing
|
||||
// it points to. For that, use PointerHolder<T const>. The new get()
|
||||
// method behaves correctly in this respect and is therefore slightly
|
||||
// different from getPointer(). This shouldn't break any correctly
|
||||
// written code. If you are relying on the incorrect behavior, use
|
||||
// PointerHolder<T const> instead.
|
||||
|
||||
# include <cstddef>
|
||||
# include <memory>
|
||||
|
||||
template <class T>
|
||||
class PointerHolder: public std::shared_ptr<T>
|
||||
{
|
||||
public:
|
||||
# if POINTERHOLDER_TRANSITION >= 3
|
||||
[[deprecated("use std::shared_ptr<T> instead")]]
|
||||
# endif // POINTERHOLDER_TRANSITION >= 3
|
||||
PointerHolder(std::shared_ptr<T> other) :
|
||||
std::shared_ptr<T>(other)
|
||||
{
|
||||
}
|
||||
# if POINTERHOLDER_TRANSITION >= 3
|
||||
[[deprecated("use std::shared_ptr<T> instead")]]
|
||||
# if POINTERHOLDER_TRANSITION >= 1
|
||||
explicit
|
||||
# endif // POINTERHOLDER_TRANSITION >= 1
|
||||
# endif // POINTERHOLDER_TRANSITION >= 3
|
||||
PointerHolder(T* pointer = 0) :
|
||||
std::shared_ptr<T>(pointer)
|
||||
{
|
||||
}
|
||||
// Create a shared pointer to an array
|
||||
# if POINTERHOLDER_TRANSITION >= 3
|
||||
[[deprecated("use std::shared_ptr<T> instead")]]
|
||||
# endif // POINTERHOLDER_TRANSITION >= 3
|
||||
PointerHolder(bool, T* pointer) :
|
||||
std::shared_ptr<T>(pointer, std::default_delete<T[]>())
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~PointerHolder() = default;
|
||||
|
||||
# if POINTERHOLDER_TRANSITION >= 2
|
||||
[[deprecated("use PointerHolder<T>::get() instead of getPointer()")]]
|
||||
# endif // POINTERHOLDER_TRANSITION >= 2
|
||||
T*
|
||||
getPointer()
|
||||
{
|
||||
return this->get();
|
||||
}
|
||||
# if POINTERHOLDER_TRANSITION >= 2
|
||||
[[deprecated("use PointerHolder<T>::get() instead of getPointer()")]]
|
||||
# endif // POINTERHOLDER_TRANSITION >= 2
|
||||
T const*
|
||||
getPointer() const
|
||||
{
|
||||
return this->get();
|
||||
}
|
||||
|
||||
# if POINTERHOLDER_TRANSITION >= 2
|
||||
[[deprecated("use PointerHolder<T>::get() instead of getPointer()")]]
|
||||
# endif // POINTERHOLDER_TRANSITION >= 2
|
||||
int
|
||||
getRefcount() const
|
||||
{
|
||||
return static_cast<int>(this->use_count());
|
||||
}
|
||||
|
||||
PointerHolder&
|
||||
operator=(decltype(nullptr))
|
||||
{
|
||||
std::shared_ptr<T>::operator=(nullptr);
|
||||
return *this;
|
||||
}
|
||||
T const&
|
||||
operator*() const
|
||||
{
|
||||
return *(this->get());
|
||||
}
|
||||
T&
|
||||
operator*()
|
||||
{
|
||||
return *(this->get());
|
||||
}
|
||||
|
||||
T const*
|
||||
operator->() const
|
||||
{
|
||||
return this->get();
|
||||
}
|
||||
T*
|
||||
operator->()
|
||||
{
|
||||
return this->get();
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename... _Args>
|
||||
inline PointerHolder<T>
|
||||
make_pointer_holder(_Args&&... __args)
|
||||
{
|
||||
return PointerHolder<T>(new T(__args...));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
PointerHolder<T>
|
||||
make_array_pointer_holder(size_t n)
|
||||
{
|
||||
return PointerHolder<T>(true, new T[n]);
|
||||
}
|
||||
|
||||
#endif // POINTERHOLDER_TRANSITION < 4
|
||||
#endif // POINTERHOLDER_HH
|
||||
@@ -0,0 +1,310 @@
|
||||
// Copyright (c) 2005-2021 Jay Berkenbilt
|
||||
// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger
|
||||
//
|
||||
// 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 QINTC_HH
|
||||
#define QINTC_HH
|
||||
|
||||
#include <qpdf/DLL.h>
|
||||
#include <qpdf/Types.h>
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
#include <locale>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <type_traits>
|
||||
|
||||
// This namespace provides safe integer conversion that detects
|
||||
// overflows. It uses short, cryptic names for brevity.
|
||||
|
||||
namespace QIntC // QIntC = qpdf Integer Conversion
|
||||
{
|
||||
// to_u is here for backward-compatibility from before we required
|
||||
// C++-11.
|
||||
template <typename T>
|
||||
class to_u
|
||||
{
|
||||
public:
|
||||
typedef typename std::make_unsigned<T>::type type;
|
||||
};
|
||||
|
||||
// Basic IntConverter class, which converts an integer from the
|
||||
// From class to one of the To class if it can be done safely and
|
||||
// throws a range_error otherwise. This class is specialized for
|
||||
// each permutation of signed/unsigned for the From and To
|
||||
// classes.
|
||||
template <
|
||||
typename From,
|
||||
typename To,
|
||||
bool From_signed = std::numeric_limits<From>::is_signed,
|
||||
bool To_signed = std::numeric_limits<To>::is_signed>
|
||||
class IntConverter
|
||||
{
|
||||
};
|
||||
|
||||
template <typename From, typename To>
|
||||
class IntConverter<From, To, false, false>
|
||||
{
|
||||
public:
|
||||
inline static To
|
||||
convert(From const& i)
|
||||
{
|
||||
// From and To are both unsigned.
|
||||
if (i > std::numeric_limits<To>::max()) {
|
||||
error(i);
|
||||
}
|
||||
return static_cast<To>(i);
|
||||
}
|
||||
|
||||
static void
|
||||
error(From i)
|
||||
{
|
||||
std::ostringstream msg;
|
||||
msg.imbue(std::locale::classic());
|
||||
msg << "integer out of range converting " << i << " from a " << sizeof(From)
|
||||
<< "-byte unsigned type to a " << sizeof(To) << "-byte unsigned type";
|
||||
throw std::range_error(msg.str());
|
||||
}
|
||||
};
|
||||
|
||||
template <typename From, typename To>
|
||||
class IntConverter<From, To, true, true>
|
||||
{
|
||||
public:
|
||||
inline static To
|
||||
convert(From const& i)
|
||||
{
|
||||
// From and To are both signed.
|
||||
if ((i < std::numeric_limits<To>::min()) || (i > std::numeric_limits<To>::max())) {
|
||||
error(i);
|
||||
}
|
||||
return static_cast<To>(i);
|
||||
}
|
||||
|
||||
static void
|
||||
error(From i)
|
||||
{
|
||||
std::ostringstream msg;
|
||||
msg.imbue(std::locale::classic());
|
||||
msg << "integer out of range converting " << i << " from a " << sizeof(From)
|
||||
<< "-byte signed type to a " << sizeof(To) << "-byte signed type";
|
||||
throw std::range_error(msg.str());
|
||||
}
|
||||
};
|
||||
|
||||
template <typename From, typename To>
|
||||
class IntConverter<From, To, true, false>
|
||||
{
|
||||
public:
|
||||
inline static To
|
||||
convert(From const& i)
|
||||
{
|
||||
// From is signed, and To is unsigned. If i > 0, it's safe to
|
||||
// convert it to the corresponding unsigned type and to
|
||||
// compare with To's max.
|
||||
auto ii = static_cast<typename to_u<From>::type>(i);
|
||||
if ((i < 0) || (ii > std::numeric_limits<To>::max())) {
|
||||
error(i);
|
||||
}
|
||||
return static_cast<To>(i);
|
||||
}
|
||||
|
||||
static void
|
||||
error(From i)
|
||||
{
|
||||
std::ostringstream msg;
|
||||
msg.imbue(std::locale::classic());
|
||||
msg << "integer out of range converting " << i << " from a " << sizeof(From)
|
||||
<< "-byte signed type to a " << sizeof(To) << "-byte unsigned type";
|
||||
throw std::range_error(msg.str());
|
||||
}
|
||||
};
|
||||
|
||||
template <typename From, typename To>
|
||||
class IntConverter<From, To, false, true>
|
||||
{
|
||||
public:
|
||||
inline static To
|
||||
convert(From const& i)
|
||||
{
|
||||
// From is unsigned, and to is signed. Convert To's max to the
|
||||
// unsigned version of To and compare i against that.
|
||||
auto maxval = static_cast<typename to_u<To>::type>(std::numeric_limits<To>::max());
|
||||
if (i > maxval) {
|
||||
error(i);
|
||||
}
|
||||
return static_cast<To>(i);
|
||||
}
|
||||
|
||||
static void
|
||||
error(From i)
|
||||
{
|
||||
std::ostringstream msg;
|
||||
msg.imbue(std::locale::classic());
|
||||
msg << "integer out of range converting " << i << " from a " << sizeof(From)
|
||||
<< "-byte unsigned type to a " << sizeof(To) << "-byte signed type";
|
||||
throw std::range_error(msg.str());
|
||||
}
|
||||
};
|
||||
|
||||
// Specific converters. The return type of each function must match
|
||||
// the second template parameter to IntConverter.
|
||||
template <typename T>
|
||||
inline char
|
||||
to_char(T const& i)
|
||||
{
|
||||
return IntConverter<T, char>::convert(i);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline unsigned char
|
||||
to_uchar(T const& i)
|
||||
{
|
||||
return IntConverter<T, unsigned char>::convert(i);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline short
|
||||
to_short(T const& i)
|
||||
{
|
||||
return IntConverter<T, short>::convert(i);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline unsigned short
|
||||
to_ushort(T const& i)
|
||||
{
|
||||
return IntConverter<T, unsigned short>::convert(i);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline int
|
||||
to_int(T const& i)
|
||||
{
|
||||
return IntConverter<T, int>::convert(i);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline unsigned int
|
||||
to_uint(T const& i)
|
||||
{
|
||||
return IntConverter<T, unsigned int>::convert(i);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline size_t
|
||||
to_size(T const& i)
|
||||
{
|
||||
return IntConverter<T, size_t>::convert(i);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline qpdf_offset_t
|
||||
to_offset(T const& i)
|
||||
{
|
||||
return IntConverter<T, qpdf_offset_t>::convert(i);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline long
|
||||
to_long(T const& i)
|
||||
{
|
||||
return IntConverter<T, long>::convert(i);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline unsigned long
|
||||
to_ulong(T const& i)
|
||||
{
|
||||
return IntConverter<T, unsigned long>::convert(i);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline long long
|
||||
to_longlong(T const& i)
|
||||
{
|
||||
return IntConverter<T, long long>::convert(i);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline unsigned long long
|
||||
to_ulonglong(T const& i)
|
||||
{
|
||||
return IntConverter<T, unsigned long long>::convert(i);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void
|
||||
range_check_error(T const& cur, T const& delta)
|
||||
{
|
||||
if ((delta > 0) && ((std::numeric_limits<T>::max() - cur) < delta)) {
|
||||
std::ostringstream msg;
|
||||
msg.imbue(std::locale::classic());
|
||||
msg << "adding " << delta << " to " << cur << " would cause an integer overflow";
|
||||
throw std::range_error(msg.str());
|
||||
} else if ((delta < 0) && ((std::numeric_limits<T>::min() - cur) > delta)) {
|
||||
std::ostringstream msg;
|
||||
msg.imbue(std::locale::classic());
|
||||
msg << "adding " << delta << " to " << cur << " would cause an integer underflow";
|
||||
throw std::range_error(msg.str());
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void
|
||||
range_check(T const& cur, T const& delta)
|
||||
{
|
||||
if ((delta > 0) != (cur > 0)) {
|
||||
return;
|
||||
}
|
||||
QIntC::range_check_error<T>(cur, delta);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void
|
||||
range_check_subtract_error(T const& cur, T const& delta)
|
||||
{
|
||||
if ((delta > 0) && ((std::numeric_limits<T>::min() + delta) > cur)) {
|
||||
std::ostringstream msg;
|
||||
msg.imbue(std::locale::classic());
|
||||
msg << "subtracting " << delta << " from " << cur
|
||||
<< " would cause an integer underflow";
|
||||
throw std::range_error(msg.str());
|
||||
} else if ((delta < 0) && ((std::numeric_limits<T>::max() + delta) < cur)) {
|
||||
std::ostringstream msg;
|
||||
msg.imbue(std::locale::classic());
|
||||
msg << "subtracting " << delta << " from " << cur << " would cause an integer overflow";
|
||||
throw std::range_error(msg.str());
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void
|
||||
range_check_subtract(T const& cur, T const& delta)
|
||||
{
|
||||
if ((delta >= 0) == (cur >= 0)) {
|
||||
return;
|
||||
}
|
||||
QIntC::range_check_subtract_error<T>(cur, delta);
|
||||
}
|
||||
}; // namespace QIntC
|
||||
|
||||
#endif // QINTC_HH
|
||||
@@ -0,0 +1,804 @@
|
||||
// Copyright (c) 2005-2021 Jay Berkenbilt
|
||||
// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger
|
||||
//
|
||||
// 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_HH
|
||||
#define QPDF_HH
|
||||
|
||||
#include <qpdf/DLL.h>
|
||||
#include <qpdf/Types.h>
|
||||
|
||||
#include <bitset>
|
||||
#include <cstdio>
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
#include <qpdf/Buffer.hh>
|
||||
#include <qpdf/InputSource.hh>
|
||||
#include <qpdf/PDFVersion.hh>
|
||||
#include <qpdf/QPDFExc.hh>
|
||||
#include <qpdf/QPDFObjGen.hh>
|
||||
#include <qpdf/QPDFObjectHandle.hh>
|
||||
#include <qpdf/QPDFStreamFilter.hh>
|
||||
#include <qpdf/QPDFTokenizer.hh>
|
||||
#include <qpdf/QPDFWriter.hh>
|
||||
#include <qpdf/QPDFXRefEntry.hh>
|
||||
|
||||
class QPDFLogger;
|
||||
|
||||
class QPDF
|
||||
{
|
||||
public:
|
||||
// Get the current version of the QPDF software. See also qpdf/DLL.h
|
||||
QPDF_DLL
|
||||
static std::string const& QPDFVersion();
|
||||
|
||||
QPDF_DLL
|
||||
QPDF();
|
||||
QPDF_DLL
|
||||
~QPDF();
|
||||
|
||||
QPDF_DLL
|
||||
static std::shared_ptr<QPDF> create();
|
||||
|
||||
// Associate a file with a QPDF object and do initial parsing of the file. PDF objects are not
|
||||
// read until they are needed. A QPDF object may be associated with only one file in its
|
||||
// lifetime. This method must be called before any methods that potentially ask for information
|
||||
// about the PDF file are called. Prior to calling this, the only methods that are allowed are
|
||||
// those that set parameters. If the input file is not encrypted, either a null password or an
|
||||
// empty password can be used. If the file is encrypted, either the user password or the owner
|
||||
// password may be supplied. The method setPasswordIsHexKey may be called prior to calling this
|
||||
// method or any of the other process methods to force the password to be interpreted as a raw
|
||||
// encryption key. See comments on setPasswordIsHexKey for more information.
|
||||
QPDF_DLL
|
||||
void processFile(char const* filename, char const* password = nullptr);
|
||||
|
||||
// Parse a PDF from a stdio FILE*. The FILE must be open in binary mode and must be seekable.
|
||||
// It may be open read only. This works exactly like processFile except that the PDF file is
|
||||
// read from an already opened FILE*. If close_file is true, the file will be closed at the
|
||||
// end. Otherwise, the caller is responsible for closing the file.
|
||||
QPDF_DLL
|
||||
void processFile(
|
||||
char const* description, FILE* file, bool close_file, char const* password = nullptr);
|
||||
|
||||
// Parse a PDF file loaded into a memory buffer. This works exactly like processFile except
|
||||
// that the PDF file is in memory instead of on disk. The description appears in any warning or
|
||||
// error message in place of the file name. The buffer is owned by the caller and must remain
|
||||
// valid for the lifetime of the QPDF object.
|
||||
QPDF_DLL
|
||||
void processMemoryFile(
|
||||
char const* description, char const* buf, size_t length, char const* password = nullptr);
|
||||
|
||||
// Parse a PDF file loaded from a custom InputSource. If you have your own method of retrieving
|
||||
// a PDF file, you can subclass InputSource and use this method.
|
||||
QPDF_DLL
|
||||
void processInputSource(std::shared_ptr<InputSource>, char const* password = nullptr);
|
||||
|
||||
// Create a PDF from an input source that contains JSON as written by writeJSON (or qpdf
|
||||
// --json-output, version 2 or higher). The JSON must be a complete representation of a PDF. See
|
||||
// "qpdf JSON" in the manual for details. The input JSON may be arbitrarily large. QPDF does not
|
||||
// load stream data into memory for more than one stream at a time, even if the stream data is
|
||||
// specified inline.
|
||||
QPDF_DLL
|
||||
void createFromJSON(std::string const& json_file);
|
||||
QPDF_DLL
|
||||
void createFromJSON(std::shared_ptr<InputSource>);
|
||||
|
||||
// Update a PDF from an input source that contains JSON in the same format as is written by
|
||||
// writeJSON (or qpdf --json-output, version 2 or higher). Objects in the PDF and not in the
|
||||
// JSON are not modified. See "qpdf JSON" in the manual for details. As with createFromJSON, the
|
||||
// input JSON may be arbitrarily large.
|
||||
QPDF_DLL
|
||||
void updateFromJSON(std::string const& json_file);
|
||||
QPDF_DLL
|
||||
void updateFromJSON(std::shared_ptr<InputSource>);
|
||||
|
||||
// Write qpdf JSON format to the pipeline "p". The only supported version is 2. The finish()
|
||||
// method is not called on the pipeline.
|
||||
//
|
||||
// The decode_level parameter controls which streams are uncompressed in the JSON. Use
|
||||
// qpdf_dl_none to preserve all stream data exactly as it appears in the input. The possible
|
||||
// values for json_stream_data can be found in qpdf/Constants.h and correspond to the
|
||||
// --json-stream-data command-line argument. If json_stream_data is qpdf_sj_file, file_prefix
|
||||
// must be specified. Each stream will be written to a file whose path is constructed by
|
||||
// appending "-nnn" to file_prefix, where "nnn" is the object number (not zero-filled). If
|
||||
// wanted_objects is empty, write all objects. Otherwise, write only objects whose keys are in
|
||||
// wanted_objects. Keys may be either "trailer" or of the form "obj:n n R". Invalid keys are
|
||||
// ignored. This corresponds to the --json-object command-line argument.
|
||||
//
|
||||
// QPDF is efficient with regard to memory when writing, allowing you to write arbitrarily large
|
||||
// PDF files to a pipeline. You can use a pipeline like Pl_Buffer or Pl_String to capture the
|
||||
// JSON output in memory, but do so with caution as this will allocate enough memory to hold the
|
||||
// entire PDF file.
|
||||
QPDF_DLL
|
||||
void writeJSON(
|
||||
int version,
|
||||
Pipeline* p,
|
||||
qpdf_stream_decode_level_e decode_level,
|
||||
qpdf_json_stream_data_e json_stream_data,
|
||||
std::string const& file_prefix,
|
||||
std::set<std::string> wanted_objects);
|
||||
|
||||
// This version of writeJSON enables writing only the "qpdf" key of an in-progress dictionary.
|
||||
// If the value of "complete" is true, a complete JSON object containing only the "qpdf" key is
|
||||
// written to the pipeline. If the value of "complete" is false, the "qpdf" key and its value
|
||||
// are written to the pipeline assuming that a dictionary is already open. The parameter
|
||||
// first_key indicates whether this is the first key in an in-progress dictionary. It will be
|
||||
// set to false by writeJSON. The "qpdf" key and value are written as if at depth 1 in a
|
||||
// prettified JSON output. Remaining arguments are the same as the above version.
|
||||
QPDF_DLL
|
||||
void writeJSON(
|
||||
int version,
|
||||
Pipeline* p,
|
||||
bool complete,
|
||||
bool& first_key,
|
||||
qpdf_stream_decode_level_e decode_level,
|
||||
qpdf_json_stream_data_e json_stream_data,
|
||||
std::string const& file_prefix,
|
||||
std::set<std::string> wanted_objects);
|
||||
|
||||
// Close or otherwise release the input source. Once this has been called, no other methods of
|
||||
// qpdf can be called safely except for getWarnings and anyWarnings(). After this has been
|
||||
// called, it is safe to perform operations on the input file such as deleting or renaming it.
|
||||
QPDF_DLL
|
||||
void closeInputSource();
|
||||
|
||||
// For certain forensic or investigatory purposes, it may sometimes be useful to specify the
|
||||
// encryption key directly, even though regular PDF applications do not provide a way to do
|
||||
// this. Calling setPasswordIsHexKey(true) before calling any of the process methods will bypass
|
||||
// the normal encryption key computation or recovery mechanisms and interpret the bytes in the
|
||||
// password as a hex-encoded encryption key. Note that we hex-encode the key because it may
|
||||
// contain null bytes and therefore can't be represented in a char const*.
|
||||
QPDF_DLL
|
||||
void setPasswordIsHexKey(bool);
|
||||
|
||||
// Create a QPDF object for an empty PDF. This PDF has no pages or objects other than a minimal
|
||||
// trailer, a document catalog, and a /Pages tree containing zero pages. Pages and other
|
||||
// objects can be added to the file in the normal way, and the trailer and document catalog can
|
||||
// be mutated. Calling this method is equivalent to calling processFile on an equivalent PDF
|
||||
// file. See the pdf-create.cc example for a demonstration of how to use this method to create
|
||||
// a PDF file from scratch.
|
||||
QPDF_DLL
|
||||
void emptyPDF();
|
||||
|
||||
// From 10.1: register a new filter implementation for a specific stream filter. You can add
|
||||
// your own implementations for new filter types or override existing ones provided by the
|
||||
// library. Registered stream filters are used for decoding only as you can override encoding
|
||||
// with stream data providers. For example, you could use this method to add support for one of
|
||||
// the other filter types by using additional third-party libraries that qpdf does not presently
|
||||
// use. The standard filters are implemented using QPDFStreamFilter classes.
|
||||
QPDF_DLL
|
||||
static void registerStreamFilter(
|
||||
std::string const& filter_name, std::function<std::shared_ptr<QPDFStreamFilter>()> factory);
|
||||
|
||||
// Parameter settings
|
||||
|
||||
// To capture or redirect output, configure the logger returned by getLogger(). By default, all
|
||||
// QPDF and QPDFJob objects share the global logger. If you need a private logger for some
|
||||
// reason, pass a new one to setLogger(). See comments in QPDFLogger.hh for details on
|
||||
// configuring the logger.
|
||||
//
|
||||
// Note that no normal QPDF operations generate output to standard output, so for applications
|
||||
// that just wish to avoid creating output for warnings and don't call any check functions,
|
||||
// calling setSuppressWarnings(true) is sufficient.
|
||||
QPDF_DLL
|
||||
std::shared_ptr<QPDFLogger> getLogger();
|
||||
QPDF_DLL
|
||||
void setLogger(std::shared_ptr<QPDFLogger>);
|
||||
|
||||
// This deprecated method is the old way to capture output, but it didn't capture all output.
|
||||
// See comments above for getLogger and setLogger. This will be removed in QPDF 12. For now, it
|
||||
// configures a private logger, separating this object from the default logger, and calls
|
||||
// setOutputStreams on that logger. See QPDFLogger.hh for additional details.
|
||||
[[deprecated("configure logger from getLogger() or call setLogger()")]] QPDF_DLL void
|
||||
setOutputStreams(std::ostream* out_stream, std::ostream* err_stream);
|
||||
|
||||
// If true, ignore any cross-reference streams in a hybrid file (one that contains both
|
||||
// cross-reference streams and cross-reference tables). This can be useful for testing to
|
||||
// ensure that a hybrid file would work with an older reader.
|
||||
QPDF_DLL
|
||||
void setIgnoreXRefStreams(bool);
|
||||
|
||||
// By default, any warnings are issued to std::cerr or the error stream specified in a call to
|
||||
// setOutputStreams as they are encountered. If this method is called with a true value,
|
||||
// reporting of warnings is suppressed. You may still retrieve warnings by calling getWarnings.
|
||||
QPDF_DLL
|
||||
void setSuppressWarnings(bool);
|
||||
|
||||
// Set the maximum number of warnings. A QPDFExc is thrown if the limit is exceeded.
|
||||
QPDF_DLL
|
||||
void setMaxWarnings(size_t);
|
||||
|
||||
// By default, QPDF will try to recover if it finds certain types of errors in PDF files. If
|
||||
// turned off, it will throw an exception on the first such problem it finds without attempting
|
||||
// recovery.
|
||||
QPDF_DLL
|
||||
void setAttemptRecovery(bool);
|
||||
|
||||
// Tell other QPDF objects that streams copied from this QPDF need to be fully copied when
|
||||
// copyForeignObject is called on them. Calling setIgnoreXRefStreams(true) on a QPDF object
|
||||
// makes it possible for the object and its input source to disappear before streams copied from
|
||||
// it are written with the destination QPDF object. Confused? Ordinarily, if you are going to
|
||||
// copy objects from a source QPDF object to a destination QPDF object using copyForeignObject
|
||||
// or addPage, the source object's input source must stick around until after the destination
|
||||
// PDF is written. If you call this method on the source QPDF object, it sends a signal to the
|
||||
// destination object that it must fully copy the stream data when copyForeignObject. It will do
|
||||
// this by making a copy in RAM. Ordinarily the stream data is copied lazily to avoid
|
||||
// unnecessary duplication of the stream data. Note that the stream data is copied into RAM only
|
||||
// once regardless of how many objects the stream is copied into. The result is that, if you
|
||||
// called setImmediateCopyFrom(true) on a given QPDF object prior to copying any of its streams,
|
||||
// you do not need to keep it or its input source around after copying its objects to another
|
||||
// QPDF. This is true even if the source streams use StreamDataProvider. Note that this method
|
||||
// is called on the QPDF object you are copying FROM, not the one you are copying to. The
|
||||
// reasoning for this is that there's no reason a given QPDF may not get objects copied to it
|
||||
// from a variety of other objects, some transient and some not. Since what's relevant is
|
||||
// whether the source QPDF is transient, the method must be called on the source QPDF, not the
|
||||
// destination one. This method will make a copy of the stream in RAM, so be sure you have
|
||||
// enough memory to simultaneously hold all the streams you're copying.
|
||||
QPDF_DLL
|
||||
void setImmediateCopyFrom(bool);
|
||||
|
||||
// Other public methods
|
||||
|
||||
// Return the list of warnings that have been issued so far and clear the list. This method may
|
||||
// be called even if processFile throws an exception. Note that if setSuppressWarnings was not
|
||||
// called or was called with a false value, any warnings retrieved here will have already been
|
||||
// output.
|
||||
QPDF_DLL
|
||||
std::vector<QPDFExc> getWarnings();
|
||||
|
||||
// Indicate whether any warnings have been issued so far. Does not clear the list of warnings.
|
||||
QPDF_DLL
|
||||
bool anyWarnings() const;
|
||||
|
||||
// Indicate the number of warnings that have been issued since the last call to getWarnings.
|
||||
// Does not clear the list of warnings.
|
||||
QPDF_DLL
|
||||
size_t numWarnings() const;
|
||||
|
||||
// Return an application-scoped unique ID for this QPDF object. This is not a globally unique
|
||||
// ID. It is constructed using a timestamp and a random number and is intended to be unique
|
||||
// among QPDF objects that are created by a single run of an application. While it's very likely
|
||||
// that these are actually globally unique, it is not recommended to use them for long-term
|
||||
// purposes.
|
||||
QPDF_DLL
|
||||
unsigned long long getUniqueId() const;
|
||||
|
||||
// Issue a warning on behalf of this QPDF object. It will be emitted with other warnings,
|
||||
// following warning suppression rules, and it will be available with getWarnings().
|
||||
QPDF_DLL
|
||||
void warn(QPDFExc const& e);
|
||||
// Same as above but creates the QPDFExc object using the arguments passed to warn. The filename
|
||||
// argument to QPDFExc is omitted. This method uses the filename associated with the QPDF
|
||||
// object.
|
||||
QPDF_DLL
|
||||
void warn(
|
||||
qpdf_error_code_e error_code,
|
||||
std::string const& object,
|
||||
qpdf_offset_t offset,
|
||||
std::string const& message);
|
||||
|
||||
// Return the filename associated with the QPDF object.
|
||||
QPDF_DLL
|
||||
std::string getFilename() const;
|
||||
// Return PDF Version and extension level together as a PDFVersion object
|
||||
QPDF_DLL
|
||||
PDFVersion getVersionAsPDFVersion();
|
||||
// Return just the PDF version from the file
|
||||
QPDF_DLL
|
||||
std::string getPDFVersion() const;
|
||||
QPDF_DLL
|
||||
int getExtensionLevel();
|
||||
QPDF_DLL
|
||||
QPDFObjectHandle getTrailer();
|
||||
QPDF_DLL
|
||||
QPDFObjectHandle getRoot();
|
||||
QPDF_DLL
|
||||
std::map<QPDFObjGen, QPDFXRefEntry> getXRefTable();
|
||||
|
||||
// Public factory methods
|
||||
|
||||
// Create a new stream. A subsequent call must be made to replaceStreamData() to provide data
|
||||
// for the stream. The stream's dictionary may be retrieved by calling getDict(), and the
|
||||
// resulting dictionary may be modified. Alternatively, you can create a new dictionary and
|
||||
// call replaceDict to install it.
|
||||
QPDF_DLL
|
||||
QPDFObjectHandle newStream();
|
||||
|
||||
// Create a new stream. Use the given buffer as the stream data. The stream dictionary's
|
||||
// /Length key will automatically be set to the size of the data buffer. If additional keys are
|
||||
// required, the stream's dictionary may be retrieved by calling getDict(), and the resulting
|
||||
// dictionary may be modified. This method is just a convenient wrapper around the newStream()
|
||||
// and replaceStreamData(). It is a convenience methods for streams that require no parameters
|
||||
// beyond the stream length. Note that you don't have to deal with compression yourself if you
|
||||
// use QPDFWriter. By default, QPDFWriter will automatically compress uncompressed stream data.
|
||||
// Example programs are provided that illustrate this.
|
||||
QPDF_DLL
|
||||
QPDFObjectHandle newStream(std::shared_ptr<Buffer> data);
|
||||
|
||||
// Create new stream with data from string. This method will create a copy of the data rather
|
||||
// than using the user-provided buffer as in the std::shared_ptr<Buffer> version of newStream.
|
||||
QPDF_DLL
|
||||
QPDFObjectHandle newStream(std::string const& data);
|
||||
|
||||
// A reserved object is a special sentinel used for qpdf to reserve a spot for an object that is
|
||||
// going to be added to the QPDF object. Normally you don't have to use this type since you can
|
||||
// just call QPDF::makeIndirectObject. However, in some cases, if you have to create objects
|
||||
// with circular references, you may need to create a reserved object so that you can have a
|
||||
// reference to it and then replace the object later. Reserved objects have the special
|
||||
// property that they can't be resolved to direct objects. This makes it possible to replace a
|
||||
// reserved object with a new object while preserving existing references to them. When you are
|
||||
// ready to replace a reserved object with its replacement, use QPDF::replaceReserved for this
|
||||
// purpose rather than the more general QPDF::replaceObject. It is an error to try to write a
|
||||
// QPDF with QPDFWriter if it has any reserved objects in it.
|
||||
QPDF_DLL
|
||||
QPDFObjectHandle newReserved();
|
||||
QPDF_DLL
|
||||
QPDFObjectHandle newIndirectNull();
|
||||
|
||||
// Install this object handle as an indirect object and return an indirect reference to it.
|
||||
QPDF_DLL
|
||||
QPDFObjectHandle makeIndirectObject(QPDFObjectHandle);
|
||||
|
||||
// Retrieve an object by object ID and generation. Returns an indirect reference to it. The
|
||||
// getObject() methods were added for qpdf 11.
|
||||
QPDF_DLL
|
||||
QPDFObjectHandle getObject(QPDFObjGen);
|
||||
QPDF_DLL
|
||||
QPDFObjectHandle getObject(int objid, int generation);
|
||||
// These are older methods, but there is no intention to deprecate
|
||||
// them.
|
||||
QPDF_DLL
|
||||
QPDFObjectHandle getObjectByObjGen(QPDFObjGen);
|
||||
QPDF_DLL
|
||||
QPDFObjectHandle getObjectByID(int objid, int generation);
|
||||
|
||||
// Replace the object with the given object id with the given object. The object handle passed
|
||||
// in must be a direct object, though it may contain references to other indirect objects within
|
||||
// it. Prior to qpdf 10.2.1, after calling this method, existing QPDFObjectHandle instances that
|
||||
// pointed to the original object still pointed to the original object, resulting in confusing
|
||||
// and incorrect behavior. This was fixed in 10.2.1, so existing QPDFObjectHandle objects will
|
||||
// start pointing to the newly replaced object. Note that replacing an object with
|
||||
// QPDFObjectHandle::newNull() effectively removes the object from the file since a non-existent
|
||||
// object is treated as a null object. To replace a reserved object, call replaceReserved
|
||||
// instead.
|
||||
QPDF_DLL
|
||||
void replaceObject(QPDFObjGen og, QPDFObjectHandle);
|
||||
QPDF_DLL
|
||||
void replaceObject(int objid, int generation, QPDFObjectHandle);
|
||||
|
||||
// Swap two objects given by ID. Prior to qpdf 10.2.1, existing QPDFObjectHandle instances that
|
||||
// reference them objects not notice the swap, but this was fixed in 10.2.1.
|
||||
QPDF_DLL
|
||||
void swapObjects(QPDFObjGen og1, QPDFObjGen og2);
|
||||
QPDF_DLL
|
||||
void swapObjects(int objid1, int generation1, int objid2, int generation2);
|
||||
|
||||
// Replace a reserved object. This is a wrapper around replaceObject but it guarantees that the
|
||||
// underlying object is a reserved object or a null object. After this call, reserved will
|
||||
// be a reference to replacement.
|
||||
QPDF_DLL
|
||||
void replaceReserved(QPDFObjectHandle reserved, QPDFObjectHandle replacement);
|
||||
|
||||
// Copy an object from another QPDF to this one. Starting with qpdf version 8.3.0, it is no
|
||||
// longer necessary to keep the original QPDF around after the call to copyForeignObject as long
|
||||
// as the source of any copied stream data is still available. Usually this means you just have
|
||||
// to keep the input file around, not the QPDF object. The exception to this is if you copy a
|
||||
// stream that gets its data from a QPDFObjectHandle::StreamDataProvider. In this case only, the
|
||||
// original stream's QPDF object must stick around because the QPDF object is itself the source
|
||||
// of the original stream data. For a more in-depth discussion, please see the TODO file.
|
||||
// Starting in 8.4.0, you can call setImmediateCopyFrom(true) on the SOURCE QPDF object (the one
|
||||
// you're copying FROM). If you do this prior to copying any of its objects, then neither the
|
||||
// source QPDF object nor its input source needs to stick around at all regardless of the
|
||||
// source. The cost is that the stream data is copied into RAM at the time copyForeignObject is
|
||||
// called. See setImmediateCopyFrom for more information.
|
||||
//
|
||||
// The return value of this method is an indirect reference to the copied object in this file.
|
||||
// This method is intended to be used to copy non-page objects. To copy page objects, pass the
|
||||
// foreign page object directly to addPage (or addPageAt). If you copy objects that contain
|
||||
// references to pages, you should copy the pages first using addPage(At). Otherwise references
|
||||
// to the pages that have not been copied will be replaced with nulls. It is possible to use
|
||||
// copyForeignObject on page objects if you are not going to use them as pages. Doing so copies
|
||||
// the object normally but does not update the page structure. For example, it is a valid use
|
||||
// case to use copyForeignObject for a page that you are going to turn into a form XObject,
|
||||
// though you can also use QPDFPageObjectHelper::getFormXObjectForPage for that purpose.
|
||||
//
|
||||
// When copying objects with this method, object structure will be preserved, so all indirectly
|
||||
// referenced indirect objects will be copied as well. This includes any circular references
|
||||
// that may exist. The QPDF object keeps a record of what has already been copied, so shared
|
||||
// objects will not be copied multiple times. This also means that if you mutate an object that
|
||||
// has already been copied and try to copy it again, it won't work since the modified object
|
||||
// will not be recopied. Therefore, you should do all mutation on the original file that you
|
||||
// are going to do before you start copying its objects to a new file.
|
||||
QPDF_DLL
|
||||
QPDFObjectHandle copyForeignObject(QPDFObjectHandle foreign);
|
||||
|
||||
// Encryption support
|
||||
|
||||
enum encryption_method_e { e_none, e_unknown, e_rc4, e_aes, e_aesv3 };
|
||||
|
||||
// To be removed from the public API in qpdf 13. See
|
||||
// <https:manual.qpdf.org/release-notes.html#r12-3-0-deprecate>.
|
||||
class EncryptionData
|
||||
{
|
||||
public:
|
||||
// This class holds data read from the encryption dictionary.
|
||||
EncryptionData(
|
||||
int V,
|
||||
int R,
|
||||
int Length_bytes,
|
||||
int P,
|
||||
std::string const& O,
|
||||
std::string const& U,
|
||||
std::string const& OE,
|
||||
std::string const& UE,
|
||||
std::string const& Perms,
|
||||
std::string const& id1,
|
||||
bool encrypt_metadata) :
|
||||
V(V),
|
||||
R(R),
|
||||
Length_bytes(Length_bytes),
|
||||
P(P),
|
||||
O(O),
|
||||
U(U),
|
||||
OE(OE),
|
||||
UE(UE),
|
||||
Perms(Perms),
|
||||
id1(id1),
|
||||
encrypt_metadata(encrypt_metadata)
|
||||
{
|
||||
}
|
||||
|
||||
int getV() const;
|
||||
int getR() const;
|
||||
int getLengthBytes() const;
|
||||
int getP() const;
|
||||
std::string const& getO() const;
|
||||
std::string const& getU() const;
|
||||
std::string const& getOE() const;
|
||||
std::string const& getUE() const;
|
||||
std::string const& getPerms() const;
|
||||
std::string const& getId1() const;
|
||||
bool getEncryptMetadata() const;
|
||||
|
||||
void setO(std::string const&);
|
||||
void setU(std::string const&);
|
||||
void setV5EncryptionParameters(
|
||||
std::string const& O,
|
||||
std::string const& OE,
|
||||
std::string const& U,
|
||||
std::string const& UE,
|
||||
std::string const& Perms);
|
||||
|
||||
private:
|
||||
EncryptionData(EncryptionData const&) = delete;
|
||||
EncryptionData& operator=(EncryptionData const&) = delete;
|
||||
|
||||
int V;
|
||||
int R;
|
||||
int Length_bytes;
|
||||
int P;
|
||||
std::string O;
|
||||
std::string U;
|
||||
std::string OE;
|
||||
std::string UE;
|
||||
std::string Perms;
|
||||
std::string id1;
|
||||
bool encrypt_metadata;
|
||||
};
|
||||
QPDF_DLL
|
||||
bool isEncrypted() const;
|
||||
|
||||
QPDF_DLL
|
||||
bool isEncrypted(int& R, int& P);
|
||||
|
||||
QPDF_DLL
|
||||
bool isEncrypted(
|
||||
int& R,
|
||||
int& P,
|
||||
int& V,
|
||||
encryption_method_e& stream_method,
|
||||
encryption_method_e& string_method,
|
||||
encryption_method_e& file_method);
|
||||
|
||||
QPDF_DLL
|
||||
bool ownerPasswordMatched() const;
|
||||
|
||||
QPDF_DLL
|
||||
bool userPasswordMatched() const;
|
||||
|
||||
// Encryption permissions -- not enforced by QPDF
|
||||
QPDF_DLL
|
||||
bool allowAccessibility();
|
||||
QPDF_DLL
|
||||
bool allowExtractAll();
|
||||
QPDF_DLL
|
||||
bool allowPrintLowRes();
|
||||
QPDF_DLL
|
||||
bool allowPrintHighRes();
|
||||
QPDF_DLL
|
||||
bool allowModifyAssembly();
|
||||
QPDF_DLL
|
||||
bool allowModifyForm();
|
||||
QPDF_DLL
|
||||
bool allowModifyAnnotation();
|
||||
QPDF_DLL
|
||||
bool allowModifyOther();
|
||||
QPDF_DLL
|
||||
bool allowModifyAll();
|
||||
|
||||
// Helper function to trim padding from user password. Calling trim_user_password on the result
|
||||
// of getPaddedUserPassword gives getTrimmedUserPassword's result.
|
||||
QPDF_DLL
|
||||
static void trim_user_password(std::string& user_password);
|
||||
QPDF_DLL
|
||||
static std::string compute_data_key(
|
||||
std::string const& encryption_key,
|
||||
int objid,
|
||||
int generation,
|
||||
bool use_aes,
|
||||
int encryption_V,
|
||||
int encryption_R);
|
||||
|
||||
// To be removed in qpdf 13. See <https:manual.qpdf.org/release-notes.html#r12-3-0-deprecate>.
|
||||
[[deprecated("to be removed in qpdf 13")]]
|
||||
QPDF_DLL static std::string
|
||||
compute_encryption_key(std::string const& password, EncryptionData const& data);
|
||||
|
||||
QPDF_DLL
|
||||
static void compute_encryption_O_U(
|
||||
char const* user_password,
|
||||
char const* owner_password,
|
||||
int V,
|
||||
int R,
|
||||
int key_len,
|
||||
int P,
|
||||
bool encrypt_metadata,
|
||||
std::string const& id1,
|
||||
std::string& O,
|
||||
std::string& U);
|
||||
QPDF_DLL
|
||||
static void compute_encryption_parameters_V5(
|
||||
char const* user_password,
|
||||
char const* owner_password,
|
||||
int V,
|
||||
int R,
|
||||
int key_len,
|
||||
int P,
|
||||
bool encrypt_metadata,
|
||||
std::string const& id1,
|
||||
std::string& encryption_key,
|
||||
std::string& O,
|
||||
std::string& U,
|
||||
std::string& OE,
|
||||
std::string& UE,
|
||||
std::string& Perms);
|
||||
// Return the full user password as stored in the PDF file. For files encrypted with 40-bit or
|
||||
// 128-bit keys, the user password can be recovered when the file is opened using the owner
|
||||
// password. This is not possible with newer encryption formats. If you are attempting to
|
||||
// recover the user password in a user-presentable form, call getTrimmedUserPassword() instead.
|
||||
QPDF_DLL
|
||||
std::string const& getPaddedUserPassword() const;
|
||||
// Return human-readable form of user password subject to same limitations as
|
||||
// getPaddedUserPassword().
|
||||
QPDF_DLL
|
||||
std::string getTrimmedUserPassword() const;
|
||||
// Return the previously computed or retrieved encryption key for this file
|
||||
QPDF_DLL
|
||||
std::string getEncryptionKey() const;
|
||||
// Remove security restrictions associated with digitally signed files. From qpdf 11.7.0, this
|
||||
// is called by QPDFAcroFormDocumentHelper::disableDigitalSignatures and is more useful when
|
||||
// called from there than when just called by itself.
|
||||
QPDF_DLL
|
||||
void removeSecurityRestrictions();
|
||||
|
||||
// Linearization support
|
||||
|
||||
// Returns true iff the file starts with a linearization parameter dictionary. Does no
|
||||
// additional validation.
|
||||
QPDF_DLL
|
||||
bool isLinearized();
|
||||
|
||||
// Performs various sanity checks on a linearized file. Return true if no errors or warnings.
|
||||
// Otherwise, return false and output errors and warnings to the default output stream
|
||||
// (std::cout or whatever is configured in the logger). It is recommended for linearization
|
||||
// errors to be treated as warnings.
|
||||
QPDF_DLL
|
||||
bool checkLinearization();
|
||||
|
||||
// Calls checkLinearization() and, if possible, prints normalized contents of some of the hints
|
||||
// tables to the default output stream. Normalization includes adding min values to delta values
|
||||
// and adjusting offsets based on the location and size of the primary hint stream.
|
||||
QPDF_DLL
|
||||
void showLinearizationData();
|
||||
|
||||
// Shows the contents of the cross-reference table
|
||||
QPDF_DLL
|
||||
void showXRefTable();
|
||||
|
||||
// Starting from qpdf 11.0 user code should not need to call this method. Before 11.0 this
|
||||
// method was used to detect all indirect references to objects that don't exist and resolve
|
||||
// them by replacing them with null, which is how the PDF spec says to interpret such dangling
|
||||
// references. This method is called automatically when you try to add any new objects, if you
|
||||
// call getAllObjects, and before a file is written. The qpdf object caches whether it has run
|
||||
// this to avoid running it multiple times. Before 11.2.1 you could pass true to force it to run
|
||||
// again if you had explicitly added new objects that may have additional dangling references.
|
||||
QPDF_DLL
|
||||
void fixDanglingReferences(bool force = false);
|
||||
|
||||
// Return the approximate number of indirect objects. It is/ approximate because not all objects
|
||||
// in the file are preserved in all cases, and gaps in object numbering are not preserved.
|
||||
QPDF_DLL
|
||||
size_t getObjectCount();
|
||||
|
||||
// Returns a list of indirect objects for every object in the xref table. Useful for discovering
|
||||
// objects that are not otherwise referenced.
|
||||
QPDF_DLL
|
||||
std::vector<QPDFObjectHandle> getAllObjects();
|
||||
|
||||
// Optimization support -- see doc/optimization. Implemented in QPDF_optimization.cc
|
||||
|
||||
// The object_stream_data map maps from a "compressed" object to the object stream that contains
|
||||
// it. This enables optimize to populate the object <-> user maps with only uncompressed
|
||||
// objects. If allow_changes is false, an exception will be thrown if any changes are made
|
||||
// during the optimization process. This is available so that the test suite can make sure that
|
||||
// a linearized file is already optimized. When called in this way, optimize() still populates
|
||||
// the object <-> user maps. The optional skip_stream_parameters parameter, if present, is
|
||||
// called for each stream object. The function should return 2 if optimization should discard
|
||||
// /Length, /Filter, and /DecodeParms; 1 if it should discard /Length, and 0 if it should
|
||||
// preserve all keys. This is used by QPDFWriter to avoid creation of dangling objects for
|
||||
// stream dictionary keys it will be regenerating.
|
||||
[[deprecated("Unused - see release notes for qpdf 12.1.0")]] QPDF_DLL void optimize(
|
||||
std::map<int, int> const& object_stream_data,
|
||||
bool allow_changes = true,
|
||||
std::function<int(QPDFObjectHandle&)> skip_stream_parameters = nullptr);
|
||||
|
||||
// Traverse page tree return all /Page objects. It also detects and resolves cases in which the
|
||||
// same /Page object is duplicated. For efficiency, this method returns a const reference to an
|
||||
// internal vector of pages. Calls to addPage, addPageAt, and removePage safely update this, but
|
||||
// direct manipulation of the pages tree or pushing inheritable objects to the page level may
|
||||
// invalidate it. See comments for updateAllPagesCache() for additional notes. Newer code should
|
||||
// use QPDFPageDocumentHelper::getAllPages instead. The decision to expose this internal cache
|
||||
// was arguably incorrect, but it is being left here for compatibility. It is, however,
|
||||
// completely safe to use this for files that you are not modifying.
|
||||
QPDF_DLL
|
||||
std::vector<QPDFObjectHandle> const& getAllPages();
|
||||
|
||||
QPDF_DLL
|
||||
bool everCalledGetAllPages() const;
|
||||
QPDF_DLL
|
||||
bool everPushedInheritedAttributesToPages() const;
|
||||
|
||||
// These methods, given a page object or its object/generation number, returns the 0-based index
|
||||
// into the array returned by getAllPages() for that page. An exception is thrown if the page is
|
||||
// not found.
|
||||
QPDF_DLL
|
||||
int findPage(QPDFObjGen og);
|
||||
QPDF_DLL
|
||||
int findPage(QPDFObjectHandle& page);
|
||||
|
||||
// This method synchronizes QPDF's cache of the page structure with the actual /Pages tree. If
|
||||
// you restrict changes to the /Pages tree, including addition, removal, or replacement of pages
|
||||
// or changes to any /Pages objects, to calls to these page handling APIs, you never need to
|
||||
// call this method. If you modify /Pages structures directly, you must call this method
|
||||
// afterwards. This method updates the internal list of pages, so after calling this method,
|
||||
// any previous references returned by getAllPages() will be valid again. It also resets any
|
||||
// state about having pushed inherited attributes in /Pages objects down to the pages, so if you
|
||||
// add any inheritable attributes to a /Pages object, you should also call this method.
|
||||
QPDF_DLL
|
||||
void updateAllPagesCache();
|
||||
|
||||
// Legacy handling API. These methods are not going anywhere, and you should feel free to
|
||||
// continue using them if it simplifies your code. Newer code should make use of
|
||||
// QPDFPageDocumentHelper instead as future page handling methods will be added there. The
|
||||
// functionality and specification of these legacy methods is identical to the identically named
|
||||
// methods there, except that these versions use QPDFObjectHandle instead of
|
||||
// QPDFPageObjectHelper, so please see comments in that file for descriptions. There are
|
||||
// subtleties you need to know about, so please look at the comments there.
|
||||
QPDF_DLL
|
||||
void pushInheritedAttributesToPage();
|
||||
QPDF_DLL
|
||||
void addPage(QPDFObjectHandle newpage, bool first);
|
||||
QPDF_DLL
|
||||
void addPageAt(QPDFObjectHandle newpage, bool before, QPDFObjectHandle refpage);
|
||||
QPDF_DLL
|
||||
void removePage(QPDFObjectHandle page);
|
||||
// End legacy page helpers
|
||||
|
||||
// End of the public API. The following classes and methods are for qpdf internal use only.
|
||||
|
||||
class Doc;
|
||||
|
||||
inline Doc& doc();
|
||||
|
||||
// For testing only -- do not add to DLL
|
||||
static bool test_json_validators();
|
||||
|
||||
private:
|
||||
// It has never been safe to copy QPDF objects as there is code in the library that assumes
|
||||
// there are no copies of a QPDF object. Copying QPDF objects was not prevented by the API until
|
||||
// qpdf 11. If you have been copying QPDF objects, use std::shared_ptr<QPDF> instead. From qpdf
|
||||
// 11, you can use QPDF::create to create them.
|
||||
QPDF(QPDF const&) = delete;
|
||||
QPDF& operator=(QPDF const&) = delete;
|
||||
|
||||
static std::string const qpdf_version;
|
||||
|
||||
class ObjCache;
|
||||
class EncryptionParameters;
|
||||
class StringDecrypter;
|
||||
class ResolveRecorder;
|
||||
class JSONReactor;
|
||||
|
||||
void removeObject(QPDFObjGen og);
|
||||
|
||||
// Calls finish() on the pipeline when done but does not delete it
|
||||
bool pipeStreamData(
|
||||
QPDFObjGen og,
|
||||
qpdf_offset_t offset,
|
||||
size_t length,
|
||||
QPDFObjectHandle dict,
|
||||
bool is_root_metadata,
|
||||
Pipeline* pipeline,
|
||||
bool suppress_warnings,
|
||||
bool will_retry);
|
||||
static bool pipeStreamData(
|
||||
std::shared_ptr<QPDF::EncryptionParameters> encp,
|
||||
std::shared_ptr<InputSource> file,
|
||||
QPDF& qpdf_for_warning,
|
||||
QPDFObjGen og,
|
||||
qpdf_offset_t offset,
|
||||
size_t length,
|
||||
QPDFObjectHandle dict,
|
||||
bool is_root_metadata,
|
||||
Pipeline* pipeline,
|
||||
bool suppress_warnings,
|
||||
bool will_retry);
|
||||
|
||||
// methods to support encryption -- implemented in QPDF_encryption.cc
|
||||
void initializeEncryption();
|
||||
static std::string
|
||||
getKeyForObject(std::shared_ptr<EncryptionParameters> encp, QPDFObjGen og, bool use_aes);
|
||||
void decryptString(std::string&, QPDFObjGen og);
|
||||
static void decryptStream(
|
||||
std::shared_ptr<EncryptionParameters> encp,
|
||||
std::shared_ptr<InputSource> file,
|
||||
QPDF& qpdf_for_warning,
|
||||
Pipeline*& pipeline,
|
||||
QPDFObjGen og,
|
||||
QPDFObjectHandle& stream_dict,
|
||||
bool is_root_metadata,
|
||||
std::unique_ptr<Pipeline>& heap);
|
||||
|
||||
// JSON import
|
||||
void importJSON(std::shared_ptr<InputSource>, bool must_be_complete);
|
||||
|
||||
class Members;
|
||||
|
||||
// Keep all member variables inside the Members object, which we dynamically allocate. This
|
||||
// makes it possible to add new private members without breaking binary compatibility.
|
||||
std::unique_ptr<Members> m;
|
||||
};
|
||||
|
||||
#endif // QPDF_HH
|
||||
Vendored
+234
@@ -0,0 +1,234 @@
|
||||
// Copyright (c) 2005-2021 Jay Berkenbilt
|
||||
// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger
|
||||
//
|
||||
// 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 QPDFACROFORMDOCUMENTHELPER_HH
|
||||
#define QPDFACROFORMDOCUMENTHELPER_HH
|
||||
|
||||
#include <qpdf/QPDFDocumentHelper.hh>
|
||||
|
||||
#include <qpdf/DLL.h>
|
||||
|
||||
#include <qpdf/QPDFAnnotationObjectHelper.hh>
|
||||
#include <qpdf/QPDFFormFieldObjectHelper.hh>
|
||||
#include <qpdf/QPDFPageObjectHelper.hh>
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
// This document helper is intended to help with operations on interactive forms. Here are the key
|
||||
// things to know:
|
||||
|
||||
// * The PDF specification talks about interactive forms and also about form XObjects. While form
|
||||
// XObjects appear in parts of interactive forms, this class is concerned about interactive forms,
|
||||
// not form XObjects.
|
||||
//
|
||||
// * Interactive forms are discussed in the PDF Specification (ISO PDF 32000-1:2008) section 12.7.
|
||||
// Also relevant is the section about Widget annotations. Annotations are discussed in section
|
||||
// 12.5 with annotation dictionaries discussed in 12.5.1. Widget annotations are discussed
|
||||
// specifically in section 12.5.6.19.
|
||||
//
|
||||
// * What you need to know about the structure of interactive forms in PDF files:
|
||||
//
|
||||
// - The document catalog contains the key "/AcroForm" which contains a list of fields. Fields are
|
||||
// represented as a tree structure much like pages. Nodes in the fields tree may contain other
|
||||
// fields. Fields may inherit values of many of their attributes from ancestors in the tree.
|
||||
//
|
||||
// - Fields may also have children that are widget annotations. As a special case, and a cause of
|
||||
// considerable confusion, if a field has a single annotation as a child, the annotation
|
||||
// dictionary may be merged with the field dictionary. In that case, the field and the
|
||||
// annotation are in the same object. Note that, while field dictionary attributes are
|
||||
// inherited, annotation dictionary attributes are not.
|
||||
//
|
||||
// - A page dictionary contains a key called "/Annots" which contains a simple list of
|
||||
// annotations. For any given annotation of subtype "/Widget", you should encounter that
|
||||
// annotation in the "/Annots" dictionary of a page, and you should also be able to reach it by
|
||||
// traversing through the "/AcroForm" dictionary from the document catalog. In the simplest case
|
||||
// (and also a very common case), a form field's widget annotation will be merged with the field
|
||||
// object, and the object will appear directly both under "/Annots" in the page dictionary and
|
||||
// under "/Fields" in the "/AcroForm" dictionary. In a more complex case, you may have to trace
|
||||
// through various "/Kids" elements in the "/AcroForm" field entry until you find the annotation
|
||||
// dictionary.
|
||||
class QPDFAcroFormDocumentHelper: public QPDFDocumentHelper
|
||||
{
|
||||
public:
|
||||
// Get a shared document helper for a given QPDF object.
|
||||
//
|
||||
// Retrieving a document helper for a QPDF object rather than creating a new one avoids repeated
|
||||
// validation of the Acroform structure, which can be expensive.
|
||||
QPDF_DLL
|
||||
static QPDFAcroFormDocumentHelper& get(QPDF& qpdf);
|
||||
|
||||
// Re-validate the AcroForm structure. This is useful if you have modified the structure of the
|
||||
// AcroForm dictionary in a way that would invalidate the cache.
|
||||
//
|
||||
// If repair is true, the document will be repaired if possible if the validation encounters
|
||||
// errors.
|
||||
QPDF_DLL
|
||||
void validate(bool repair = true);
|
||||
|
||||
QPDF_DLL
|
||||
QPDFAcroFormDocumentHelper(QPDF&);
|
||||
|
||||
~QPDFAcroFormDocumentHelper() override = default;
|
||||
|
||||
// This class lazily creates an internal cache of the mapping among form fields, annotations,
|
||||
// and pages. Methods within this class preserve the validity of this cache. However, if you
|
||||
// modify pages' annotation dictionaries, the document's /AcroForm dictionary, or any form
|
||||
// fields manually in a way that alters the association between forms, fields, annotations, and
|
||||
// pages, it may cause this cache to become invalid. This method marks the cache invalid and
|
||||
// forces it to be regenerated the next time it is needed.
|
||||
QPDF_DLL
|
||||
void invalidateCache();
|
||||
|
||||
QPDF_DLL
|
||||
bool hasAcroForm();
|
||||
|
||||
// Add a form field, initializing the document's AcroForm dictionary if needed, updating the
|
||||
// cache if necessary. Note that you are adding fields that are copies of other fields, this
|
||||
// method may result in multiple fields existing with the same qualified name, which can have
|
||||
// unexpected side effects. In that case, you should use addAndRenameFormFields() instead.
|
||||
QPDF_DLL
|
||||
void addFormField(QPDFFormFieldObjectHelper);
|
||||
|
||||
// Add a collection of form fields making sure that their fully qualified names don't conflict
|
||||
// with already present form fields. Fields within the collection of new fields that have the
|
||||
// same name as each other will continue to do so.
|
||||
QPDF_DLL
|
||||
void addAndRenameFormFields(std::vector<QPDFObjectHandle> fields);
|
||||
|
||||
// Remove fields from the fields array
|
||||
QPDF_DLL
|
||||
void removeFormFields(std::set<QPDFObjGen> const&);
|
||||
|
||||
// Set the name of a field, updating internal records of field names. Name should be UTF-8
|
||||
// encoded.
|
||||
QPDF_DLL
|
||||
void setFormFieldName(QPDFFormFieldObjectHelper, std::string const& name);
|
||||
|
||||
// Return a vector of all terminal fields in a document. Terminal fields are fields that have no
|
||||
// children that are also fields. Terminal fields may still have children that are annotations.
|
||||
// Intermediate nodes in the fields tree are not included in this list, but you can still reach
|
||||
// them through the getParent method of the field object helper.
|
||||
QPDF_DLL
|
||||
std::vector<QPDFFormFieldObjectHelper> getFormFields();
|
||||
|
||||
// Return all the form fields that have the given fully-qualified name and also have an explicit
|
||||
// "/T" attribute. For this information to be accurate, any changes to field names must be done
|
||||
// through setFormFieldName() above.
|
||||
QPDF_DLL
|
||||
std::set<QPDFObjGen> getFieldsWithQualifiedName(std::string const& name);
|
||||
|
||||
// Return the annotations associated with a terminal field. Note that in the case of a field
|
||||
// having a single annotation, the underlying object will typically be the same as the
|
||||
// underlying object for the field.
|
||||
QPDF_DLL
|
||||
std::vector<QPDFAnnotationObjectHelper> getAnnotationsForField(QPDFFormFieldObjectHelper);
|
||||
|
||||
// Return annotations of subtype /Widget for a page.
|
||||
QPDF_DLL
|
||||
std::vector<QPDFAnnotationObjectHelper> getWidgetAnnotationsForPage(QPDFPageObjectHelper);
|
||||
|
||||
// Return top-level form fields for a page.
|
||||
QPDF_DLL
|
||||
std::vector<QPDFFormFieldObjectHelper> getFormFieldsForPage(QPDFPageObjectHelper);
|
||||
|
||||
// Return the terminal field that is associated with this annotation. If the annotation
|
||||
// dictionary is merged with the field dictionary, the underlying object will be the same, but
|
||||
// this is not always the case. Note that if you call this method with an annotation that is not
|
||||
// a widget annotation, there will not be an associated field, and this method will return a
|
||||
// helper associated with a null object (isNull() == true).
|
||||
QPDF_DLL
|
||||
QPDFFormFieldObjectHelper getFieldForAnnotation(QPDFAnnotationObjectHelper);
|
||||
|
||||
// Return the current value of /NeedAppearances. If /NeedAppearances is missing, return false as
|
||||
// that is how PDF viewers are supposed to interpret it.
|
||||
QPDF_DLL
|
||||
bool getNeedAppearances();
|
||||
|
||||
// Indicate whether appearance streams must be regenerated. If you modify a field value, you
|
||||
// should call setNeedAppearances(true) unless you also generate an appearance stream for the
|
||||
// corresponding annotation at the same time. If you generate appearance streams for all fields,
|
||||
// you can call setNeedAppearances(false). If you use QPDFFormFieldObjectHelper::setV, it will
|
||||
// automatically call this method unless you tell it not to.
|
||||
QPDF_DLL
|
||||
void setNeedAppearances(bool);
|
||||
|
||||
// If /NeedAppearances is false, do nothing. Otherwise generate appearance streams for all
|
||||
// widget annotations that need them. See comments in QPDFFormFieldObjectHelper.hh for
|
||||
// generateAppearance for limitations. For checkbox and radio button fields, this code ensures
|
||||
// that appearance state is consistent with the field's value and uses any pre-existing
|
||||
// appearance streams.
|
||||
QPDF_DLL
|
||||
void generateAppearancesIfNeeded();
|
||||
|
||||
// Disable Digital Signature Fields. Remove all digital signature fields from the document,
|
||||
// leaving any annotation showing the content of the field intact. This also calls
|
||||
// QPDF::removeSecurityRestrictions.
|
||||
QPDF_DLL
|
||||
void disableDigitalSignatures();
|
||||
|
||||
// Note: this method works on all annotations, not just ones with associated fields. For each
|
||||
// annotation in old_annots, apply the given transformation matrix to create a new annotation.
|
||||
// New annotations are appended to new_annots. If the annotation is associated with a form
|
||||
// field, a new form field is created that points to the new annotation and is appended to
|
||||
// new_fields, and the old field is added to old_fields.
|
||||
//
|
||||
// old_annots may belong to a different QPDF object. In that case, you should pass in from_qpdf,
|
||||
// and copyForeignObject will be called automatically. If this is the case, for efficiency, you
|
||||
// may pass in a QPDFAcroFormDocumentHelper for the other file to avoid the expensive process of
|
||||
// creating one for each call to transformAnnotations. New fields and annotations are not added
|
||||
// to the document or pages. You have to do that yourself after calling transformAnnotations. If
|
||||
// this operation will leave orphaned fields behind, such as if you are replacing the old
|
||||
// annotations with the new ones on the same page and the fields and annotations are not shared,
|
||||
// you will also need to remove the old fields to prevent them from hanging around unreferenced.
|
||||
QPDF_DLL
|
||||
void transformAnnotations(
|
||||
QPDFObjectHandle old_annots,
|
||||
std::vector<QPDFObjectHandle>& new_annots,
|
||||
std::vector<QPDFObjectHandle>& new_fields,
|
||||
std::set<QPDFObjGen>& old_fields,
|
||||
QPDFMatrix const& cm,
|
||||
QPDF* from_qpdf = nullptr,
|
||||
QPDFAcroFormDocumentHelper* from_afdh = nullptr);
|
||||
|
||||
// Copy form fields and annotations from one page to another, allowing the from page to be in a
|
||||
// different QPDF or in the same QPDF. This would typically be called after calling addPage to
|
||||
// add field/annotation awareness. When just copying the page by itself, annotations end up
|
||||
// being shared, and fields end up being omitted because there is no reference to the field from
|
||||
// the page. This method ensures that each separate copy of a page has private annotations and
|
||||
// that fields and annotations are properly updated to resolve conflicts that may occur from
|
||||
// common resource and field names across documents. It is basically a wrapper around
|
||||
// transformAnnotations that handles updating the receiving page. If new_fields is non-null, any
|
||||
// newly created fields are added to it.
|
||||
QPDF_DLL
|
||||
void fixCopiedAnnotations(
|
||||
QPDFObjectHandle to_page,
|
||||
QPDFObjectHandle from_page,
|
||||
QPDFAcroFormDocumentHelper& from_afdh,
|
||||
std::set<QPDFObjGen>* new_fields = nullptr);
|
||||
|
||||
private:
|
||||
friend class QPDF::Doc;
|
||||
class Members;
|
||||
|
||||
std::shared_ptr<Members> m;
|
||||
};
|
||||
|
||||
#endif // QPDFACROFORMDOCUMENTHELPER_HH
|
||||
Vendored
+105
@@ -0,0 +1,105 @@
|
||||
// Copyright (c) 2005-2021 Jay Berkenbilt
|
||||
// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger
|
||||
//
|
||||
// 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 QPDFANNOTATIONOBJECTHELPER_HH
|
||||
#define QPDFANNOTATIONOBJECTHELPER_HH
|
||||
|
||||
#include <qpdf/Constants.h>
|
||||
#include <qpdf/QPDFObjectHelper.hh>
|
||||
|
||||
#include <qpdf/DLL.h>
|
||||
|
||||
class QPDFAnnotationObjectHelper: public QPDFObjectHelper
|
||||
{
|
||||
public:
|
||||
QPDF_DLL
|
||||
QPDFAnnotationObjectHelper(QPDFObjectHandle);
|
||||
|
||||
~QPDFAnnotationObjectHelper() override = default;
|
||||
|
||||
// This class provides helper methods for annotations. More functionality will likely be added
|
||||
// in the future.
|
||||
|
||||
// Some functionality for annotations is also implemented in QPDFAcroFormDocumentHelper and
|
||||
// QPDFFormFieldObjectHelper. In some cases, functions defined there work for other annotations
|
||||
// besides widget annotations, but they are implemented with form fields so that they can
|
||||
// properly handle form fields when needed.
|
||||
|
||||
// Return the subtype of the annotation as a string (e.g. "/Widget"). Returns an empty string
|
||||
// if the subtype (which is required by the spec) is missing.
|
||||
QPDF_DLL
|
||||
std::string getSubtype();
|
||||
|
||||
QPDF_DLL
|
||||
QPDFObjectHandle::Rectangle getRect();
|
||||
|
||||
QPDF_DLL
|
||||
QPDFObjectHandle getAppearanceDictionary();
|
||||
|
||||
// Return the appearance state as given in "/AS", or an empty string if none is given.
|
||||
QPDF_DLL
|
||||
std::string getAppearanceState();
|
||||
|
||||
// Return flags from "/F". The value is a logical or of pdf_annotation_flag_e as defined in
|
||||
// qpdf/Constants.h.
|
||||
QPDF_DLL
|
||||
int getFlags();
|
||||
|
||||
// Return a specific stream. "which" may be one of "/N", "/R", or "/D" to indicate the normal,
|
||||
// rollover, or down appearance stream. (Any value may be passed to "which"; if an appearance
|
||||
// stream of that name exists, it will be returned.) If the value associated with "which" in the
|
||||
// appearance dictionary is a subdictionary, an appearance state may be specified to select
|
||||
// which appearance stream is desired. If not specified, the appearance state in "/AS" will
|
||||
// used.
|
||||
QPDF_DLL
|
||||
QPDFObjectHandle getAppearanceStream(std::string const& which, std::string const& state = "");
|
||||
|
||||
// Generate text suitable for addition to the containing page's content stream that draws this
|
||||
// annotation's appearance stream as a form XObject. The value "name" is the resource name that
|
||||
// will be used to refer to the form xobject. The value "rotate" should be set to the page's
|
||||
// /Rotate value or 0 if none. The values of required_flags and forbidden_flags are constructed
|
||||
// by logically "or"ing annotation flags of type pdf_annotation_flag_e defined in
|
||||
// qpdf/Constants.h. Content will be returned only if all required_flags are set and no
|
||||
// forbidden_flags are set. For example, including an_no_view in forbidden_flags could be useful
|
||||
// for creating an on-screen view, and including an_print to required_flags could be useful if
|
||||
// preparing to print.
|
||||
QPDF_DLL
|
||||
std::string getPageContentForAppearance(
|
||||
std::string const& name,
|
||||
int rotate,
|
||||
int required_flags = 0,
|
||||
int forbidden_flags = an_invisible | an_hidden);
|
||||
|
||||
private:
|
||||
class Members
|
||||
{
|
||||
friend class QPDFAnnotationObjectHelper;
|
||||
|
||||
public:
|
||||
~Members() = default;
|
||||
|
||||
private:
|
||||
Members() = default;
|
||||
Members(Members const&) = delete;
|
||||
};
|
||||
|
||||
std::shared_ptr<Members> m;
|
||||
};
|
||||
|
||||
#endif // QPDFANNOTATIONOBJECTHELPER_HH
|
||||
+82
@@ -0,0 +1,82 @@
|
||||
// Copyright (c) 2005-2021 Jay Berkenbilt
|
||||
// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger
|
||||
//
|
||||
// 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 QPDFCRYPTOIMPL_HH
|
||||
#define QPDFCRYPTOIMPL_HH
|
||||
|
||||
#include <qpdf/DLL.h>
|
||||
#include <string>
|
||||
|
||||
// This class is part of qpdf's pluggable crypto provider support.
|
||||
// Most users won't need to know or care about this class, but you can
|
||||
// use it if you want to supply your own crypto implementation. To do
|
||||
// so, provide an implementation of QPDFCryptoImpl, ensure that you
|
||||
// register it by calling QPDFCryptoProvider::registerImpl, and make
|
||||
// it the default by calling QPDFCryptoProvider::setDefaultProvider.
|
||||
class QPDF_DLL_CLASS QPDFCryptoImpl
|
||||
{
|
||||
public:
|
||||
QPDFCryptoImpl() = default;
|
||||
|
||||
virtual ~QPDFCryptoImpl() = default;
|
||||
|
||||
// Random Number Generation
|
||||
|
||||
virtual void provideRandomData(unsigned char* data, size_t len) = 0;
|
||||
|
||||
// Hashing
|
||||
|
||||
typedef unsigned char MD5_Digest[16];
|
||||
virtual void MD5_init() = 0;
|
||||
virtual void MD5_update(unsigned char const* data, size_t len) = 0;
|
||||
virtual void MD5_finalize() = 0;
|
||||
virtual void MD5_digest(MD5_Digest) = 0;
|
||||
|
||||
virtual void SHA2_init(int bits) = 0;
|
||||
virtual void SHA2_update(unsigned char const* data, size_t len) = 0;
|
||||
virtual void SHA2_finalize() = 0;
|
||||
virtual std::string SHA2_digest() = 0;
|
||||
|
||||
// Encryption/Decryption
|
||||
|
||||
// QPDF must support RC4 to be able to work with older PDF files
|
||||
// and readers. Search for RC4 in README.md
|
||||
|
||||
// key_len of -1 means treat key_data as a null-terminated string
|
||||
virtual void RC4_init(unsigned char const* key_data, int key_len = -1) = 0;
|
||||
// out_data = 0 means to encrypt/decrypt in place
|
||||
virtual void
|
||||
RC4_process(unsigned char const* in_data, size_t len, unsigned char* out_data = nullptr) = 0;
|
||||
virtual void RC4_finalize() = 0;
|
||||
|
||||
static size_t constexpr rijndael_buf_size = 16;
|
||||
virtual void rijndael_init(
|
||||
bool encrypt,
|
||||
unsigned char const* key_data,
|
||||
size_t key_len,
|
||||
bool cbc_mode,
|
||||
unsigned char* cbc_block) = 0;
|
||||
virtual void rijndael_process(unsigned char* in_data, unsigned char* out_data) = 0;
|
||||
virtual void rijndael_finalize() = 0;
|
||||
};
|
||||
|
||||
#endif // QPDFCRYPTOIMPL_HH
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
// Copyright (c) 2005-2021 Jay Berkenbilt
|
||||
// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger
|
||||
//
|
||||
// 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 QPDFCRYPTOPROVIDER_HH
|
||||
#define QPDFCRYPTOPROVIDER_HH
|
||||
|
||||
#include <qpdf/DLL.h>
|
||||
#include <qpdf/QPDFCryptoImpl.hh>
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
// This class is part of qpdf's pluggable crypto provider support. Most users won't need to know or
|
||||
// care about this class, but you can use it if you want to supply your own crypto implementation.
|
||||
// See also comments in QPDFCryptoImpl.hh.
|
||||
class QPDFCryptoProvider
|
||||
{
|
||||
public:
|
||||
// Methods for getting and registering crypto implementations. These methods are not
|
||||
// thread-safe.
|
||||
|
||||
// Return an instance of a crypto provider using the default implementation.
|
||||
QPDF_DLL
|
||||
static std::shared_ptr<QPDFCryptoImpl> getImpl();
|
||||
|
||||
// Return an instance of the crypto provider registered using the given name.
|
||||
QPDF_DLL
|
||||
static std::shared_ptr<QPDFCryptoImpl> getImpl(std::string const& name);
|
||||
|
||||
typedef std::function<std::shared_ptr<QPDFCryptoImpl>()> provider_fn;
|
||||
|
||||
// Register a crypto implementation with the given name. The provider function must return
|
||||
// a shared pointer to an instance of the implementation class, which must be derived from
|
||||
// QPDFCryptoImpl.
|
||||
QPDF_DLL static void registerImpl(std::string const& name, provider_fn f);
|
||||
|
||||
// Register the given type (T) as a crypto implementation. T must be derived from QPDFCryptoImpl
|
||||
// and must have a constructor that takes no arguments.
|
||||
template <typename T>
|
||||
static void
|
||||
registerImpl(std::string const& name)
|
||||
{
|
||||
registerImpl(name, std::make_shared<T>);
|
||||
}
|
||||
|
||||
// Set the crypto provider registered with the given name as the default crypto implementation.
|
||||
QPDF_DLL
|
||||
static void setDefaultProvider(std::string const& name);
|
||||
|
||||
// Get the names of registered implementations
|
||||
QPDF_DLL
|
||||
static std::set<std::string> getRegisteredImpls();
|
||||
|
||||
// Get the name of the default crypto provider
|
||||
QPDF_DLL
|
||||
static std::string getDefaultProvider();
|
||||
|
||||
private:
|
||||
QPDFCryptoProvider();
|
||||
~QPDFCryptoProvider() = default;
|
||||
QPDFCryptoProvider(QPDFCryptoProvider const&) = delete;
|
||||
QPDFCryptoProvider& operator=(QPDFCryptoProvider const&) = delete;
|
||||
|
||||
static QPDFCryptoProvider& getInstance();
|
||||
|
||||
std::shared_ptr<QPDFCryptoImpl> getImpl_internal(std::string const& name) const;
|
||||
void registerImpl_internal(std::string const& name, provider_fn f);
|
||||
void setDefaultProvider_internal(std::string const& name);
|
||||
|
||||
class Members
|
||||
{
|
||||
friend class QPDFCryptoProvider;
|
||||
|
||||
public:
|
||||
Members() = default;
|
||||
~Members() = default;
|
||||
|
||||
private:
|
||||
Members(Members const&) = delete;
|
||||
Members& operator=(Members const&) = delete;
|
||||
|
||||
std::string default_provider;
|
||||
std::map<std::string, provider_fn> providers;
|
||||
};
|
||||
|
||||
std::shared_ptr<Members> m;
|
||||
};
|
||||
|
||||
#endif // QPDFCRYPTOPROVIDER_HH
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
// Copyright (c) 2005-2021 Jay Berkenbilt
|
||||
// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger
|
||||
//
|
||||
// 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 QPDFDOCUMENTHELPER_HH
|
||||
#define QPDFDOCUMENTHELPER_HH
|
||||
|
||||
#include <qpdf/DLL.h>
|
||||
#include <qpdf/QPDF.hh>
|
||||
|
||||
// This is a base class for QPDF Document Helper classes. Document helpers are classes that provide
|
||||
// a convenient, higher-level API for accessing document-level structures within a PDF file.
|
||||
// Document helpers are always initialized with a reference to a QPDF object, and the object can
|
||||
// always be retrieved. The intention is that you may freely intermix use of document helpers with
|
||||
// the underlying QPDF object unless there is a specific comment in a specific helper method that
|
||||
// says otherwise. The pattern of using helper objects was introduced to allow creation of higher
|
||||
// level helper functions without polluting the public interface of QPDF.
|
||||
class QPDF_DLL_CLASS QPDFDocumentHelper
|
||||
{
|
||||
public:
|
||||
QPDFDocumentHelper(QPDF& qpdf) :
|
||||
qpdf(qpdf)
|
||||
{
|
||||
}
|
||||
QPDF_DLL
|
||||
virtual ~QPDFDocumentHelper();
|
||||
QPDF&
|
||||
getQPDF()
|
||||
{
|
||||
return qpdf;
|
||||
}
|
||||
QPDF const&
|
||||
getQPDF() const
|
||||
{
|
||||
return qpdf;
|
||||
}
|
||||
|
||||
protected:
|
||||
QPDF& qpdf;
|
||||
};
|
||||
|
||||
#endif // QPDFDOCUMENTHELPER_HH
|
||||
Vendored
+100
@@ -0,0 +1,100 @@
|
||||
// Copyright (c) 2005-2021 Jay Berkenbilt
|
||||
// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger
|
||||
//
|
||||
// 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 QPDFEFSTREAMOBJECTHELPER_HH
|
||||
#define QPDFEFSTREAMOBJECTHELPER_HH
|
||||
|
||||
#include <qpdf/QPDFObjectHelper.hh>
|
||||
|
||||
#include <qpdf/DLL.h>
|
||||
|
||||
#include <qpdf/QPDFObjectHandle.hh>
|
||||
#include <functional>
|
||||
|
||||
// This class provides a higher level interface around Embedded File Streams, which are discussed in
|
||||
// section 7.11.4 of the ISO-32000 PDF specification.
|
||||
class QPDFEFStreamObjectHelper: public QPDFObjectHelper
|
||||
{
|
||||
public:
|
||||
QPDF_DLL
|
||||
QPDFEFStreamObjectHelper(QPDFObjectHandle);
|
||||
|
||||
~QPDFEFStreamObjectHelper() override = default;
|
||||
|
||||
// Date parameters are strings that conform to the PDF spec for date/time strings, which is
|
||||
// "D:yyyymmddhhmmss<z>" where <z> is either "Z" for UTC or "-hh'mm'" or "+hh'mm'" for timezone
|
||||
// offset. Examples: "D:20210207161528-05'00'", "D:20210207211528Z". See
|
||||
// QUtil::qpdf_time_to_pdf_time.
|
||||
|
||||
QPDF_DLL
|
||||
std::string getCreationDate();
|
||||
QPDF_DLL
|
||||
std::string getModDate();
|
||||
// Get size as reported in the object; return 0 if not present.
|
||||
QPDF_DLL
|
||||
size_t getSize();
|
||||
// Subtype is a mime type such as "text/plain"
|
||||
QPDF_DLL
|
||||
std::string getSubtype();
|
||||
// Return the checksum as stored in the object as a binary string. This does not check
|
||||
// consistency with the data. If not present, return an empty string. The PDF spec specifies
|
||||
// this as an MD5 checksum and notes that it is not to be used for security purposes since MD5
|
||||
// is known to be insecure.
|
||||
QPDF_DLL
|
||||
std::string getChecksum();
|
||||
|
||||
// Setters return a reference to this object so that they can be used as fluent interfaces, e.g.
|
||||
// efsoh.setCreationDate(x).setModDate(y);
|
||||
|
||||
// Create a new embedded file stream with the given stream data, which can be provided in any of
|
||||
// several ways. To get the new object back, call getObjectHandle() on the returned object. The
|
||||
// checksum and size are computed automatically and stored. Other parameters may be supplied
|
||||
// using setters defined below.
|
||||
QPDF_DLL
|
||||
static QPDFEFStreamObjectHelper createEFStream(QPDF& qpdf, std::shared_ptr<Buffer> data);
|
||||
QPDF_DLL
|
||||
static QPDFEFStreamObjectHelper createEFStream(QPDF& qpdf, std::string const& data);
|
||||
// The provider function must write the data to the given pipeline. The function may be called
|
||||
// multiple times by the qpdf library. You can pass QUtil::file_provider(filename) as the
|
||||
// provider to have the qpdf library provide the contents of filename as a binary.
|
||||
QPDF_DLL
|
||||
static QPDFEFStreamObjectHelper
|
||||
createEFStream(QPDF& qpdf, std::function<void(Pipeline*)> provider);
|
||||
|
||||
// Setters for other parameters
|
||||
QPDF_DLL
|
||||
QPDFEFStreamObjectHelper& setCreationDate(std::string const&);
|
||||
QPDF_DLL
|
||||
QPDFEFStreamObjectHelper& setModDate(std::string const&);
|
||||
|
||||
// Set subtype as a mime-type, e.g. "text/plain" or "application/pdf".
|
||||
QPDF_DLL
|
||||
QPDFEFStreamObjectHelper& setSubtype(std::string const&);
|
||||
|
||||
private:
|
||||
QPDFObjectHandle getParam(std::string const& pkey);
|
||||
void setParam(std::string const& pkey, QPDFObjectHandle const&);
|
||||
static QPDFEFStreamObjectHelper newFromStream(QPDFObjectHandle stream);
|
||||
|
||||
class Members;
|
||||
|
||||
std::shared_ptr<Members> m;
|
||||
};
|
||||
|
||||
#endif // QPDFEFSTREAMOBJECTHELPER_HH
|
||||
Vendored
+90
@@ -0,0 +1,90 @@
|
||||
// Copyright (c) 2005-2021 Jay Berkenbilt
|
||||
// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger
|
||||
//
|
||||
// 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 QPDFEMBEDDEDFILEDOCUMENTHELPER_HH
|
||||
#define QPDFEMBEDDEDFILEDOCUMENTHELPER_HH
|
||||
|
||||
#include <qpdf/QPDFDocumentHelper.hh>
|
||||
|
||||
#include <qpdf/DLL.h>
|
||||
#include <qpdf/QPDF.hh>
|
||||
#include <qpdf/QPDFFileSpecObjectHelper.hh>
|
||||
#include <qpdf/QPDFNameTreeObjectHelper.hh>
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
|
||||
// This class provides a higher level interface around document-level file attachments, also known
|
||||
// as embedded files. These are discussed in sections 7.7.4 and 7.11 of the ISO-32000 PDF
|
||||
// specification.
|
||||
class QPDFEmbeddedFileDocumentHelper: public QPDFDocumentHelper
|
||||
{
|
||||
public:
|
||||
// Get a shared document helper for a given QPDF object.
|
||||
//
|
||||
// Retrieving a document helper for a QPDF object rather than creating a new one avoids repeated
|
||||
// validation of the EmbeddedFiles structure, which can be expensive.
|
||||
QPDF_DLL
|
||||
static QPDFEmbeddedFileDocumentHelper& get(QPDF& qpdf);
|
||||
|
||||
// Re-validate the EmbeddedFiles structure. This is useful if you have modified the structure of
|
||||
// the EmbeddedFiles dictionary in a way that would invalidate the cache.
|
||||
//
|
||||
// If repair is true, the document will be repaired if possible if the validation encounters
|
||||
// errors.
|
||||
QPDF_DLL
|
||||
void validate(bool repair = true);
|
||||
|
||||
QPDF_DLL
|
||||
QPDFEmbeddedFileDocumentHelper(QPDF&);
|
||||
|
||||
~QPDFEmbeddedFileDocumentHelper() override = default;
|
||||
|
||||
QPDF_DLL
|
||||
bool hasEmbeddedFiles() const;
|
||||
|
||||
QPDF_DLL
|
||||
std::map<std::string, std::shared_ptr<QPDFFileSpecObjectHelper>> getEmbeddedFiles();
|
||||
|
||||
// If an embedded file with the given name exists, return a (shared) pointer to it. Otherwise,
|
||||
// return nullptr.
|
||||
QPDF_DLL
|
||||
std::shared_ptr<QPDFFileSpecObjectHelper> getEmbeddedFile(std::string const& name);
|
||||
|
||||
// Add or replace an attachment
|
||||
QPDF_DLL
|
||||
void replaceEmbeddedFile(std::string const& name, QPDFFileSpecObjectHelper const&);
|
||||
|
||||
// Remove an embedded file if present. Return value is true if the file was present and was
|
||||
// removed. This method not only removes the embedded file from the embedded files name tree but
|
||||
// also nulls out the file specification dictionary. This means that any references to this file
|
||||
// from file attachment annotations will also stop working. This is the best way to make the
|
||||
// attachment actually disappear from the file and not just from the list of attachments.
|
||||
QPDF_DLL
|
||||
bool removeEmbeddedFile(std::string const& name);
|
||||
|
||||
private:
|
||||
void initEmbeddedFiles();
|
||||
|
||||
class Members;
|
||||
|
||||
std::shared_ptr<Members> m;
|
||||
};
|
||||
|
||||
#endif // QPDFEMBEDDEDFILEDOCUMENTHELPER_HH
|
||||
@@ -0,0 +1,89 @@
|
||||
// Copyright (c) 2005-2021 Jay Berkenbilt
|
||||
// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger
|
||||
//
|
||||
// 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 QPDFEXC_HH
|
||||
#define QPDFEXC_HH
|
||||
|
||||
#include <qpdf/Constants.h>
|
||||
#include <qpdf/DLL.h>
|
||||
#include <qpdf/Types.h>
|
||||
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
class QPDF_DLL_CLASS QPDFExc: public std::runtime_error
|
||||
{
|
||||
public:
|
||||
QPDF_DLL
|
||||
QPDFExc(
|
||||
qpdf_error_code_e error_code,
|
||||
std::string const& filename,
|
||||
std::string const& object,
|
||||
qpdf_offset_t offset,
|
||||
std::string const& message);
|
||||
|
||||
QPDF_DLL
|
||||
QPDFExc(
|
||||
qpdf_error_code_e error_code,
|
||||
std::string const& filename,
|
||||
std::string const& object,
|
||||
qpdf_offset_t offset,
|
||||
std::string const& message,
|
||||
bool zero_offset_valid);
|
||||
|
||||
~QPDFExc() noexcept override = default;
|
||||
|
||||
// To get a complete error string, call what(), provided by std::exception. The accessors below
|
||||
// return the original values used to create the exception. Only the error code and message are
|
||||
// guaranteed to have non-zero/empty values.
|
||||
|
||||
// There is no lookup code that maps numeric error codes into strings. The numeric error code
|
||||
// is just another way to get at the underlying issue, but it is more programmer-friendly than
|
||||
// trying to parse a string that is subject to change.
|
||||
|
||||
QPDF_DLL
|
||||
qpdf_error_code_e getErrorCode() const;
|
||||
QPDF_DLL
|
||||
std::string const& getFilename() const;
|
||||
QPDF_DLL
|
||||
std::string const& getObject() const;
|
||||
QPDF_DLL
|
||||
qpdf_offset_t getFilePosition() const;
|
||||
QPDF_DLL
|
||||
std::string const& getMessageDetail() const;
|
||||
|
||||
private:
|
||||
QPDF_DLL_PRIVATE
|
||||
static std::string createWhat(
|
||||
std::string const& filename,
|
||||
std::string const& object,
|
||||
qpdf_offset_t offset,
|
||||
std::string const& message);
|
||||
|
||||
// This class does not use the Members pattern to avoid needless memory allocations during
|
||||
// exception handling.
|
||||
|
||||
qpdf_error_code_e error_code;
|
||||
std::string filename;
|
||||
std::string object;
|
||||
qpdf_offset_t offset;
|
||||
std::string message;
|
||||
};
|
||||
|
||||
#endif // QPDFEXC_HH
|
||||
Vendored
+94
@@ -0,0 +1,94 @@
|
||||
// Copyright (c) 2005-2021 Jay Berkenbilt
|
||||
// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger
|
||||
//
|
||||
// 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 QPDFFILESPECOBJECTHELPER_HH
|
||||
#define QPDFFILESPECOBJECTHELPER_HH
|
||||
|
||||
#include <qpdf/QPDFObjectHelper.hh>
|
||||
|
||||
#include <qpdf/DLL.h>
|
||||
|
||||
#include <qpdf/QPDFEFStreamObjectHelper.hh>
|
||||
#include <qpdf/QPDFObjectHandle.hh>
|
||||
|
||||
// This class provides a higher level interface around File Specification dictionaries, which are
|
||||
// discussed in section 7.11 of the ISO-32000 PDF specification.
|
||||
class QPDFFileSpecObjectHelper: public QPDFObjectHelper
|
||||
{
|
||||
public:
|
||||
QPDF_DLL
|
||||
QPDFFileSpecObjectHelper(QPDFObjectHandle);
|
||||
|
||||
~QPDFFileSpecObjectHelper() override = default;
|
||||
|
||||
QPDF_DLL
|
||||
std::string getDescription();
|
||||
|
||||
// Get the main filename for this file specification. In priority order, check /UF, /F, /Unix,
|
||||
// /DOS, /Mac.
|
||||
QPDF_DLL
|
||||
std::string getFilename();
|
||||
|
||||
// Return any of /UF, /F, /Unix, /DOS, /Mac filename keys that may be present in the object.
|
||||
QPDF_DLL
|
||||
std::map<std::string, std::string> getFilenames();
|
||||
|
||||
// Get the requested embedded file stream for this file specification. If key is empty, In
|
||||
// priority order, check /UF, /F, /Unix, /DOS, /Mac. Returns a null object if not found. If this
|
||||
// is an actual embedded file stream, its data is the content of the attachment. You can also
|
||||
// use QPDFEFStreamObjectHelper for higher level access to the parameters.
|
||||
QPDF_DLL
|
||||
QPDFObjectHandle getEmbeddedFileStream(std::string const& key = "");
|
||||
|
||||
// Return the /EF key of the file spec, which is a map from file name key to embedded file
|
||||
// stream.
|
||||
QPDF_DLL
|
||||
QPDFObjectHandle getEmbeddedFileStreams();
|
||||
|
||||
// Setters return a reference to this object so that they can be used as fluent interfaces, e.g.
|
||||
// fsoh.setDescription(x).setFilename(y);
|
||||
|
||||
// Create a new filespec as an indirect object with the given filename, and attach the contents
|
||||
// of the specified file as data in an embedded file stream.
|
||||
QPDF_DLL
|
||||
static QPDFFileSpecObjectHelper
|
||||
createFileSpec(QPDF& qpdf, std::string const& filename, std::string const& fullpath);
|
||||
|
||||
// Create a new filespec as an indirect object with the given unicode filename and embedded file
|
||||
// stream. The file name will be used as both /UF and /F. If you need to override, call
|
||||
// setFilename.
|
||||
QPDF_DLL
|
||||
static QPDFFileSpecObjectHelper
|
||||
createFileSpec(QPDF& qpdf, std::string const& filename, QPDFEFStreamObjectHelper);
|
||||
|
||||
QPDF_DLL
|
||||
QPDFFileSpecObjectHelper& setDescription(std::string const&);
|
||||
// setFilename sets /UF to unicode_name. If compat_name is empty, it is also set to
|
||||
// unicode_name. unicode_name should be a UTF-8 encoded string. compat_name is converted to a
|
||||
// string QPDFObjectHandle literally, preserving whatever encoding it might happen to have.
|
||||
QPDF_DLL
|
||||
QPDFFileSpecObjectHelper&
|
||||
setFilename(std::string const& unicode_name, std::string const& compat_name = "");
|
||||
|
||||
private:
|
||||
class Members;
|
||||
std::shared_ptr<Members> m;
|
||||
};
|
||||
|
||||
#endif // QPDFFILESPECOBJECTHELPER_HH
|
||||
Vendored
+195
@@ -0,0 +1,195 @@
|
||||
// Copyright (c) 2005-2021 Jay Berkenbilt
|
||||
// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger
|
||||
//
|
||||
// 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 QPDFFORMFIELDOBJECTHELPER_HH
|
||||
#define QPDFFORMFIELDOBJECTHELPER_HH
|
||||
|
||||
#include <qpdf/QPDFObjectHelper.hh>
|
||||
|
||||
#include <qpdf/DLL.h>
|
||||
#include <vector>
|
||||
|
||||
class QPDFAnnotationObjectHelper;
|
||||
|
||||
// This object helper helps with form fields for interactive forms. Please see comments in
|
||||
// QPDFAcroFormDocumentHelper.hh for additional details.
|
||||
class QPDFFormFieldObjectHelper: public QPDFObjectHelper
|
||||
{
|
||||
public:
|
||||
QPDF_DLL
|
||||
QPDFFormFieldObjectHelper();
|
||||
QPDF_DLL
|
||||
QPDFFormFieldObjectHelper(QPDFObjectHandle);
|
||||
|
||||
~QPDFFormFieldObjectHelper() override = default;
|
||||
|
||||
QPDF_DLL
|
||||
bool isNull();
|
||||
|
||||
// Return the field's parent. A form field object helper whose underlying object is null is
|
||||
// returned if there is no parent. This condition may be tested by calling isNull().
|
||||
QPDF_DLL
|
||||
QPDFFormFieldObjectHelper getParent();
|
||||
|
||||
// Return the top-level field for this field. Typically this will be the field itself or its
|
||||
// parent. If is_different is provided, it is set to true if the top-level field is different
|
||||
// from the field itself; otherwise it is set to false.
|
||||
QPDF_DLL
|
||||
QPDFFormFieldObjectHelper getTopLevelField(bool* is_different = nullptr);
|
||||
|
||||
// Get a field value, possibly inheriting the value from an ancestor node.
|
||||
QPDF_DLL
|
||||
QPDFObjectHandle getInheritableFieldValue(std::string const& name);
|
||||
|
||||
// Get an inherited field value as a string. If it is not a string, silently return the empty
|
||||
// string.
|
||||
QPDF_DLL
|
||||
std::string getInheritableFieldValueAsString(std::string const& name);
|
||||
|
||||
// Get an inherited field value of type name as a string representing the name. If it is not a
|
||||
// name, silently return the empty string.
|
||||
QPDF_DLL
|
||||
std::string getInheritableFieldValueAsName(std::string const& name);
|
||||
|
||||
// Returns the value of /FT if present, otherwise returns the empty string.
|
||||
QPDF_DLL
|
||||
std::string getFieldType();
|
||||
|
||||
QPDF_DLL
|
||||
std::string getFullyQualifiedName();
|
||||
|
||||
QPDF_DLL
|
||||
std::string getPartialName();
|
||||
|
||||
// Return the alternative field name (/TU), which is the field name intended to be presented to
|
||||
// users. If not present, fall back to the fully qualified name.
|
||||
QPDF_DLL
|
||||
std::string getAlternativeName();
|
||||
|
||||
// Return the mapping field name (/TM). If not present, fall back to the alternative name, then
|
||||
// to the partial name.
|
||||
QPDF_DLL
|
||||
std::string getMappingName();
|
||||
|
||||
QPDF_DLL
|
||||
QPDFObjectHandle getValue();
|
||||
|
||||
// Return the field's value as a string. If this is called with a field whose value is not a
|
||||
// string, the empty string will be silently returned.
|
||||
QPDF_DLL
|
||||
std::string getValueAsString();
|
||||
|
||||
QPDF_DLL
|
||||
QPDFObjectHandle getDefaultValue();
|
||||
|
||||
// Return the field's default value as a string. If this is called with a field whose value is
|
||||
// not a string, the empty string will be silently returned.
|
||||
QPDF_DLL
|
||||
std::string getDefaultValueAsString();
|
||||
|
||||
// Return the default appearance string, taking inheritance from the field tree into account.
|
||||
// Returns the empty string if the default appearance string is not available (because it's
|
||||
// erroneously absent or because this is not a variable text field). If not found in the field
|
||||
// hierarchy, look in /AcroForm.
|
||||
QPDF_DLL
|
||||
std::string getDefaultAppearance();
|
||||
|
||||
// Return the default resource dictionary for the field. This comes not from the field but from
|
||||
// the document-level /AcroForm dictionary. While several PDF generators put a /DR key in the
|
||||
// form field's dictionary, experimentation suggests that many popular readers, including Adobe
|
||||
// Acrobat and Acrobat Reader, ignore any /DR item on the field.
|
||||
QPDF_DLL
|
||||
QPDFObjectHandle getDefaultResources();
|
||||
|
||||
// Return the quadding value, taking inheritance from the field tree into account. Returns 0 if
|
||||
// quadding is not specified. Look in /AcroForm if not found in the field hierarchy.
|
||||
QPDF_DLL
|
||||
int getQuadding();
|
||||
|
||||
// Return field flags from /Ff. The value is a logical or of pdf_form_field_flag_e as defined in
|
||||
// qpdf/Constants.h
|
||||
QPDF_DLL
|
||||
int getFlags();
|
||||
|
||||
// Methods for testing for particular types of form fields
|
||||
|
||||
// Returns true if field is of type /Tx
|
||||
QPDF_DLL
|
||||
bool isText();
|
||||
// Returns true if field is of type /Btn and flags do not indicate some other type of button.
|
||||
QPDF_DLL
|
||||
bool isCheckbox();
|
||||
// Returns true if field is a checkbox and is checked.
|
||||
QPDF_DLL
|
||||
bool isChecked();
|
||||
// Returns true if field is of type /Btn and flags indicate that it is a radio button
|
||||
QPDF_DLL
|
||||
bool isRadioButton();
|
||||
// Returns true if field is of type /Btn and flags indicate that it is a pushbutton
|
||||
QPDF_DLL
|
||||
bool isPushbutton();
|
||||
// Returns true if field is of type /Ch
|
||||
QPDF_DLL
|
||||
bool isChoice();
|
||||
// Returns choices display values as UTF-8 strings
|
||||
QPDF_DLL
|
||||
std::vector<std::string> getChoices();
|
||||
|
||||
// Set an attribute to the given value. If you have a QPDFAcroFormDocumentHelper and you want to
|
||||
// set the name of a field, use QPDFAcroFormDocumentHelper::setFormFieldName instead.
|
||||
QPDF_DLL
|
||||
void setFieldAttribute(std::string const& key, QPDFObjectHandle value);
|
||||
|
||||
// Set an attribute to the given value as a Unicode string (UTF-16 BE encoded). The input string
|
||||
// should be UTF-8 encoded. If you have a QPDFAcroFormDocumentHelper and you want to set the
|
||||
// name of a field, use QPDFAcroFormDocumentHelper::setFormFieldName instead.
|
||||
QPDF_DLL
|
||||
void setFieldAttribute(std::string const& key, std::string const& utf8_value);
|
||||
|
||||
// Set /V (field value) to the given value. If need_appearances is true and the field type is
|
||||
// either /Tx (text) or /Ch (choice), set /NeedAppearances to true. You can explicitly tell this
|
||||
// method not to set /NeedAppearances if you are going to generate an appearance stream
|
||||
// yourself. Starting with qpdf 8.3.0, this method handles fields of type /Btn (checkboxes,
|
||||
// radio buttons, pushbuttons) specially. When setting a checkbox value, any value other than
|
||||
// /Off will be treated as on, and the actual value set will be based on the appearance stream's
|
||||
// /N dictionary, so the value that ends up in /V may not exactly match the value you pass in.
|
||||
QPDF_DLL
|
||||
void setV(QPDFObjectHandle value, bool need_appearances = true);
|
||||
|
||||
// Set /V (field value) to the given string value encoded as a Unicode string. The input value
|
||||
// should be UTF-8 encoded. See comments above about /NeedAppearances.
|
||||
QPDF_DLL
|
||||
void setV(std::string const& utf8_value, bool need_appearances = true);
|
||||
|
||||
// Update the appearance stream for this field. Note that qpdf's ability to generate appearance
|
||||
// streams is limited. We only generate appearance streams for streams of type text or choice.
|
||||
// The appearance uses the default parameters provided in the file, and it only supports ASCII
|
||||
// characters. Quadding is currently ignored. While this functionality is limited, it should do
|
||||
// a decent job on properly constructed PDF files when field values are restricted to ASCII
|
||||
// characters.
|
||||
QPDF_DLL
|
||||
void generateAppearance(QPDFAnnotationObjectHelper&);
|
||||
|
||||
private:
|
||||
class Members;
|
||||
|
||||
std::shared_ptr<Members> m;
|
||||
};
|
||||
|
||||
#endif // QPDFFORMFIELDOBJECTHELPER_HH
|
||||
@@ -0,0 +1,542 @@
|
||||
// Copyright (c) 2005-2021 Jay Berkenbilt
|
||||
// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger
|
||||
//
|
||||
// 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 QPDFJOB_HH
|
||||
#define QPDFJOB_HH
|
||||
|
||||
#include <qpdf/Constants.h>
|
||||
#include <qpdf/DLL.h>
|
||||
#include <qpdf/PDFVersion.hh>
|
||||
#include <qpdf/QPDF.hh>
|
||||
#include <qpdf/QPDFOutlineObjectHelper.hh>
|
||||
#include <qpdf/QPDFPageObjectHelper.hh>
|
||||
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class QPDFWriter;
|
||||
class Pipeline;
|
||||
class QPDFLogger;
|
||||
|
||||
class QPDFJob
|
||||
{
|
||||
public:
|
||||
static int constexpr LATEST_JOB_JSON = 1;
|
||||
|
||||
// Exit codes -- returned by getExitCode() after calling run()
|
||||
static int constexpr EXIT_ERROR = qpdf_exit_error;
|
||||
static int constexpr EXIT_WARNING = qpdf_exit_warning;
|
||||
// For is-encrypted and requires-password
|
||||
static int constexpr EXIT_IS_NOT_ENCRYPTED = qpdf_exit_is_not_encrypted;
|
||||
static int constexpr EXIT_CORRECT_PASSWORD = qpdf_exit_correct_password;
|
||||
|
||||
// QPDFUsage is thrown if there are any usage-like errors when calling Config methods.
|
||||
QPDF_DLL
|
||||
QPDFJob();
|
||||
|
||||
// SETUP FUNCTIONS
|
||||
|
||||
// Initialize a QPDFJob object from argv, which must be a null-terminated array of
|
||||
// null-terminated UTF-8-encoded C strings. The progname_env argument is the name of an
|
||||
// environment variable which, if set, overrides the name of the executable for purposes of
|
||||
// generating the --completion options. See QPDFArgParser for details. If a null pointer is
|
||||
// passed in, the default value of "QPDF_EXECUTABLE" is used. This is used by the QPDF cli,
|
||||
// which just initializes a QPDFJob from argv, calls run(), and handles errors and exit status
|
||||
// issues. You can perform much of the cli functionality programmatically in this way rather
|
||||
// than using the regular API. This is exposed in the C API, which makes it easier to get
|
||||
// certain high-level qpdf functionality from other languages. If there are any command-line
|
||||
// errors, this method will throw QPDFUsage which is derived from std::runtime_error. Other
|
||||
// exceptions may be thrown in some cases. Note that argc, and argv should be UTF-8 encoded. If
|
||||
// you are calling this from a Windows Unicode-aware main (wmain), see
|
||||
// QUtil::call_main_from_wmain for information about converting arguments to UTF-8. This method
|
||||
// will mutate arguments that are passed to it.
|
||||
QPDF_DLL
|
||||
void initializeFromArgv(char const* const argv[], char const* progname_env = nullptr);
|
||||
|
||||
// Initialize a QPDFJob from json. Passing partial = true prevents this method from doing the
|
||||
// final checks (calling checkConfiguration) after processing the json file. This makes it
|
||||
// possible to initialize QPDFJob in stages using multiple json files or to have a json file
|
||||
// that can be processed from the CLI with --job-json-file and be combined with other arguments.
|
||||
// For example, you might include only encryption parameters, leaving it up to the rest of the
|
||||
// command-line arguments to provide input and output files. initializeFromJson is called with
|
||||
// partial = true when invoked from the command line. To make sure that the json file is fully
|
||||
// valid on its own, just don't specify any other command-line flags. If there are any
|
||||
// configuration errors, QPDFUsage is thrown. Some error messages may be CLI-centric. If an
|
||||
// exception tells you to use the "--some-option" option, set the "someOption" key in the JSON
|
||||
// object instead.
|
||||
QPDF_DLL
|
||||
void initializeFromJson(std::string const& json, bool partial = false);
|
||||
|
||||
// Set name that is used to prefix verbose messages, progress messages, and other things that
|
||||
// the library writes to output and error streams on the caller's behalf. Defaults to "qpdf".
|
||||
QPDF_DLL
|
||||
void setMessagePrefix(std::string const&);
|
||||
QPDF_DLL
|
||||
std::string getMessagePrefix() const;
|
||||
|
||||
// To capture or redirect output, configure the logger returned by getLogger(). By default, all
|
||||
// QPDF and QPDFJob objects share the global logger. If you need a private logger for some
|
||||
// reason, pass a new one to setLogger(). See comments in QPDFLogger.hh for details on
|
||||
// configuring the logger.
|
||||
//
|
||||
// If you set a custom logger here, the logger will be passed to all subsequent QPDF objects
|
||||
// created by this QPDFJob object.
|
||||
QPDF_DLL
|
||||
std::shared_ptr<QPDFLogger> getLogger();
|
||||
QPDF_DLL
|
||||
void setLogger(std::shared_ptr<QPDFLogger>);
|
||||
|
||||
// This deprecated method is the old way to capture output, but it didn't capture all output.
|
||||
// See comments above for getLogger and setLogger. This will be removed in QPDF 12. For now, it
|
||||
// configures a private logger, separating this object from the default logger, and calls
|
||||
// setOutputStreams on that logger. See QPDFLogger.hh for additional details.
|
||||
[[deprecated("configure logger from getLogger() or call setLogger()")]] QPDF_DLL void
|
||||
setOutputStreams(std::ostream* out_stream, std::ostream* err_stream);
|
||||
|
||||
// You can register a custom progress reporter to be called by QPDFWriter (see
|
||||
// QPDFWriter::registerProgressReporter). This is only called if you also request progress
|
||||
// reporting through normal configuration methods (e.g., pass --progress, call
|
||||
// config()->progress, etc.)
|
||||
QPDF_DLL
|
||||
void registerProgressReporter(std::function<void(int)>);
|
||||
|
||||
// Check to make sure no contradictory options have been specified. This is called automatically
|
||||
// after initializing from argv or json and is also called by run, but you can call it manually
|
||||
// as well. It throws a QPDFUsage exception if there are any errors. This Config object (see
|
||||
// CONFIGURATION) also has a checkConfiguration method which calls this one.
|
||||
QPDF_DLL
|
||||
void checkConfiguration();
|
||||
|
||||
// Returns true if output is created by the specified job.
|
||||
QPDF_DLL
|
||||
bool createsOutput() const;
|
||||
|
||||
// SEE BELOW FOR MORE PUBLIC METHODS AND CLASSES
|
||||
private:
|
||||
// These structures are private but we need to define them before the public Config classes.
|
||||
struct CopyAttachmentFrom
|
||||
{
|
||||
std::string path;
|
||||
std::string password;
|
||||
std::string prefix;
|
||||
};
|
||||
|
||||
struct AddAttachment
|
||||
{
|
||||
std::string path;
|
||||
std::string key;
|
||||
std::string filename;
|
||||
std::string creationdate;
|
||||
std::string moddate;
|
||||
std::string mimetype;
|
||||
std::string description;
|
||||
bool replace{false};
|
||||
};
|
||||
|
||||
public:
|
||||
// CONFIGURATION
|
||||
|
||||
// Configuration classes are implemented in QPDFJob_config.cc.
|
||||
|
||||
// The config() method returns a shared pointer to a Config object. The Config object contains
|
||||
// methods that correspond with qpdf command-line arguments. You can use a fluent interface to
|
||||
// configure a QPDFJob object that would do exactly the same thing as a specific qpdf command.
|
||||
// The example qpdf-job.cc contains an example of this usage. You can also use
|
||||
// initializeFromJson or initializeFromArgv to initialize a QPDFJob object.
|
||||
|
||||
// Notes about the Config methods:
|
||||
//
|
||||
// * Most of the method declarations are automatically generated in header files that are
|
||||
// included within the class definitions. They correspond in predictable ways to the
|
||||
// command-line arguments and are generated from the same code that generates the command-line
|
||||
// argument parsing code.
|
||||
//
|
||||
// * Methods return pointers, rather than references, to configuration objects. References
|
||||
// might feel more familiar to users of fluent interfaces, so why do we use pointers? The
|
||||
// main methods that create them return smart pointers so that users can initialize them when
|
||||
// needed, which you can't do with references. Returning pointers instead of references makes
|
||||
// for a more uniform interface.
|
||||
|
||||
// Maintainer documentation: see the section in README-maintainer called "HOW TO ADD A
|
||||
// COMMAND-LINE ARGUMENT", which contains references to additional places in the documentation.
|
||||
|
||||
class Config;
|
||||
|
||||
class AttConfig
|
||||
{
|
||||
friend class QPDFJob;
|
||||
friend class Config;
|
||||
|
||||
public:
|
||||
QPDF_DLL
|
||||
Config* endAddAttachment();
|
||||
QPDF_DLL
|
||||
AttConfig* file(std::string const& parameter);
|
||||
|
||||
#include <qpdf/auto_job_c_att.hh>
|
||||
|
||||
private:
|
||||
AttConfig(Config*);
|
||||
AttConfig(AttConfig const&) = delete;
|
||||
|
||||
Config* config;
|
||||
AddAttachment att;
|
||||
};
|
||||
|
||||
class CopyAttConfig
|
||||
{
|
||||
friend class QPDFJob;
|
||||
friend class Config;
|
||||
|
||||
public:
|
||||
QPDF_DLL
|
||||
Config* endCopyAttachmentsFrom();
|
||||
QPDF_DLL
|
||||
CopyAttConfig* file(std::string const& parameter);
|
||||
|
||||
#include <qpdf/auto_job_c_copy_att.hh>
|
||||
|
||||
private:
|
||||
CopyAttConfig(Config*);
|
||||
CopyAttConfig(CopyAttConfig const&) = delete;
|
||||
|
||||
Config* config;
|
||||
CopyAttachmentFrom caf;
|
||||
};
|
||||
|
||||
class PagesConfig
|
||||
{
|
||||
friend class QPDFJob;
|
||||
friend class Config;
|
||||
|
||||
public:
|
||||
QPDF_DLL
|
||||
Config* endPages();
|
||||
// From qpdf 11.9.0, you can call file(), range(), and password(). Each call to file()
|
||||
// starts a new page spec.
|
||||
QPDF_DLL
|
||||
PagesConfig* pageSpec(
|
||||
std::string const& filename, std::string const& range, char const* password = nullptr);
|
||||
|
||||
#include <qpdf/auto_job_c_pages.hh>
|
||||
|
||||
private:
|
||||
PagesConfig(Config*);
|
||||
PagesConfig(PagesConfig const&) = delete;
|
||||
|
||||
Config* config;
|
||||
};
|
||||
|
||||
class UOConfig
|
||||
{
|
||||
friend class QPDFJob;
|
||||
friend class Config;
|
||||
|
||||
public:
|
||||
QPDF_DLL
|
||||
Config* endUnderlayOverlay();
|
||||
|
||||
#include <qpdf/auto_job_c_uo.hh>
|
||||
|
||||
private:
|
||||
UOConfig(Config*);
|
||||
UOConfig(UOConfig const&) = delete;
|
||||
|
||||
Config* config;
|
||||
};
|
||||
|
||||
class EncConfig
|
||||
{
|
||||
friend class QPDFJob;
|
||||
friend class Config;
|
||||
|
||||
public:
|
||||
QPDF_DLL
|
||||
Config* endEncrypt();
|
||||
QPDF_DLL
|
||||
EncConfig* file(std::string const& parameter);
|
||||
|
||||
#include <qpdf/auto_job_c_enc.hh>
|
||||
|
||||
private:
|
||||
EncConfig(Config*);
|
||||
EncConfig(EncConfig const&) = delete;
|
||||
|
||||
Config* config;
|
||||
};
|
||||
|
||||
class PageLabelsConfig
|
||||
{
|
||||
friend class QPDFJob;
|
||||
friend class Config;
|
||||
|
||||
public:
|
||||
QPDF_DLL
|
||||
Config* endSetPageLabels();
|
||||
|
||||
#include <qpdf/auto_job_c_set_page_labels.hh>
|
||||
|
||||
private:
|
||||
PageLabelsConfig(Config*);
|
||||
PageLabelsConfig(PageLabelsConfig const&) = delete;
|
||||
|
||||
Config* config;
|
||||
};
|
||||
|
||||
class GlobalConfig
|
||||
{
|
||||
friend class QPDFJob;
|
||||
friend class Config;
|
||||
|
||||
public:
|
||||
QPDF_DLL
|
||||
Config* endGlobal();
|
||||
|
||||
#include <qpdf/auto_job_c_global.hh>
|
||||
|
||||
GlobalConfig(Config*); // for qpdf internal use only
|
||||
GlobalConfig(GlobalConfig const&) = delete;
|
||||
|
||||
private:
|
||||
Config* config;
|
||||
};
|
||||
|
||||
class Config
|
||||
{
|
||||
friend class QPDFJob;
|
||||
|
||||
public:
|
||||
// Proxy to QPDFJob::checkConfiguration()
|
||||
QPDF_DLL
|
||||
void checkConfiguration();
|
||||
|
||||
QPDF_DLL
|
||||
Config* inputFile(std::string const& filename);
|
||||
QPDF_DLL
|
||||
Config* emptyInput();
|
||||
QPDF_DLL
|
||||
Config* outputFile(std::string const& filename);
|
||||
QPDF_DLL
|
||||
Config* replaceInput();
|
||||
QPDF_DLL
|
||||
Config* setPageLabels(std::vector<std::string> const& specs);
|
||||
|
||||
QPDF_DLL
|
||||
std::shared_ptr<CopyAttConfig> copyAttachmentsFrom();
|
||||
QPDF_DLL
|
||||
std::shared_ptr<AttConfig> addAttachment();
|
||||
QPDF_DLL
|
||||
std::shared_ptr<GlobalConfig> global();
|
||||
QPDF_DLL
|
||||
std::shared_ptr<PagesConfig> pages();
|
||||
QPDF_DLL
|
||||
std::shared_ptr<UOConfig> overlay();
|
||||
QPDF_DLL
|
||||
std::shared_ptr<UOConfig> underlay();
|
||||
QPDF_DLL
|
||||
std::shared_ptr<EncConfig>
|
||||
encrypt(int keylen, std::string const& user_password, std::string const& owner_password);
|
||||
|
||||
#include <qpdf/auto_job_c_main.hh>
|
||||
|
||||
private:
|
||||
Config() = delete;
|
||||
Config(Config const&) = delete;
|
||||
Config(QPDFJob& job) :
|
||||
o(job)
|
||||
{
|
||||
}
|
||||
QPDFJob& o;
|
||||
};
|
||||
|
||||
// Return a top-level configuration item. See CONFIGURATION above for details. If an invalid
|
||||
// configuration is created (such as supplying contradictory options, omitting an input file,
|
||||
// etc.), QPDFUsage is thrown. Note that error messages are CLI-centric, but you can map them
|
||||
// into config calls. For example, if an exception tells you to use the --some-option flag, you
|
||||
// should call config()->someOption() instead.
|
||||
QPDF_DLL
|
||||
std::shared_ptr<Config> config();
|
||||
|
||||
// Execute the job
|
||||
QPDF_DLL
|
||||
void run();
|
||||
|
||||
// The following two methods allow a job to be run in two stages - creation of a QPDF object and
|
||||
// writing of the QPDF object. This allows the QPDF object to be modified prior to writing it
|
||||
// out. See examples/qpdfjob-remove-annotations for an illustration of its use.
|
||||
|
||||
// Run the first stage of the job. Return a nullptr if the configuration is not valid.
|
||||
QPDF_DLL
|
||||
std::unique_ptr<QPDF> createQPDF();
|
||||
|
||||
// Run the second stage of the job. Do nothing if a nullptr is passed as parameter.
|
||||
QPDF_DLL
|
||||
void writeQPDF(QPDF& qpdf);
|
||||
|
||||
// CHECK STATUS -- these methods provide information known after run() is called.
|
||||
|
||||
QPDF_DLL
|
||||
bool hasWarnings() const;
|
||||
|
||||
// Return one of the EXIT_* constants defined at the top of the class declaration. This may be
|
||||
// called after run() when run() did not throw an exception. Takes into consideration whether
|
||||
// isEncrypted or requiresPassword was called. Note that this function does not know whether
|
||||
// run() threw an exception, so code that uses this to determine how to exit should explicitly
|
||||
// use EXIT_ERROR if run() threw an exception.
|
||||
QPDF_DLL
|
||||
int getExitCode() const;
|
||||
|
||||
// Return value is bitwise OR of values from qpdf_encryption_status_e
|
||||
QPDF_DLL
|
||||
unsigned long getEncryptionStatus();
|
||||
|
||||
// HELPER FUNCTIONS -- methods useful for calling in handlers that interact with QPDFJob during
|
||||
// run or initialization.
|
||||
|
||||
// If in verbose mode, call the given function, passing in the output stream and message prefix.
|
||||
QPDF_DLL
|
||||
void doIfVerbose(std::function<void(Pipeline&, std::string const& prefix)> fn);
|
||||
|
||||
// Provide a string that is the help information ("schema" for the qpdf-specific JSON object)
|
||||
// for the specified version of JSON output.
|
||||
QPDF_DLL
|
||||
static std::string json_out_schema(int version);
|
||||
|
||||
[[deprecated("use json_out_schema(version)")]] static std::string QPDF_DLL json_out_schema_v1();
|
||||
|
||||
// Provide a string that is the help information for specified version of JSON format for
|
||||
// QPDFJob.
|
||||
QPDF_DLL
|
||||
static std::string job_json_schema(int version);
|
||||
|
||||
[[deprecated("use job_json_schema(version)")]] static std::string QPDF_DLL job_json_schema_v1();
|
||||
|
||||
private:
|
||||
struct PageNo;
|
||||
struct Selection;
|
||||
struct Input;
|
||||
struct Inputs;
|
||||
struct RotationSpec;
|
||||
struct UnderOverlay;
|
||||
struct PageLabelSpec;
|
||||
|
||||
enum password_mode_e { pm_bytes, pm_hex_bytes, pm_unicode, pm_auto };
|
||||
|
||||
// Helper functions
|
||||
static void usage(std::string const& msg);
|
||||
static JSON json_schema(int json_version, std::set<std::string>* keys = nullptr);
|
||||
static void parse_object_id(std::string const& objspec, bool& trailer, int& obj, int& gen);
|
||||
void parseRotationParameter(std::string const&);
|
||||
std::vector<int> parseNumrange(char const* range, int max);
|
||||
|
||||
// Basic file processing
|
||||
void processFile(
|
||||
std::unique_ptr<QPDF>&,
|
||||
char const* filename,
|
||||
char const* password,
|
||||
bool used_for_input,
|
||||
bool main_input);
|
||||
void processInputSource(
|
||||
std::unique_ptr<QPDF>&,
|
||||
std::shared_ptr<InputSource> is,
|
||||
char const* password,
|
||||
bool used_for_input);
|
||||
void doProcess(
|
||||
std::unique_ptr<QPDF>&,
|
||||
std::function<void(QPDF*, char const*)> fn,
|
||||
char const* password,
|
||||
bool empty,
|
||||
bool used_for_input,
|
||||
bool main_input);
|
||||
void doProcessOnce(
|
||||
std::unique_ptr<QPDF>&,
|
||||
std::function<void(QPDF*, char const*)> fn,
|
||||
char const* password,
|
||||
bool empty,
|
||||
bool used_for_input,
|
||||
bool main_input);
|
||||
|
||||
// Transformations
|
||||
void handlePageSpecs(QPDF& pdf);
|
||||
bool shouldRemoveUnreferencedResources(QPDF& pdf);
|
||||
void handleRotations(QPDF& pdf);
|
||||
void getUOPagenos(
|
||||
std::vector<UnderOverlay>& uo, std::vector<std::map<size_t, std::vector<int>>>& pagenos);
|
||||
void handleUnderOverlay(QPDF& pdf);
|
||||
std::string doUnderOverlayForPage(
|
||||
QPDF& pdf,
|
||||
UnderOverlay& uo,
|
||||
std::vector<std::map<size_t, std::vector<int>>>& pagenos,
|
||||
PageNo const& page_idx,
|
||||
size_t uo_idx,
|
||||
std::map<int, std::map<size_t, QPDFObjectHandle>>& fo,
|
||||
QPDFPageObjectHelper& dest_page);
|
||||
void validateUnderOverlay(QPDF& pdf, UnderOverlay* uo);
|
||||
void handleTransformations(QPDF& pdf);
|
||||
void addAttachments(QPDF& pdf);
|
||||
void copyAttachments(QPDF& pdf);
|
||||
|
||||
// Inspection
|
||||
void doInspection(QPDF& pdf);
|
||||
void doCheck(QPDF& pdf);
|
||||
void showEncryption(QPDF& pdf);
|
||||
void doShowObj(QPDF& pdf);
|
||||
void doShowPages(QPDF& pdf);
|
||||
void doListAttachments(QPDF& pdf);
|
||||
void doShowAttachment(QPDF& pdf);
|
||||
|
||||
// Output generation
|
||||
void doSplitPages(QPDF& pdf);
|
||||
void setWriterOptions(qpdf::Writer&);
|
||||
void setEncryptionOptions(QPDFWriter&);
|
||||
void maybeFixWritePassword(int R, std::string& password);
|
||||
void writeOutfile(QPDF& pdf);
|
||||
void writeJSON(QPDF& pdf);
|
||||
|
||||
// JSON
|
||||
void doJSON(QPDF& pdf, Pipeline*);
|
||||
QPDFObjGen::set getWantedJSONObjects();
|
||||
void doJSONObjects(Pipeline* p, bool& first, QPDF& pdf);
|
||||
void doJSONObjectinfo(Pipeline* p, bool& first, QPDF& pdf);
|
||||
void doJSONPages(Pipeline* p, bool& first, QPDF& pdf);
|
||||
void doJSONPageLabels(Pipeline* p, bool& first, QPDF& pdf);
|
||||
void doJSONOutlines(Pipeline* p, bool& first, QPDF& pdf);
|
||||
void doJSONAcroform(Pipeline* p, bool& first, QPDF& pdf);
|
||||
void doJSONEncrypt(Pipeline* p, bool& first, QPDF& pdf);
|
||||
void doJSONAttachments(Pipeline* p, bool& first, QPDF& pdf);
|
||||
void addOutlinesToJson(
|
||||
std::vector<QPDFOutlineObjectHelper> outlines,
|
||||
JSON& j,
|
||||
std::map<QPDFObjGen, int>& page_numbers);
|
||||
|
||||
enum remove_unref_e { re_auto, re_yes, re_no };
|
||||
|
||||
class Members;
|
||||
|
||||
std::shared_ptr<Members> m;
|
||||
};
|
||||
|
||||
#endif // QPDFOBJECT_HH
|
||||
+164
@@ -0,0 +1,164 @@
|
||||
// Copyright (c) 2005-2021 Jay Berkenbilt
|
||||
// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger
|
||||
//
|
||||
// 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 QPDFLOGGER_HH
|
||||
#define QPDFLOGGER_HH
|
||||
|
||||
#include <qpdf/DLL.h>
|
||||
#include <qpdf/Pipeline.hh>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
|
||||
class QPDFLogger
|
||||
{
|
||||
public:
|
||||
QPDF_DLL
|
||||
static std::shared_ptr<QPDFLogger> create();
|
||||
|
||||
// Return the default logger. In general, you should use the default logger. You can also create
|
||||
// your own loggers and use them with QPDF and QPDFJob objects, but there are few reasons to do
|
||||
// so. One reason may be that you are using multiple QPDF or QPDFJob objects in different
|
||||
// threads and want to capture output and errors to different streams. (Note that a single QPDF
|
||||
// or QPDFJob can't be safely used from multiple threads, but it is safe to use separate QPDF
|
||||
// and QPDFJob objects on separate threads.) Another possible reason would be if you are writing
|
||||
// an application that uses the qpdf library directly and qpdf is also used by a downstream
|
||||
// library or if you are using qpdf from a library and don't want to interfere with potential
|
||||
// uses of qpdf by other libraries or applications.
|
||||
QPDF_DLL
|
||||
static std::shared_ptr<QPDFLogger> defaultLogger();
|
||||
|
||||
// Defaults:
|
||||
//
|
||||
// info -- if save is standard output, standard error, else standard output
|
||||
// warn -- whatever error points to
|
||||
// error -- standard error
|
||||
// save -- undefined unless set
|
||||
//
|
||||
// "info" is used for diagnostic messages, verbose messages, and progress messages. "warn" is
|
||||
// used for warnings. "error" is used for errors. "save" is used for saving output -- see below.
|
||||
//
|
||||
// On deletion, finish() is called for the standard output and standard error pipelines, which
|
||||
// flushes output. If you supply any custom pipelines, you must call finish() on them yourself.
|
||||
// Note that calling finish is not needed for string, stdio, or ostream pipelines.
|
||||
//
|
||||
// NOTES ABOUT THE SAVE PIPELINE
|
||||
//
|
||||
// The save pipeline is used by QPDFJob when some kind of binary output is being saved. This
|
||||
// includes saving attachments and stream data and also includes when the output file is
|
||||
// standard output. If you want to grab that output, you can call setSave. See
|
||||
// examples/qpdfjob-save-attachment.cc and examples/qpdfjob-c-save-attachment.c.
|
||||
//
|
||||
// You should never set the save pipeline to the same destination as something else. Doing so
|
||||
// will corrupt your save output. If you want to save to standard output, use the method
|
||||
// saveToStandardOutput(). In addition to setting the save pipeline, that does the following
|
||||
// extra things:
|
||||
//
|
||||
// * If standard output has been used, a logic error is thrown
|
||||
// * If info is set to standard output at the time of the set save call, it is switched to
|
||||
// standard error.
|
||||
//
|
||||
// This is not a guarantee. You can still mess this up in ways that are not checked. Here are a
|
||||
// few examples:
|
||||
//
|
||||
// * Don't set any pipeline to standard output *after* passing it to setSave()
|
||||
// * Don't use a separate mechanism to write stdout/stderr other than
|
||||
// QPDFLogger::standardOutput()
|
||||
// * Don't set anything to the same custom pipeline that save is set to.
|
||||
//
|
||||
// Just be sure that if you change pipelines around, you should avoid having the save pipeline
|
||||
// also be used for any other purpose. The special case for saving to standard output allows you
|
||||
// to call saveToStandardOutput() early without having to worry about the info pipeline.
|
||||
|
||||
QPDF_DLL
|
||||
void info(char const*);
|
||||
QPDF_DLL
|
||||
void info(std::string const&);
|
||||
QPDF_DLL
|
||||
std::shared_ptr<Pipeline> getInfo(bool null_okay = false);
|
||||
|
||||
QPDF_DLL
|
||||
void warn(char const*);
|
||||
QPDF_DLL
|
||||
void warn(std::string const&);
|
||||
QPDF_DLL
|
||||
std::shared_ptr<Pipeline> getWarn(bool null_okay = false);
|
||||
|
||||
QPDF_DLL
|
||||
void error(char const*);
|
||||
QPDF_DLL
|
||||
void error(std::string const&);
|
||||
QPDF_DLL
|
||||
std::shared_ptr<Pipeline> getError(bool null_okay = false);
|
||||
|
||||
QPDF_DLL
|
||||
std::shared_ptr<Pipeline> getSave(bool null_okay = false);
|
||||
|
||||
QPDF_DLL
|
||||
std::shared_ptr<Pipeline> standardOutput();
|
||||
QPDF_DLL
|
||||
std::shared_ptr<Pipeline> standardError();
|
||||
QPDF_DLL
|
||||
std::shared_ptr<Pipeline> discard();
|
||||
|
||||
// Passing a null pointer resets to default
|
||||
QPDF_DLL
|
||||
void setInfo(std::shared_ptr<Pipeline>);
|
||||
QPDF_DLL
|
||||
void setWarn(std::shared_ptr<Pipeline>);
|
||||
QPDF_DLL
|
||||
void setError(std::shared_ptr<Pipeline>);
|
||||
// See notes above about the save pipeline
|
||||
QPDF_DLL
|
||||
void setSave(std::shared_ptr<Pipeline>, bool only_if_not_set);
|
||||
QPDF_DLL
|
||||
void saveToStandardOutput(bool only_if_not_set);
|
||||
|
||||
// Shortcut for logic to reset output to new output/error streams. out_stream is used for info,
|
||||
// err_stream is used for error, and warning is cleared so that it follows error.
|
||||
QPDF_DLL
|
||||
void setOutputStreams(std::ostream* out_stream, std::ostream* err_stream);
|
||||
|
||||
private:
|
||||
QPDFLogger();
|
||||
std::shared_ptr<Pipeline> throwIfNull(std::shared_ptr<Pipeline>, bool null_okay);
|
||||
|
||||
class Members
|
||||
{
|
||||
friend class QPDFLogger;
|
||||
|
||||
public:
|
||||
~Members();
|
||||
|
||||
private:
|
||||
Members();
|
||||
Members(Members const&) = delete;
|
||||
|
||||
std::shared_ptr<Pipeline> p_discard;
|
||||
std::shared_ptr<Pipeline> p_real_stdout;
|
||||
std::shared_ptr<Pipeline> p_stdout;
|
||||
std::shared_ptr<Pipeline> p_stderr;
|
||||
std::shared_ptr<Pipeline> p_info;
|
||||
std::shared_ptr<Pipeline> p_warn;
|
||||
std::shared_ptr<Pipeline> p_error;
|
||||
std::shared_ptr<Pipeline> p_save;
|
||||
};
|
||||
std::shared_ptr<Members> m;
|
||||
};
|
||||
|
||||
#endif // QPDFLOGGER_HH
|
||||
+93
@@ -0,0 +1,93 @@
|
||||
// Copyright (c) 2005-2021 Jay Berkenbilt
|
||||
// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger
|
||||
//
|
||||
// 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 QPDFMATRIX_HH
|
||||
#define QPDFMATRIX_HH
|
||||
|
||||
#include <qpdf/DLL.h>
|
||||
#include <qpdf/QPDFObjectHandle.hh>
|
||||
#include <string>
|
||||
|
||||
// This class represents a PDF transformation matrix using a tuple such that
|
||||
//
|
||||
// ┌ ┐
|
||||
// │ a b 0 │
|
||||
// (a, b, c, d, e, f) = │ c d 0 │
|
||||
// │ e f 1 │
|
||||
// └ ┘
|
||||
class QPDFMatrix
|
||||
{
|
||||
public:
|
||||
QPDF_DLL
|
||||
QPDFMatrix();
|
||||
QPDF_DLL
|
||||
QPDFMatrix(double a, double b, double c, double d, double e, double f);
|
||||
QPDF_DLL
|
||||
QPDFMatrix(QPDFObjectHandle::Matrix const&);
|
||||
|
||||
// Returns the six values separated by spaces as real numbers with trimmed zeroes.
|
||||
QPDF_DLL
|
||||
std::string unparse() const;
|
||||
|
||||
QPDF_DLL
|
||||
QPDFObjectHandle::Matrix getAsMatrix() const;
|
||||
|
||||
// Replace this with other * this
|
||||
QPDF_DLL
|
||||
void concat(QPDFMatrix const& other);
|
||||
|
||||
// Same as concat(sx, 0, 0, sy, 0, 0)
|
||||
QPDF_DLL
|
||||
void scale(double sx, double sy);
|
||||
|
||||
// Same as concat(1, 0, 0, 1, tx, ty);
|
||||
QPDF_DLL
|
||||
void translate(double tx, double ty);
|
||||
|
||||
// Any value other than 90, 180, or 270 is ignored
|
||||
QPDF_DLL
|
||||
void rotatex90(int angle);
|
||||
|
||||
// Transform a point. The underlying operation is to take
|
||||
// [x y 1] * this
|
||||
// and take the first and second rows of the result as xp and yp.
|
||||
QPDF_DLL
|
||||
void transform(double x, double y, double& xp, double& yp) const;
|
||||
|
||||
// Transform a rectangle by creating a new rectangle that tightly bounds the polygon resulting
|
||||
// from transforming the four corners.
|
||||
QPDF_DLL
|
||||
QPDFObjectHandle::Rectangle transformRectangle(QPDFObjectHandle::Rectangle r) const;
|
||||
|
||||
// operator== tests for exact equality, not considering deltas for floating point.
|
||||
QPDF_DLL
|
||||
bool operator==(QPDFMatrix const& rhs) const;
|
||||
|
||||
QPDF_DLL
|
||||
bool operator!=(QPDFMatrix const& rhs) const;
|
||||
|
||||
double a;
|
||||
double b;
|
||||
double c;
|
||||
double d;
|
||||
double e;
|
||||
double f;
|
||||
};
|
||||
|
||||
#endif // QPDFMATRIX_HH
|
||||
Vendored
+184
@@ -0,0 +1,184 @@
|
||||
// Copyright (c) 2005-2021 Jay Berkenbilt
|
||||
// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger
|
||||
//
|
||||
// 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 QPDFNAMETREEOBJECTHELPER_HH
|
||||
#define QPDFNAMETREEOBJECTHELPER_HH
|
||||
|
||||
#include <qpdf/QPDFObjGen.hh>
|
||||
#include <qpdf/QPDFObjectHelper.hh>
|
||||
#include <iterator>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
|
||||
#include <qpdf/DLL.h>
|
||||
|
||||
class NNTreeImpl;
|
||||
class NNTreeIterator;
|
||||
class NNTreeDetails;
|
||||
|
||||
// This is an object helper for name trees. See section 7.9.6 in the PDF spec (ISO 32000) for a
|
||||
// description of name trees. When looking up items in the name tree, use UTF-8 strings. All names
|
||||
// are normalized for lookup purposes.
|
||||
//
|
||||
// See examples/pdf-name-number-tree.cc for a demonstration of using QPDFNameTreeObjectHelper.
|
||||
class QPDF_DLL_CLASS QPDFNameTreeObjectHelper: public QPDFObjectHelper
|
||||
{
|
||||
public:
|
||||
// The qpdf object is required so that this class can issue warnings, attempt repairs, and add
|
||||
// indirect objects.
|
||||
QPDF_DLL
|
||||
QPDFNameTreeObjectHelper(QPDFObjectHandle, QPDF&, bool auto_repair = true);
|
||||
|
||||
QPDF_DLL
|
||||
QPDFNameTreeObjectHelper(
|
||||
QPDFObjectHandle,
|
||||
QPDF&,
|
||||
std::function<bool(QPDFObjectHandle const&)> value_validator,
|
||||
bool auto_repair);
|
||||
|
||||
// Validate the name tree. Returns true if the tree is valid.
|
||||
//
|
||||
// If the tree is not valid and auto_repair is true, attempt to repair the tree.
|
||||
QPDF_DLL
|
||||
bool validate(bool repair = true);
|
||||
|
||||
// Create an empty name tree
|
||||
QPDF_DLL
|
||||
static QPDFNameTreeObjectHelper newEmpty(QPDF&, bool auto_repair = true);
|
||||
|
||||
QPDF_DLL
|
||||
~QPDFNameTreeObjectHelper() override;
|
||||
|
||||
// Return whether the name tree has an explicit entry for this name.
|
||||
QPDF_DLL
|
||||
bool hasName(std::string const& utf8);
|
||||
|
||||
// Find an object by name. If found, returns true and initializes oh. See also find().
|
||||
QPDF_DLL
|
||||
bool findObject(std::string const& utf8, QPDFObjectHandle& oh);
|
||||
|
||||
class QPDF_DLL_PRIVATE iterator
|
||||
{
|
||||
friend class QPDFNameTreeObjectHelper;
|
||||
|
||||
public:
|
||||
typedef std::pair<std::string, QPDFObjectHandle> T;
|
||||
using iterator_category = std::bidirectional_iterator_tag;
|
||||
using value_type = T;
|
||||
using difference_type = long;
|
||||
using pointer = T*;
|
||||
using reference = T&;
|
||||
|
||||
virtual ~iterator() = default;
|
||||
QPDF_DLL
|
||||
bool valid() const;
|
||||
QPDF_DLL
|
||||
iterator& operator++();
|
||||
iterator
|
||||
operator++(int)
|
||||
{
|
||||
iterator t = *this;
|
||||
++(*this);
|
||||
return t;
|
||||
}
|
||||
QPDF_DLL
|
||||
iterator& operator--();
|
||||
iterator
|
||||
operator--(int)
|
||||
{
|
||||
iterator t = *this;
|
||||
--(*this);
|
||||
return t;
|
||||
}
|
||||
QPDF_DLL
|
||||
reference operator*();
|
||||
QPDF_DLL
|
||||
pointer operator->();
|
||||
QPDF_DLL
|
||||
bool operator==(iterator const& other) const;
|
||||
bool
|
||||
operator!=(iterator const& other) const
|
||||
{
|
||||
return !operator==(other);
|
||||
}
|
||||
|
||||
// DANGER: this method can create inconsistent trees if not used properly! Insert a new item
|
||||
// immediately after the current iterator and increment so that it points to the new item.
|
||||
// If the current iterator is end(), insert at the beginning. This method does not check for
|
||||
// proper ordering, so if you use it, you must ensure that the item you are inserting
|
||||
// belongs where you are putting it. The reason for this method is that it is more efficient
|
||||
// than insert() and can be used safely when you are creating a new tree and inserting items
|
||||
// in sorted order.
|
||||
QPDF_DLL
|
||||
void insertAfter(std::string const& key, QPDFObjectHandle value);
|
||||
|
||||
// Remove the current item and advance the iterator to the next item.
|
||||
QPDF_DLL
|
||||
void remove();
|
||||
|
||||
private:
|
||||
void updateIValue();
|
||||
|
||||
iterator(std::shared_ptr<NNTreeIterator> const&);
|
||||
std::shared_ptr<NNTreeIterator> impl;
|
||||
value_type ivalue;
|
||||
};
|
||||
|
||||
// The iterator looks like map iterator, so i.first is a string and i.second is a
|
||||
// QPDFObjectHandle. Incrementing end() brings you to the first item. Decrementing end() brings
|
||||
// you to the last item.
|
||||
QPDF_DLL
|
||||
iterator begin() const;
|
||||
QPDF_DLL
|
||||
iterator end() const;
|
||||
// Return a bidirectional iterator that points to the last item.
|
||||
QPDF_DLL
|
||||
iterator last() const;
|
||||
|
||||
// Find the entry with the given key. If return_prev_if_not_found is true and the item is not
|
||||
// found, return the next lower item.
|
||||
QPDF_DLL
|
||||
iterator find(std::string const& key, bool return_prev_if_not_found = false);
|
||||
|
||||
// Insert a new item. If the key already exists, it is replaced.
|
||||
QPDF_DLL
|
||||
iterator insert(std::string const& key, QPDFObjectHandle value);
|
||||
|
||||
// Remove an item. Return true if the item was found and removed; otherwise return false. If
|
||||
// value is not nullptr, initialize it to the value that was removed.
|
||||
QPDF_DLL
|
||||
bool remove(std::string const& key, QPDFObjectHandle* value = nullptr);
|
||||
|
||||
// Return the contents of the name tree as a map. Note that name trees may be very large, so
|
||||
// this may use a lot of RAM. It is more efficient to use QPDFNameTreeObjectHelper's iterator.
|
||||
QPDF_DLL
|
||||
std::map<std::string, QPDFObjectHandle> getAsMap() const;
|
||||
|
||||
// Split a node if the number of items exceeds this value. There's no real reason to ever set
|
||||
// this except for testing.
|
||||
QPDF_DLL
|
||||
void setSplitThreshold(int);
|
||||
|
||||
private:
|
||||
class QPDF_DLL_PRIVATE Members;
|
||||
|
||||
std::shared_ptr<Members> m;
|
||||
};
|
||||
|
||||
#endif // QPDFNAMETREEOBJECTHELPER_HH
|
||||
Vendored
+200
@@ -0,0 +1,200 @@
|
||||
// Copyright (c) 2005-2021 Jay Berkenbilt
|
||||
// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger
|
||||
//
|
||||
// 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 QPDFNUMBERTREEOBJECTHELPER_HH
|
||||
#define QPDFNUMBERTREEOBJECTHELPER_HH
|
||||
|
||||
#include <qpdf/QPDFObjGen.hh>
|
||||
#include <qpdf/QPDFObjectHelper.hh>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
|
||||
#include <qpdf/DLL.h>
|
||||
|
||||
class NNTreeImpl;
|
||||
class NNTreeIterator;
|
||||
class NNTreeDetails;
|
||||
|
||||
// This is an object helper for number trees. See section 7.9.7 in the PDF spec (ISO 32000) for a
|
||||
// description of number trees.
|
||||
//
|
||||
// See examples/pdf-name-number-tree.cc for a demonstration of using QPDFNumberTreeObjectHelper.
|
||||
class QPDF_DLL_CLASS QPDFNumberTreeObjectHelper: public QPDFObjectHelper
|
||||
{
|
||||
public:
|
||||
// The qpdf object is required so that this class can issue warnings, attempt repairs, and add
|
||||
// indirect objects.
|
||||
QPDF_DLL
|
||||
QPDFNumberTreeObjectHelper(QPDFObjectHandle, QPDF&, bool auto_repair = true);
|
||||
|
||||
QPDF_DLL
|
||||
QPDFNumberTreeObjectHelper(
|
||||
QPDFObjectHandle,
|
||||
QPDF&,
|
||||
std::function<bool(QPDFObjectHandle const&)> value_validator,
|
||||
bool auto_repair);
|
||||
|
||||
QPDF_DLL
|
||||
~QPDFNumberTreeObjectHelper() override;
|
||||
|
||||
// Create an empty number tree
|
||||
QPDF_DLL
|
||||
static QPDFNumberTreeObjectHelper newEmpty(QPDF&, bool auto_repair = true);
|
||||
|
||||
typedef long long int numtree_number;
|
||||
|
||||
// Validate the name tree. Returns true if the tree is valid.
|
||||
//
|
||||
// If the tree is not valid and auto_repair is true, attempt to repair the tree.
|
||||
QPDF_DLL
|
||||
bool validate(bool repair = true);
|
||||
|
||||
// Return overall minimum and maximum indices
|
||||
QPDF_DLL
|
||||
numtree_number getMin();
|
||||
QPDF_DLL
|
||||
numtree_number getMax();
|
||||
|
||||
// Return whether the number tree has an explicit entry for this number.
|
||||
QPDF_DLL
|
||||
bool hasIndex(numtree_number idx);
|
||||
|
||||
// Find an object with a specific index. If found, returns true and initializes oh. See also
|
||||
// find().
|
||||
QPDF_DLL
|
||||
bool findObject(numtree_number idx, QPDFObjectHandle& oh);
|
||||
// Find the object at the index or, if not found, the object whose index is the highest index
|
||||
// less than the requested index. If the requested index is less than the minimum, return false.
|
||||
// Otherwise, return true, initialize oh to the object, and set offset to the difference between
|
||||
// the requested index and the actual index. For example, if a number tree has values for 3 and
|
||||
// 6 and idx is 5, this method would return true, initialize oh to the value with index 3, and
|
||||
// set offset to 2 (5 - 3). See also find().
|
||||
QPDF_DLL
|
||||
bool findObjectAtOrBelow(numtree_number idx, QPDFObjectHandle& oh, numtree_number& offset);
|
||||
|
||||
class QPDF_DLL_PRIVATE iterator
|
||||
{
|
||||
friend class QPDFNumberTreeObjectHelper;
|
||||
|
||||
public:
|
||||
typedef std::pair<numtree_number, QPDFObjectHandle> T;
|
||||
using iterator_category = std::bidirectional_iterator_tag;
|
||||
using value_type = T;
|
||||
using difference_type = long;
|
||||
using pointer = T*;
|
||||
using reference = T&;
|
||||
|
||||
virtual ~iterator() = default;
|
||||
QPDF_DLL
|
||||
bool valid() const;
|
||||
QPDF_DLL
|
||||
iterator& operator++();
|
||||
iterator
|
||||
operator++(int)
|
||||
{
|
||||
iterator t = *this;
|
||||
++(*this);
|
||||
return t;
|
||||
}
|
||||
QPDF_DLL
|
||||
iterator& operator--();
|
||||
iterator
|
||||
operator--(int)
|
||||
{
|
||||
iterator t = *this;
|
||||
--(*this);
|
||||
return t;
|
||||
}
|
||||
QPDF_DLL
|
||||
reference operator*();
|
||||
QPDF_DLL
|
||||
pointer operator->();
|
||||
QPDF_DLL
|
||||
bool operator==(iterator const& other) const;
|
||||
bool
|
||||
operator!=(iterator const& other) const
|
||||
{
|
||||
return !operator==(other);
|
||||
}
|
||||
|
||||
// DANGER: this method can create inconsistent trees if not used properly! Insert a new item
|
||||
// immediately after the current iterator and increment so that it points to the new item.
|
||||
// If the current iterator is end(), insert at the beginning. This method does not check for
|
||||
// proper ordering, so if you use it, you must ensure that the item you are inserting
|
||||
// belongs where you are putting it. The reason for this method is that it is more efficient
|
||||
// than insert() and can be used safely when you are creating a new tree and inserting items
|
||||
// in sorted order.
|
||||
QPDF_DLL
|
||||
void insertAfter(numtree_number key, QPDFObjectHandle value);
|
||||
|
||||
// Remove the current item and advance the iterator to the next item.
|
||||
QPDF_DLL
|
||||
void remove();
|
||||
|
||||
private:
|
||||
void updateIValue();
|
||||
|
||||
iterator(std::shared_ptr<NNTreeIterator> const&);
|
||||
std::shared_ptr<NNTreeIterator> impl;
|
||||
value_type ivalue;
|
||||
};
|
||||
|
||||
// The iterator looks like map iterator, so i.first is a numtree_number and i.second is a
|
||||
// QPDFObjectHandle. Incrementing end() brings you to the first item. Decrementing end() brings
|
||||
// you to the last item.
|
||||
QPDF_DLL
|
||||
iterator begin() const;
|
||||
QPDF_DLL
|
||||
iterator end() const;
|
||||
// Return a bidirectional iterator that points to the last item.
|
||||
QPDF_DLL
|
||||
iterator last() const;
|
||||
|
||||
// Find the entry with the given key. If return_prev_if_not_found is true and the item is not
|
||||
// found, return the next lower item.
|
||||
QPDF_DLL
|
||||
iterator find(numtree_number key, bool return_prev_if_not_found = false);
|
||||
|
||||
// Insert a new item. If the key already exists, it is replaced.
|
||||
QPDF_DLL
|
||||
iterator insert(numtree_number key, QPDFObjectHandle value);
|
||||
|
||||
// Remove an item. Return true if the item was found and removed; otherwise return false. If
|
||||
// value is not nullptr, initialize it to the value that was removed.
|
||||
QPDF_DLL
|
||||
bool remove(numtree_number key, QPDFObjectHandle* value = nullptr);
|
||||
|
||||
// Return the contents of the number tree as a map. Note that number trees may be very large, so
|
||||
// this may use a lot of RAM. It is more efficient to use QPDFNumberTreeObjectHelper's iterator.
|
||||
typedef std::map<numtree_number, QPDFObjectHandle> idx_map;
|
||||
QPDF_DLL
|
||||
idx_map getAsMap() const;
|
||||
|
||||
// Split a node if the number of items exceeds this value. There's no real reason to ever set
|
||||
// this except for testing.
|
||||
QPDF_DLL
|
||||
void setSplitThreshold(int);
|
||||
|
||||
private:
|
||||
class QPDF_DLL_PRIVATE Members;
|
||||
|
||||
std::shared_ptr<Members> m;
|
||||
};
|
||||
|
||||
#endif // QPDFNUMBERTREEOBJECTHELPER_HH
|
||||
+137
@@ -0,0 +1,137 @@
|
||||
// Copyright (c) 2005-2021 Jay Berkenbilt
|
||||
// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger
|
||||
//
|
||||
// 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 QPDFOBJGEN_HH
|
||||
#define QPDFOBJGEN_HH
|
||||
|
||||
#include <qpdf/DLL.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
class QPDFObjectHandle;
|
||||
class QPDFObjectHelper;
|
||||
|
||||
// This class represents an object ID and generation pair. It is suitable to use as a key in a map
|
||||
// or set.
|
||||
|
||||
class QPDFObjGen
|
||||
{
|
||||
public:
|
||||
QPDFObjGen() = default;
|
||||
QPDFObjGen(int obj, int gen) :
|
||||
obj(obj),
|
||||
gen(gen)
|
||||
{
|
||||
}
|
||||
bool
|
||||
operator<(QPDFObjGen const& rhs) const
|
||||
{
|
||||
return (obj < rhs.obj) || (obj == rhs.obj && gen < rhs.gen);
|
||||
}
|
||||
bool
|
||||
operator==(QPDFObjGen const& rhs) const
|
||||
{
|
||||
return obj == rhs.obj && gen == rhs.gen;
|
||||
}
|
||||
bool
|
||||
operator!=(QPDFObjGen const& rhs) const
|
||||
{
|
||||
return !(*this == rhs);
|
||||
}
|
||||
int
|
||||
getObj() const
|
||||
{
|
||||
return obj;
|
||||
}
|
||||
int
|
||||
getGen() const
|
||||
{
|
||||
return gen;
|
||||
}
|
||||
bool
|
||||
isIndirect() const
|
||||
{
|
||||
return obj != 0;
|
||||
}
|
||||
std::string
|
||||
unparse(char separator = ',') const
|
||||
{
|
||||
return std::to_string(obj) + separator + std::to_string(gen);
|
||||
}
|
||||
friend std::ostream&
|
||||
operator<<(std::ostream& os, QPDFObjGen og)
|
||||
{
|
||||
os << og.obj << "," << og.gen;
|
||||
return os;
|
||||
}
|
||||
|
||||
// Convenience class for loop detection when processing objects.
|
||||
//
|
||||
// The class adds 'add' methods to a std::set<QPDFObjGen> which allows to test whether an
|
||||
// QPDFObjGen is present in the set and to insert it in a single operation. The 'add' method is
|
||||
// overloaded to take a QPDFObjGen, QPDFObjectHandle or an QPDFObjectHelper as parameter.
|
||||
//
|
||||
// The erase method is modified to ignore requests to erase QPDFObjGen(0, 0).
|
||||
//
|
||||
// Usage example:
|
||||
//
|
||||
// void process_object(QPDFObjectHandle oh, QPDFObjGen::set& seen)
|
||||
// {
|
||||
// if (seen.add(oh)) {
|
||||
// // handle first encounter of oh
|
||||
// } else {
|
||||
// // handle loop / subsequent encounter of oh
|
||||
// }
|
||||
// }
|
||||
class QPDF_DLL_CLASS set: public std::set<QPDFObjGen>
|
||||
{
|
||||
public:
|
||||
// Add 'og' to the set. Return false if 'og' is already present in the set. Attempts to
|
||||
// insert QPDFObjGen(0, 0) are ignored.
|
||||
bool
|
||||
add(QPDFObjGen og)
|
||||
{
|
||||
if (og.isIndirect()) {
|
||||
if (count(og)) {
|
||||
return false;
|
||||
}
|
||||
emplace(og);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
erase(QPDFObjGen og)
|
||||
{
|
||||
if (og.isIndirect()) {
|
||||
std::set<QPDFObjGen>::erase(og);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
// This class does not use the Members pattern to avoid a memory allocation for every one of
|
||||
// these. A lot of these get created and destroyed.
|
||||
int obj{0};
|
||||
int gen{0};
|
||||
};
|
||||
|
||||
#endif // QPDFOBJGEN_HH
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
// Copyright (c) 2005-2021 Jay Berkenbilt
|
||||
// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger
|
||||
//
|
||||
// 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 QPDFOBJECT_OLD_HH
|
||||
#define QPDFOBJECT_OLD_HH
|
||||
|
||||
// Current code should not include <qpdf/QPDFObject.hh>. This file exists
|
||||
// to ensure that code that includes it doesn't accidentally work because
|
||||
// of an old qpdf installed on the system. Including this file became an
|
||||
// error with qpdf version 12. The internal QPDFObject API is defined in
|
||||
// QPDFObject_private.hh, which is not part of the public API.
|
||||
|
||||
// Instead of including this header, include <qpdf/Constants.h>, and
|
||||
// replace `QPDFObject::ot_` with `::ot_` in your code.
|
||||
#error "QPDFObject.hh is obsolete; see comments in QPDFObject.hh for details"
|
||||
|
||||
#endif // QPDFOBJECT_OLD_HH
|
||||
+1576
File diff suppressed because it is too large
Load Diff
+70
@@ -0,0 +1,70 @@
|
||||
// Copyright (c) 2005-2021 Jay Berkenbilt
|
||||
// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger
|
||||
//
|
||||
// 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 QPDFOBJECTHELPER_HH
|
||||
#define QPDFOBJECTHELPER_HH
|
||||
|
||||
#include <qpdf/DLL.h>
|
||||
|
||||
#include <qpdf/QPDFObjectHandle.hh>
|
||||
|
||||
// This is a base class for QPDF Object Helper classes. Object helpers are classes that provide a
|
||||
// convenient, higher-level API for working with specific types of QPDF objects. Object helpers are
|
||||
// always initialized with a QPDFObjectHandle, and the underlying object handle can always be
|
||||
// retrieved. The intention is that you may freely intermix use of object helpers with the
|
||||
// underlying QPDF objects unless there is a specific comment in a specific helper method that says
|
||||
// otherwise. The pattern of using helper objects was introduced to allow creation of higher level
|
||||
// helper functions without polluting the public interface of QPDFObjectHandle.
|
||||
class QPDF_DLL_CLASS QPDFObjectHelper: public qpdf::BaseHandle
|
||||
{
|
||||
public:
|
||||
QPDFObjectHelper(QPDFObjectHandle oh) :
|
||||
qpdf::BaseHandle(oh.getObj())
|
||||
{
|
||||
}
|
||||
QPDF_DLL
|
||||
virtual ~QPDFObjectHelper();
|
||||
QPDFObjectHandle
|
||||
getObjectHandle()
|
||||
{
|
||||
return {obj};
|
||||
}
|
||||
QPDFObjectHandle const
|
||||
getObjectHandle() const
|
||||
{
|
||||
return {obj};
|
||||
}
|
||||
|
||||
protected:
|
||||
QPDF_DLL_PRIVATE
|
||||
QPDFObjectHandle
|
||||
oh()
|
||||
{
|
||||
return {obj};
|
||||
}
|
||||
QPDF_DLL_PRIVATE
|
||||
QPDFObjectHandle const
|
||||
oh() const
|
||||
{
|
||||
return {obj};
|
||||
}
|
||||
QPDFObjectHandle oh_;
|
||||
};
|
||||
|
||||
#endif // QPDFOBJECTHELPER_HH
|
||||
Vendored
+92
@@ -0,0 +1,92 @@
|
||||
// Copyright (c) 2005-2021 Jay Berkenbilt
|
||||
// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger
|
||||
//
|
||||
// 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 QPDFOUTLINEDOCUMENTHELPER_HH
|
||||
#define QPDFOUTLINEDOCUMENTHELPER_HH
|
||||
|
||||
#include <qpdf/QPDF.hh>
|
||||
#include <qpdf/QPDFDocumentHelper.hh>
|
||||
#include <qpdf/QPDFNameTreeObjectHelper.hh>
|
||||
#include <qpdf/QPDFObjGen.hh>
|
||||
#include <qpdf/QPDFOutlineObjectHelper.hh>
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include <qpdf/DLL.h>
|
||||
|
||||
// This is a document helper for outlines, also known as bookmarks. Outlines are discussed in
|
||||
// section 12.3.3 of the PDF spec (ISO-32000). With the help of QPDFOutlineObjectHelper, the
|
||||
// outlines tree is traversed, and a bidirectional map is made between pages and outlines. See also
|
||||
// QPDFOutlineObjectHelper.
|
||||
class QPDFOutlineDocumentHelper: public QPDFDocumentHelper
|
||||
{
|
||||
public:
|
||||
// Get a shared document helper for a given QPDF object.
|
||||
//
|
||||
// Retrieving a document helper for a QPDF object rather than creating a new one avoids repeated
|
||||
// validation of the Acroform structure, which can be expensive.
|
||||
QPDF_DLL
|
||||
static QPDFOutlineDocumentHelper& get(QPDF& qpdf);
|
||||
|
||||
// Re-validate the Outlines structure. This is useful if you have modified the structure of the
|
||||
// Outlines dictionary in a way that would invalidate the cache.
|
||||
//
|
||||
// If repair is true, the document will be repaired if possible if the validation encounters
|
||||
// errors.
|
||||
QPDF_DLL
|
||||
void validate(bool repair = true);
|
||||
|
||||
QPDF_DLL
|
||||
QPDFOutlineDocumentHelper(QPDF&);
|
||||
|
||||
~QPDFOutlineDocumentHelper() override = default;
|
||||
|
||||
QPDF_DLL
|
||||
bool hasOutlines();
|
||||
|
||||
QPDF_DLL
|
||||
std::vector<QPDFOutlineObjectHelper> getTopLevelOutlines();
|
||||
|
||||
// If the name is a name object, look it up in the /Dests key of the document catalog. If the
|
||||
// name is a string, look it up in the name tree pointed to by the /Dests key of the names
|
||||
// dictionary.
|
||||
QPDF_DLL
|
||||
QPDFObjectHandle resolveNamedDest(QPDFObjectHandle name);
|
||||
|
||||
// Return a list outlines that are known to target the specified page.
|
||||
QPDF_DLL
|
||||
std::vector<QPDFOutlineObjectHelper> getOutlinesForPage(QPDFObjGen);
|
||||
|
||||
class Accessor
|
||||
{
|
||||
friend class QPDFOutlineObjectHelper;
|
||||
|
||||
static bool checkSeen(QPDFOutlineDocumentHelper& dh, QPDFObjGen og);
|
||||
};
|
||||
|
||||
private:
|
||||
void initializeByPage();
|
||||
|
||||
class Members;
|
||||
|
||||
std::shared_ptr<Members> m;
|
||||
};
|
||||
|
||||
#endif // QPDFOUTLINEDOCUMENTHELPER_HH
|
||||
+109
@@ -0,0 +1,109 @@
|
||||
// Copyright (c) 2005-2021 Jay Berkenbilt
|
||||
// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger
|
||||
//
|
||||
// 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 QPDFOUTLINEOBJECTHELPER_HH
|
||||
#define QPDFOUTLINEOBJECTHELPER_HH
|
||||
|
||||
#include <qpdf/QPDFObjGen.hh>
|
||||
#include <qpdf/QPDFObjectHelper.hh>
|
||||
#include <vector>
|
||||
|
||||
class QPDFOutlineDocumentHelper;
|
||||
|
||||
#include <qpdf/DLL.h>
|
||||
|
||||
// This is an object helper for outline items. Outlines, also known as bookmarks, are described in
|
||||
// section 12.3.3 of the PDF spec (ISO-32000). See comments below for details.
|
||||
class QPDFOutlineObjectHelper: public QPDFObjectHelper
|
||||
{
|
||||
public:
|
||||
~QPDFOutlineObjectHelper() override
|
||||
{
|
||||
// This must be cleared explicitly to avoid circular references that prevent cleanup of
|
||||
// shared pointers.
|
||||
m->parent = nullptr;
|
||||
}
|
||||
|
||||
// All constructors are private. You can only create one of these using
|
||||
// QPDFOutlineDocumentHelper.
|
||||
|
||||
// Return parent pointer. Returns a null pointer if this is a top-level outline.
|
||||
QPDF_DLL
|
||||
std::shared_ptr<QPDFOutlineObjectHelper> getParent();
|
||||
|
||||
// Return children as a list.
|
||||
QPDF_DLL
|
||||
std::vector<QPDFOutlineObjectHelper> getKids();
|
||||
|
||||
// Return the destination, regardless of whether it is named or explicit and whether it is
|
||||
// directly provided or in a GoTo action. Returns a null object if the destination can't be
|
||||
// determined. Named destinations can be resolved using the older root /Dest dictionary or the
|
||||
// current names tree.
|
||||
QPDF_DLL
|
||||
QPDFObjectHandle getDest();
|
||||
|
||||
// Return the page that the outline points to. Returns a null object if the destination page
|
||||
// can't be determined.
|
||||
QPDF_DLL
|
||||
QPDFObjectHandle getDestPage();
|
||||
|
||||
// Returns the value of /Count as present in the object, or 0 if not present. If count is
|
||||
// positive, the outline is open. If negative, it is closed. Either way, the absolute value is
|
||||
// the number of descendant items that would be visible if this were open.
|
||||
QPDF_DLL
|
||||
int getCount();
|
||||
|
||||
// Returns the title as a UTF-8 string. Returns an empty string if there is no title.
|
||||
QPDF_DLL
|
||||
std::string getTitle();
|
||||
|
||||
class Accessor
|
||||
{
|
||||
friend class QPDFOutlineDocumentHelper;
|
||||
|
||||
static QPDFOutlineObjectHelper
|
||||
create(QPDFObjectHandle oh, QPDFOutlineDocumentHelper& dh, int depth)
|
||||
{
|
||||
return {oh, dh, depth};
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
QPDFOutlineObjectHelper(QPDFObjectHandle, QPDFOutlineDocumentHelper&, int);
|
||||
|
||||
class Members
|
||||
{
|
||||
friend class QPDFOutlineObjectHelper;
|
||||
|
||||
public:
|
||||
~Members() = default;
|
||||
|
||||
private:
|
||||
Members(QPDFOutlineDocumentHelper& dh);
|
||||
Members(Members const&) = delete;
|
||||
|
||||
QPDFOutlineDocumentHelper& dh;
|
||||
std::shared_ptr<QPDFOutlineObjectHelper> parent;
|
||||
std::vector<QPDFOutlineObjectHelper> kids;
|
||||
};
|
||||
|
||||
std::shared_ptr<Members> m;
|
||||
};
|
||||
|
||||
#endif // QPDFOUTLINEOBJECTHELPER_HH
|
||||
+128
@@ -0,0 +1,128 @@
|
||||
// Copyright (c) 2005-2021 Jay Berkenbilt
|
||||
// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger
|
||||
//
|
||||
// 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 QPDFPAGEDOCUMENTHELPER_HH
|
||||
#define QPDFPAGEDOCUMENTHELPER_HH
|
||||
|
||||
#include <qpdf/Constants.h>
|
||||
#include <qpdf/QPDFDocumentHelper.hh>
|
||||
#include <qpdf/QPDFPageObjectHelper.hh>
|
||||
|
||||
#include <qpdf/DLL.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <qpdf/QPDF.hh>
|
||||
|
||||
class QPDFAcroFormDocumentHelper;
|
||||
|
||||
class QPDFPageDocumentHelper: public QPDFDocumentHelper
|
||||
{
|
||||
public:
|
||||
// Get a shared document helper for a given QPDF object.
|
||||
//
|
||||
// Retrieving a document helper for a QPDF object rather than creating a new one avoids repeated
|
||||
// validation of the Acroform structure, which can be expensive.
|
||||
QPDF_DLL
|
||||
static QPDFPageDocumentHelper& get(QPDF& qpdf);
|
||||
|
||||
// Re-validate the Pages structure. This is useful if you have modified the Pages structure in
|
||||
// a way that would invalidate the cache.
|
||||
//
|
||||
// If repair is true, the document will be repaired if possible if the validation encounters
|
||||
// errors.
|
||||
QPDF_DLL
|
||||
void validate(bool repair = true);
|
||||
|
||||
QPDF_DLL
|
||||
QPDFPageDocumentHelper(QPDF&);
|
||||
|
||||
~QPDFPageDocumentHelper() override = default;
|
||||
|
||||
// Traverse page tree, and return all /Page objects wrapped in QPDFPageObjectHelper objects.
|
||||
// Unlike with QPDF::getAllPages, the vector of pages returned by this call is not affected by
|
||||
// additions or removals of pages. If you manipulate pages, you will have to call this again to
|
||||
// get a new copy. Please see comments in QPDF.hh for getAllPages() for additional details.
|
||||
QPDF_DLL
|
||||
std::vector<QPDFPageObjectHelper> getAllPages();
|
||||
|
||||
// The PDF /Pages tree allows inherited values. Working with the pages of a pdf is much easier
|
||||
// when the inheritance is resolved by explicitly setting the values in each /Page.
|
||||
QPDF_DLL
|
||||
void pushInheritedAttributesToPage();
|
||||
|
||||
// This calls QPDFPageObjectHelper::removeUnreferencedResources for every page in the document.
|
||||
// See comments in QPDFPageObjectHelper.hh for details.
|
||||
QPDF_DLL
|
||||
void removeUnreferencedResources();
|
||||
|
||||
// Add a new page at the beginning or the end of the current pdf. The newpage parameter may be
|
||||
// either a direct object, an indirect object from this QPDF, or an indirect object from another
|
||||
// QPDF. If it is a direct object, it will be made indirect. If it is an indirect object from
|
||||
// another QPDF, this method will call pushInheritedAttributesToPage on the other file and then
|
||||
// copy the page to this QPDF using the same underlying code as copyForeignObject. At this
|
||||
// stage, if the indirect object is already in the pages tree, a shallow copy is made to avoid
|
||||
// adding the same page more than once. In version 10.3.1 and earlier, adding a page that
|
||||
// already existed would throw an exception and could cause qpdf to crash on subsequent page
|
||||
// insertions in some cases. Note that this means that, in some cases, the page actually added
|
||||
// won't be exactly the same object as the one passed in. If you want to do subsequent
|
||||
// modification on the page, you should retrieve it again.
|
||||
//
|
||||
// Note that you can call copyForeignObject directly to copy a page from a different file, but
|
||||
// the resulting object will not be a page in the new file. You could do this, for example, to
|
||||
// convert a page into a form XObject, though for that, you're better off using
|
||||
// QPDFPageObjectHelper::getFormXObjectForPage.
|
||||
//
|
||||
// This method does not have any specific awareness of annotations or form fields, so if you
|
||||
// just add a page without thinking about it, you might end up with two pages that share form
|
||||
// fields or annotations. While the page may look fine, it will probably not function properly
|
||||
// with regard to interactive features. To work around this, you should call
|
||||
// QPDFAcroFormDocumentHelper::fixCopiedAnnotations. A future version of qpdf will likely
|
||||
// provide a higher-level interface for copying pages around that will handle document-level
|
||||
// constructs in a less error-prone fashion.
|
||||
|
||||
QPDF_DLL
|
||||
void addPage(QPDFPageObjectHelper newpage, bool first);
|
||||
|
||||
// Add new page before or after refpage. See comments for addPage for details about what newpage
|
||||
// should be.
|
||||
QPDF_DLL
|
||||
void addPageAt(QPDFPageObjectHelper newpage, bool before, QPDFPageObjectHelper refpage);
|
||||
|
||||
// Remove page from the pdf.
|
||||
QPDF_DLL
|
||||
void removePage(QPDFPageObjectHelper page);
|
||||
|
||||
// For every annotation, integrate the annotation's appearance stream into the containing page's
|
||||
// content streams, merge the annotation's resources with the page's resources, and remove the
|
||||
// annotation from the page. Handles widget annotations associated with interactive form fields
|
||||
// as a special case, including removing the /AcroForm key from the document catalog. The values
|
||||
// passed to required_flags and forbidden_flags are passed along to
|
||||
// QPDFAnnotationObjectHelper::getPageContentForAppearance. See comments there in
|
||||
// QPDFAnnotationObjectHelper.hh for meanings of those flags.
|
||||
QPDF_DLL
|
||||
void flattenAnnotations(int required_flags = 0, int forbidden_flags = an_invisible | an_hidden);
|
||||
|
||||
private:
|
||||
class Members;
|
||||
|
||||
std::shared_ptr<Members> m;
|
||||
};
|
||||
|
||||
#endif // QPDFPAGEDOCUMENTHELPER_HH
|
||||
Vendored
+99
@@ -0,0 +1,99 @@
|
||||
// Copyright (c) 2005-2021 Jay Berkenbilt
|
||||
// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger
|
||||
//
|
||||
// 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 QPDFPAGELABELDOCUMENTHELPER_HH
|
||||
#define QPDFPAGELABELDOCUMENTHELPER_HH
|
||||
|
||||
#include <qpdf/QPDFDocumentHelper.hh>
|
||||
|
||||
#include <qpdf/DLL.h>
|
||||
#include <qpdf/QPDF.hh>
|
||||
|
||||
#include <vector>
|
||||
|
||||
// Page labels are discussed in the PDF spec (ISO-32000) in section 12.4.2.
|
||||
//
|
||||
// Page labels are implemented as a number tree. Each key is a page index, numbered from 0. The
|
||||
// values are dictionaries with the following keys, all optional:
|
||||
//
|
||||
// * /Type: if present, must be /PageLabel
|
||||
// * /S: one of /D, /R, /r, /A, or /a for decimal, upper-case and lower-case Roman numeral, or
|
||||
// upper-case and lower-case alphabetic
|
||||
// * /P: if present, a fixed prefix string that is prepended to each page number
|
||||
// * /St: the starting number, or 1 if not specified
|
||||
|
||||
class QPDFPageLabelDocumentHelper: public QPDFDocumentHelper
|
||||
{
|
||||
public:
|
||||
// Get a shared document helper for a given QPDF object.
|
||||
//
|
||||
// Retrieving a document helper for a QPDF object rather than creating a new one avoids repeated
|
||||
// validation of the PageLabels structure, which can be expensive.
|
||||
QPDF_DLL
|
||||
static QPDFPageLabelDocumentHelper& get(QPDF& qpdf);
|
||||
|
||||
// Re-validate the PageLabels structure. This is useful if you have modified the structure of
|
||||
// the PageLabels dictionary in a way that could have invalidated the structure.
|
||||
//
|
||||
// If repair is true, the document will be repaired if possible if the validation encounters
|
||||
// errors.
|
||||
QPDF_DLL
|
||||
void validate(bool repair = true);
|
||||
|
||||
QPDF_DLL
|
||||
QPDFPageLabelDocumentHelper(QPDF&);
|
||||
|
||||
~QPDFPageLabelDocumentHelper() override = default;
|
||||
|
||||
QPDF_DLL
|
||||
bool hasPageLabels();
|
||||
|
||||
// Helper function to create a dictionary suitable for adding to the /PageLabels numbers tree.
|
||||
QPDF_DLL
|
||||
static QPDFObjectHandle
|
||||
pageLabelDict(qpdf_page_label_e label_type, int start_num, std::string_view prefix);
|
||||
|
||||
// Return a page label dictionary representing the page label for the given page. The page does
|
||||
// not need to appear explicitly in the page label dictionary. This method will adjust /St as
|
||||
// needed to produce a label that is suitable for the page.
|
||||
QPDF_DLL
|
||||
QPDFObjectHandle getLabelForPage(long long page_idx);
|
||||
|
||||
// Append to the incoming vector a list of objects suitable for inclusion in a /PageLabels
|
||||
// dictionary's /Nums field. start_idx and end_idx are the indexes to the starting and ending
|
||||
// pages (inclusive) in the original file, and new_start_idx is the index to the first page in
|
||||
// the new file. For example, if pages 10 through 12 of one file are being copied to a new file
|
||||
// as pages 6 through 8, you would call getLabelsForPageRange(10, 12, 6), which would return as
|
||||
// many entries as are required to add to the new file's PageLabels. This method fabricates a
|
||||
// suitable entry even if the original document has no page labels. This behavior facilitates
|
||||
// using this function to incrementally build up a page labels tree when merging files.
|
||||
QPDF_DLL
|
||||
void getLabelsForPageRange(
|
||||
long long start_idx,
|
||||
long long end_idx,
|
||||
long long new_start_idx,
|
||||
std::vector<QPDFObjectHandle>& new_labels);
|
||||
|
||||
private:
|
||||
class Members;
|
||||
|
||||
std::shared_ptr<Members> m;
|
||||
};
|
||||
|
||||
#endif // QPDFPAGELABELDOCUMENTHELPER_HH
|
||||
+423
@@ -0,0 +1,423 @@
|
||||
// Copyright (c) 2005-2021 Jay Berkenbilt
|
||||
// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger
|
||||
//
|
||||
// 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 QPDFPAGEOBJECTHELPER_HH
|
||||
#define QPDFPAGEOBJECTHELPER_HH
|
||||
|
||||
#include <qpdf/QPDFAnnotationObjectHelper.hh>
|
||||
#include <qpdf/QPDFMatrix.hh>
|
||||
#include <qpdf/QPDFObjectHelper.hh>
|
||||
|
||||
#include <qpdf/DLL.h>
|
||||
|
||||
#include <qpdf/QPDFObjectHandle.hh>
|
||||
#include <functional>
|
||||
|
||||
class QPDFAcroFormDocumentHelper;
|
||||
|
||||
// This is a helper class for page objects, but as of qpdf 10.1, many of the methods also work
|
||||
// for form XObjects. When this is the case, it is noted in the comment.
|
||||
class QPDFPageObjectHelper: public QPDFObjectHelper
|
||||
{
|
||||
public:
|
||||
QPDF_DLL
|
||||
QPDFPageObjectHelper(QPDFObjectHandle);
|
||||
|
||||
~QPDFPageObjectHelper() override = default;
|
||||
|
||||
// PAGE ATTRIBUTES
|
||||
|
||||
// The getAttribute method works with pages and form XObjects. It returns the value of the
|
||||
// requested attribute from the page/form XObject's dictionary, taking inheritance from the
|
||||
// pages tree into consideration. For pages, the attributes /MediaBox, /CropBox, /Resources, and
|
||||
// /Rotate are inheritable, meaning that if they are not present directly on the page node, they
|
||||
// may be inherited from ancestor nodes in the pages tree.
|
||||
//
|
||||
// There are two ways that an attribute can be "shared":
|
||||
//
|
||||
// * For inheritable attributes on pages, it may appear in a higher level node of the pages tree
|
||||
//
|
||||
// * For any attribute, the attribute may be an indirect object which may be referenced by more
|
||||
// than one page/form XObject.
|
||||
//
|
||||
// If copy_if_shared is true, then this method will replace the attribute with a shallow copy if
|
||||
// it is indirect or inherited and return the copy. You should do this if you are going to
|
||||
// modify the returned object and want the modifications to apply to the current page/form
|
||||
// XObject only.
|
||||
QPDF_DLL
|
||||
QPDFObjectHandle getAttribute(std::string const& name, bool copy_if_shared);
|
||||
|
||||
// PAGE BOXES
|
||||
//
|
||||
// Pages have various types of boundary boxes. These are described in detail in the PDF
|
||||
// specification (section 14.11.2 Page boundaries). They are, by key in the page dictionary:
|
||||
//
|
||||
// * /MediaBox -- boundaries of physical page
|
||||
// * /CropBox -- clipping region of what is displayed
|
||||
// * /BleedBox -- clipping region for production environments
|
||||
// * /TrimBox -- dimensions of final printed page after trimming
|
||||
// * /ArtBox -- extent of meaningful content including margins
|
||||
//
|
||||
// Of these, only /MediaBox is required. If any are absent, the
|
||||
// fallback value for /CropBox is /MediaBox, and the fallback
|
||||
// values for the other boxes are /CropBox.
|
||||
//
|
||||
// As noted above (PAGE ATTRIBUTES), /MediaBox and /CropBox can be inherited from parent nodes
|
||||
// in the pages tree. The other boxes can't be inherited.
|
||||
//
|
||||
// When the comments below refer to the "effective value" of a box, this takes into
|
||||
// consideration both inheritance through the pages tree (in the case of /MediaBox and /CropBox)
|
||||
// and fallback values for missing attributes (for all except /MediaBox).
|
||||
//
|
||||
// For the methods below, copy_if_shared is passed to getAttribute and therefore refers only to
|
||||
// indirect objects and values that are inherited through the pages tree.
|
||||
//
|
||||
// If copy_if_fallback is true, a copy is made if the object's value was obtained by falling
|
||||
// back to a different box.
|
||||
//
|
||||
// The copy_if_shared and copy_if_fallback parameters carry across multiple layers. This is
|
||||
// explained below.
|
||||
//
|
||||
// You should set copy_if_shared to true if you want to modify a bounding box for the current
|
||||
// page without affecting other pages but you don't want to change the fallback behavior. For
|
||||
// example, if you want to modify the /TrimBox for the current page only but have it continue to
|
||||
// fall back to the value of /CropBox or /MediaBox if they are not defined, you could set
|
||||
// copy_if_shared to true.
|
||||
//
|
||||
// You should set copy_if_fallback to true if you want to modify a specific box as distinct from
|
||||
// any other box. For example, if you want to make /TrimBox differ from /CropBox, then you
|
||||
// should set copy_if_fallback to true.
|
||||
//
|
||||
// The copy_if_fallback flags were added in qpdf 11.
|
||||
//
|
||||
// For example, suppose that neither /CropBox nor /TrimBox is present on a page but /CropBox is
|
||||
// present in the page's parent node in the page tree.
|
||||
//
|
||||
// * getTrimBox(false, false) would return the /CropBox from the parent node.
|
||||
//
|
||||
// * getTrimBox(true, false) would make a shallow copy of the /CropBox from the parent node into
|
||||
// the current node and return it.
|
||||
//
|
||||
// * getTrimBox(false, true) would make a shallow copy of the /CropBox from the parent node into
|
||||
// /TrimBox of the current node and return it.
|
||||
//
|
||||
// * getTrimBox(true, true) would make a shallow copy of the /CropBox from the parent node into
|
||||
// the current node, then make a shallow copy of the resulting copy to /TrimBox of the current
|
||||
// node, and then return that.
|
||||
//
|
||||
// To illustrate how these parameters carry across multiple layers, suppose that neither
|
||||
// /MediaBox, /CropBox, nor /TrimBox is present on a page but /MediaBox is present on the
|
||||
// parent. In this case:
|
||||
//
|
||||
// * getTrimBox(false, false) would return the value of /MediaBox from the parent node.
|
||||
//
|
||||
// * getTrimBox(true, false) would copy /MediaBox to the current node and return it.
|
||||
//
|
||||
// * getTrimBox(false, true) would first copy /MediaBox from the parent to /CropBox, then copy
|
||||
// /CropBox to /TrimBox, and then return the result.
|
||||
//
|
||||
// * getTrimBox(true, true) would first copy /MediaBox from the parent to the current page, then
|
||||
// copy it to /CropBox, then copy /CropBox to /TrimBox, and then return the result.
|
||||
//
|
||||
// If you need different behavior, call getAttribute directly and take care of your own copying.
|
||||
|
||||
// Return the effective MediaBox
|
||||
QPDF_DLL
|
||||
QPDFObjectHandle getMediaBox(bool copy_if_shared = false);
|
||||
|
||||
// Return the effective CropBox. If not defined, fall back to MediaBox
|
||||
QPDF_DLL
|
||||
QPDFObjectHandle getCropBox(bool copy_if_shared = false, bool copy_if_fallback = false);
|
||||
|
||||
// Return the effective BleedBox. If not defined, fall back to CropBox.
|
||||
QPDF_DLL
|
||||
QPDFObjectHandle getBleedBox(bool copy_if_shared = false, bool copy_if_fallback = false);
|
||||
|
||||
// Return the effective TrimBox. If not defined, fall back to CropBox.
|
||||
QPDF_DLL
|
||||
QPDFObjectHandle getTrimBox(bool copy_if_shared = false, bool copy_if_fallback = false);
|
||||
|
||||
// Return the effective ArtBox. If not defined, fall back to CropBox.
|
||||
QPDF_DLL
|
||||
QPDFObjectHandle getArtBox(bool copy_if_shared = false, bool copy_if_fallback = false);
|
||||
|
||||
// Iterate through XObjects, possibly recursing into form XObjects. This works with pages or
|
||||
// form XObjects. Call action on each XObject for which selector, if specified, returns true.
|
||||
// With no selector, calls action for every object. In addition to the object being passed to
|
||||
// action, the containing XObject dictionary and key are passed in. Remember that the XObject
|
||||
// dictionary may be shared, and the object may appear in multiple XObject dictionaries.
|
||||
QPDF_DLL
|
||||
void forEachXObject(
|
||||
bool recursive,
|
||||
std::function<void(
|
||||
QPDFObjectHandle& obj, QPDFObjectHandle& xobj_dict, std::string const& key)> action,
|
||||
std::function<bool(QPDFObjectHandle)> selector = nullptr);
|
||||
// Only call action for images
|
||||
QPDF_DLL
|
||||
void forEachImage(
|
||||
bool recursive,
|
||||
std::function<void(
|
||||
QPDFObjectHandle& obj, QPDFObjectHandle& xobj_dict, std::string const& key)> action);
|
||||
// Only call action for form XObjects
|
||||
QPDF_DLL
|
||||
void forEachFormXObject(
|
||||
bool recursive,
|
||||
std::function<void(
|
||||
QPDFObjectHandle& obj, QPDFObjectHandle& xobj_dict, std::string const& key)> action);
|
||||
|
||||
// Returns an empty map if there are no images or no resources. Prior to qpdf 8.4.0, this
|
||||
// function did not support inherited resources, but it does now. Return value is a map from
|
||||
// XObject name to the image object, which is always a stream. Works with form XObjects as well
|
||||
// as pages. This method does not recurse into nested form XObjects. For that, use forEachImage.
|
||||
QPDF_DLL
|
||||
std::map<std::string, QPDFObjectHandle> getImages();
|
||||
|
||||
// Old name -- calls getImages()
|
||||
QPDF_DLL
|
||||
std::map<std::string, QPDFObjectHandle> getPageImages();
|
||||
|
||||
// Returns an empty map if there are no form XObjects or no resources. Otherwise, returns a map
|
||||
// of keys to form XObjects directly referenced from this page or form XObjects. This does not
|
||||
// recurse into nested form XObjects. For that, use forEachFormXObject.
|
||||
QPDF_DLL
|
||||
std::map<std::string, QPDFObjectHandle> getFormXObjects();
|
||||
|
||||
// Converts each inline image to an external (normal) image if the size is at least the
|
||||
// specified number of bytes. This method works with pages or form XObjects. By default, it
|
||||
// recursively processes nested form XObjects. Pass true as shallow to avoid this behavior.
|
||||
// Prior to qpdf 10.1, form XObjects were ignored, but this was considered a bug.
|
||||
QPDF_DLL
|
||||
void externalizeInlineImages(size_t min_size = 0, bool shallow = false);
|
||||
|
||||
// Return the annotations in the page's "/Annots" list, if any. If only_subtype is non-empty,
|
||||
// only include annotations of the given subtype.
|
||||
QPDF_DLL
|
||||
std::vector<QPDFAnnotationObjectHelper> getAnnotations(std::string const& only_subtype = "");
|
||||
|
||||
// Returns a vector of stream objects representing the content streams for the given page. This
|
||||
// routine allows the caller to not care whether there are one or more than one content streams
|
||||
// for a page.
|
||||
QPDF_DLL
|
||||
std::vector<QPDFObjectHandle> getPageContents();
|
||||
|
||||
// Add the given object as a new content stream for this page. If parameter 'first' is true, add
|
||||
// to the beginning. Otherwise, add to the end. This routine automatically converts the page
|
||||
// contents to an array if it is a scalar, allowing the caller not to care what the initial
|
||||
// structure is. You can call coalesceContentStreams() afterwards if you want to force it to be
|
||||
// a single stream.
|
||||
QPDF_DLL
|
||||
void addPageContents(QPDFObjectHandle contents, bool first);
|
||||
|
||||
// Rotate a page. If relative is false, set the rotation of the page to angle. Otherwise, add
|
||||
// angle to the rotation of the page. Angle must be a multiple of 90. Adding 90 to the rotation
|
||||
// rotates clockwise by 90 degrees.
|
||||
QPDF_DLL
|
||||
void rotatePage(int angle, bool relative);
|
||||
|
||||
// Coalesce a page's content streams. A page's content may be a stream or an array of streams.
|
||||
// If this page's content is an array, concatenate the streams into a single stream. This can be
|
||||
// useful when working with files that split content streams in arbitrary spots, such as in the
|
||||
// middle of a token, as that can confuse some software. You could also call this after calling
|
||||
// addPageContents.
|
||||
QPDF_DLL
|
||||
void coalesceContentStreams();
|
||||
|
||||
//
|
||||
// Content stream handling
|
||||
//
|
||||
|
||||
// Parse a page's contents through ParserCallbacks, described above. This method works whether
|
||||
// the contents are a single stream or an array of streams. Call on a page object. Also works
|
||||
// for form XObjects.
|
||||
QPDF_DLL
|
||||
void parseContents(QPDFObjectHandle::ParserCallbacks* callbacks);
|
||||
// Old name
|
||||
QPDF_DLL
|
||||
void parsePageContents(QPDFObjectHandle::ParserCallbacks* callbacks);
|
||||
|
||||
// Pass a page's or form XObject's contents through the given TokenFilter. If a pipeline is also
|
||||
// provided, it will be the target of the write methods from the token filter. If a pipeline is
|
||||
// not specified, any output generated by the token filter will be discarded. Use this interface
|
||||
// if you need to pass a page's contents through filter for work purposes without having that
|
||||
// filter automatically applied to the page's contents, as happens with addContentTokenFilter.
|
||||
// See examples/pdf-count-strings.cc for an example.
|
||||
QPDF_DLL
|
||||
void filterContents(QPDFObjectHandle::TokenFilter* filter, Pipeline* next = nullptr);
|
||||
|
||||
// Old name -- calls filterContents()
|
||||
QPDF_DLL
|
||||
void filterPageContents(QPDFObjectHandle::TokenFilter* filter, Pipeline* next = nullptr);
|
||||
|
||||
// Pipe a page's contents through the given pipeline. This method works whether the contents are
|
||||
// a single stream or an array of streams. Also works on form XObjects.
|
||||
QPDF_DLL
|
||||
void pipeContents(Pipeline* p);
|
||||
// Old name
|
||||
QPDF_DLL
|
||||
void pipePageContents(Pipeline* p);
|
||||
|
||||
// Attach a token filter to a page's contents. If the page's contents is an array of streams, it
|
||||
// is automatically coalesced. The token filter is applied to the page's contents as a single
|
||||
// stream. Also works on form XObjects.
|
||||
QPDF_DLL
|
||||
void addContentTokenFilter(std::shared_ptr<QPDFObjectHandle::TokenFilter> token_filter);
|
||||
|
||||
// A page's resources dictionary maps names to objects elsewhere in the file. This method walks
|
||||
// through a page's contents and keeps tracks of which resources are referenced somewhere in the
|
||||
// contents. Then it removes from the resources dictionary any object that is not referenced in
|
||||
// the contents. This operation is most useful after calling
|
||||
// QPDFPageDocumentHelper::pushInheritedAttributesToPage(). This method is used by page
|
||||
// splitting code to avoid copying unused objects in files that used shared resource
|
||||
// dictionaries across multiple pages. This method recurses into form XObjects and can be called
|
||||
// with a form XObject as well as a page.
|
||||
QPDF_DLL
|
||||
void removeUnreferencedResources();
|
||||
|
||||
// Return a new QPDFPageObjectHelper that is a duplicate of the page. The returned object is an
|
||||
// indirect object that is ready to be inserted into the same or a different QPDF object using
|
||||
// any of the addPage methods in QPDFPageDocumentHelper or QPDF. Without calling one of those
|
||||
// methods, the page will not be added anywhere. The new page object shares all content streams
|
||||
// and indirect object resources with the original page, so if you are going to modify the
|
||||
// contents or other aspects of the page, you will need to handling copying of the component
|
||||
// parts separately.
|
||||
QPDF_DLL
|
||||
QPDFPageObjectHelper shallowCopyPage();
|
||||
|
||||
// Return a transformation matrix whose effect is the same as the page's /Rotate and /UserUnit
|
||||
// parameters. If invert is true, return a matrix whose effect is the opposite. The regular
|
||||
// matrix is suitable for taking something from this page to put elsewhere, and the second one
|
||||
// is suitable for putting something else onto this page. The page's TrimBox is used as the
|
||||
// bounding box for purposes of computing the matrix.
|
||||
QPDF_DLL
|
||||
QPDFObjectHandle::Matrix getMatrixForTransformations(bool invert = false);
|
||||
|
||||
// Return a form XObject that draws this page. This is useful for n-up operations, underlay,
|
||||
// overlay, thumbnail generation, or any other case in which it is useful to replicate the
|
||||
// contents of a page in some other context. The dictionaries are shallow copies of the original
|
||||
// page dictionary, and the contents are coalesced from the page's contents. The resulting
|
||||
// object handle is not referenced anywhere. If handle_transformations is true, the resulting
|
||||
// form XObject's /Matrix will be set to replicate rotation (/Rotate) and scaling (/UserUnit) in
|
||||
// the page's dictionary. In this way, the page's transformations will be preserved when placing
|
||||
// this object on another page.
|
||||
QPDF_DLL
|
||||
QPDFObjectHandle getFormXObjectForPage(bool handle_transformations = true);
|
||||
|
||||
// Return content stream text that will place the given form XObject (fo) using the resource
|
||||
// name "name" on this page centered within the given rectangle. If invert_transformations is
|
||||
// true, the effect of any rotation (/Rotate) and scaling (/UserUnit) applied to the current
|
||||
// page will be inverted in the form XObject placement. This will cause the form XObject's
|
||||
// absolute orientation to be preserved. You could overlay one page on another by calling
|
||||
// getFormXObjectForPage on the original page, QPDFObjectHandle::getUniqueResourceName on the
|
||||
// destination page's Resources dictionary to generate a name for the resulting object, and
|
||||
// calling placeFormXObject on the destination page. Then insert the new fo (or, if it comes
|
||||
// from a different file, the result of calling copyForeignObject on it) into the resources
|
||||
// dictionary using name, and append or prepend the content to the page's content streams. See
|
||||
// the overlay/underlay code in qpdf.cc or examples/pdf-overlay-page.cc for an example. From
|
||||
// qpdf 10.0.0, the allow_shrink and allow_expand parameters control whether the form XObject is
|
||||
// allowed to be shrunk or expanded to stay within or maximally fill the destination rectangle.
|
||||
// The default values are for backward compatibility with the pre-10.0.0 behavior.
|
||||
QPDF_DLL
|
||||
std::string placeFormXObject(
|
||||
QPDFObjectHandle fo,
|
||||
std::string const& name,
|
||||
QPDFObjectHandle::Rectangle rect,
|
||||
bool invert_transformations = true,
|
||||
bool allow_shrink = true,
|
||||
bool allow_expand = false);
|
||||
|
||||
// Alternative version that also fills in the transformation matrix that was used.
|
||||
QPDF_DLL
|
||||
std::string placeFormXObject(
|
||||
QPDFObjectHandle fo,
|
||||
std::string const& name,
|
||||
QPDFObjectHandle::Rectangle rect,
|
||||
QPDFMatrix& cm,
|
||||
bool invert_transformations = true,
|
||||
bool allow_shrink = true,
|
||||
bool allow_expand = false);
|
||||
|
||||
// Return the transformation matrix that translates from the given form XObject's coordinate
|
||||
// system into the given rectangular region on the page. The parameters have the same meaning as
|
||||
// for placeFormXObject.
|
||||
QPDF_DLL
|
||||
QPDFMatrix getMatrixForFormXObjectPlacement(
|
||||
QPDFObjectHandle fo,
|
||||
QPDFObjectHandle::Rectangle rect,
|
||||
bool invert_transformations = true,
|
||||
bool allow_shrink = true,
|
||||
bool allow_expand = false);
|
||||
|
||||
// If a page is rotated using /Rotate in the page's dictionary, instead rotate the page by the
|
||||
// same amount by altering the contents and removing the /Rotate key. This method adjusts the
|
||||
// various page bounding boxes (/MediaBox, etc.) so that the page will have the same semantics.
|
||||
// This can be useful to work around problems with PDF applications that can't properly handle
|
||||
// rotated pages. If a QPDFAcroFormDocumentHelper is provided, it will be used for resolving any
|
||||
// form fields that have to be rotated. If not, one will be created inside the function, which
|
||||
// is less efficient.
|
||||
QPDF_DLL
|
||||
void flattenRotation(QPDFAcroFormDocumentHelper* afdh = nullptr);
|
||||
|
||||
// Copy annotations from another page into this page. The other page may be from the same QPDF
|
||||
// or from a different QPDF. Each annotation's rectangle is transformed by the given matrix. If
|
||||
// the annotation is a widget annotation that is associated with a form field, the form field is
|
||||
// copied into this document's AcroForm dictionary as well. You can use this to copy annotations
|
||||
// from a page that was converted to a form XObject and added to another page. For example of
|
||||
// this, see examples/pdf-overlay-page.cc. This method calls
|
||||
// QPDFAcroFormDocumentHelper::transformAnnotations, which will copy annotations and form fields
|
||||
// so that you can copy annotations from a source page to any number of other pages, even with
|
||||
// different matrices, and maintain independence from the original annotations. See also
|
||||
// QPDFAcroFormDocumentHelper::fixCopiedAnnotations, which can be used if you copy a page and
|
||||
// want to repair the annotations on the destination page to make them independent from the
|
||||
// original page's annotations.
|
||||
//
|
||||
// If you pass in a QPDFAcroFormDocumentHelper*, the method will use that instead of creating
|
||||
// one in the function. Creating QPDFAcroFormDocumentHelper objects is expensive, so if you're
|
||||
// doing a lot of copying, it can be more efficient to create these outside and pass them in.
|
||||
QPDF_DLL
|
||||
void copyAnnotations(
|
||||
QPDFPageObjectHelper from_page,
|
||||
QPDFMatrix const& cm = QPDFMatrix(),
|
||||
QPDFAcroFormDocumentHelper* afdh = nullptr,
|
||||
QPDFAcroFormDocumentHelper* from_afdh = nullptr);
|
||||
|
||||
private:
|
||||
QPDFObjectHandle getAttribute(
|
||||
std::string const& name,
|
||||
bool copy_if_shared,
|
||||
std::function<QPDFObjectHandle()> get_fallback,
|
||||
bool copy_if_fallback);
|
||||
static bool
|
||||
removeUnreferencedResourcesHelper(QPDFPageObjectHelper ph, std::set<std::string>& unresolved);
|
||||
|
||||
class Members
|
||||
{
|
||||
friend class QPDFPageObjectHelper;
|
||||
|
||||
public:
|
||||
~Members() = default;
|
||||
|
||||
private:
|
||||
Members() = default;
|
||||
Members(Members const&) = delete;
|
||||
};
|
||||
|
||||
std::shared_ptr<Members> m;
|
||||
};
|
||||
|
||||
#endif // QPDFPAGEOBJECTHELPER_HH
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
// Copyright (c) 2005-2021 Jay Berkenbilt
|
||||
// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger
|
||||
//
|
||||
// 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 QPDFSTREAMFILTER_HH
|
||||
#define QPDFSTREAMFILTER_HH
|
||||
|
||||
#include <qpdf/DLL.h>
|
||||
#include <qpdf/Pipeline.hh>
|
||||
#include <qpdf/QPDFObjectHandle.hh>
|
||||
|
||||
class QPDF_DLL_CLASS QPDFStreamFilter
|
||||
{
|
||||
public:
|
||||
QPDFStreamFilter() = default;
|
||||
|
||||
virtual ~QPDFStreamFilter() = default;
|
||||
|
||||
// A QPDFStreamFilter class must implement, at a minimum, setDecodeParms() and
|
||||
// getDecodePipeline(). QPDF will always call setDecodeParms() before calling
|
||||
// getDecodePipeline(). It is expected that you will store any needed information from
|
||||
// decode_parms (or the decode_parms object itself) in your instance so that it can be used to
|
||||
// construct the decode pipeline.
|
||||
|
||||
// Return a boolean indicating whether your filter can proceed with the given /DecodeParms. The
|
||||
// default implementation accepts a null object and rejects everything else.
|
||||
QPDF_DLL
|
||||
virtual bool setDecodeParms(QPDFObjectHandle decode_parms);
|
||||
|
||||
// Return a pipeline that will decode data encoded with your filter. Your implementation must
|
||||
// ensure that the pipeline is deleted when the instance of your class is destroyed.
|
||||
QPDF_DLL
|
||||
virtual Pipeline* getDecodePipeline(Pipeline* next) = 0;
|
||||
|
||||
// If your filter implements "specialized" compression or lossy compression, override one or
|
||||
// both of these methods. The default implementations return false. See comments in QPDFWriter
|
||||
// for details. QPDF defines specialized compression as non-lossy compression not intended for
|
||||
// general-purpose data. qpdf, by default, doesn't mess with streams that are compressed with
|
||||
// specialized compression, the idea being that the decision to use that compression scheme
|
||||
// would fall outside of what QPDFWriter would know anything about, so any attempt to decode and
|
||||
// re-encode would probably be undesirable.
|
||||
QPDF_DLL
|
||||
virtual bool isSpecializedCompression();
|
||||
QPDF_DLL
|
||||
virtual bool isLossyCompression();
|
||||
|
||||
private:
|
||||
QPDFStreamFilter(QPDFStreamFilter const&) = delete;
|
||||
QPDFStreamFilter& operator=(QPDFStreamFilter const&) = delete;
|
||||
};
|
||||
|
||||
#endif // QPDFSTREAMFILTER_HH
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
// Copyright (c) 2005-2021 Jay Berkenbilt
|
||||
// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger
|
||||
//
|
||||
// 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 QPDFSYSTEMERROR_HH
|
||||
#define QPDFSYSTEMERROR_HH
|
||||
|
||||
#include <qpdf/Constants.h>
|
||||
#include <qpdf/DLL.h>
|
||||
#include <qpdf/Types.h>
|
||||
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
class QPDF_DLL_CLASS QPDFSystemError: public std::runtime_error
|
||||
{
|
||||
public:
|
||||
QPDF_DLL
|
||||
QPDFSystemError(std::string const& description, int system_errno);
|
||||
|
||||
~QPDFSystemError() noexcept override = default;
|
||||
|
||||
// To get a complete error string, call what(), provided by std::exception. The accessors below
|
||||
// return the original values used to create the exception.
|
||||
|
||||
QPDF_DLL
|
||||
std::string const& getDescription() const;
|
||||
QPDF_DLL
|
||||
int getErrno() const;
|
||||
|
||||
private:
|
||||
QPDF_DLL_PRIVATE
|
||||
static std::string createWhat(std::string const& description, int system_errno);
|
||||
|
||||
// This class does not use the Members pattern to avoid needless memory allocations during
|
||||
// exception handling.
|
||||
|
||||
std::string description;
|
||||
int system_errno;
|
||||
};
|
||||
|
||||
#endif // QPDFSYSTEMERROR_HH
|
||||
+218
@@ -0,0 +1,218 @@
|
||||
// Copyright (c) 2005-2021 Jay Berkenbilt
|
||||
// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger
|
||||
//
|
||||
// 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 QPDFTOKENIZER_HH
|
||||
#define QPDFTOKENIZER_HH
|
||||
|
||||
#include <qpdf/DLL.h>
|
||||
|
||||
#include <qpdf/InputSource.hh>
|
||||
|
||||
#include <cstdio>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
namespace qpdf
|
||||
{
|
||||
class Tokenizer;
|
||||
namespace impl
|
||||
{
|
||||
class Parser;
|
||||
}
|
||||
} // namespace qpdf
|
||||
|
||||
class QPDFTokenizer
|
||||
{
|
||||
public:
|
||||
// Token type tt_eof is only returned of allowEOF() is called on the tokenizer. tt_eof was
|
||||
// introduced in QPDF version 4.1. tt_space, tt_comment, and tt_inline_image were added in QPDF
|
||||
// version 8.
|
||||
enum token_type_e {
|
||||
tt_bad,
|
||||
tt_array_close,
|
||||
tt_array_open,
|
||||
tt_brace_close,
|
||||
tt_brace_open,
|
||||
tt_dict_close,
|
||||
tt_dict_open,
|
||||
tt_integer,
|
||||
tt_name,
|
||||
tt_real,
|
||||
tt_string,
|
||||
tt_null,
|
||||
tt_bool,
|
||||
tt_word,
|
||||
tt_eof,
|
||||
tt_space,
|
||||
tt_comment,
|
||||
tt_inline_image,
|
||||
};
|
||||
|
||||
class Token
|
||||
{
|
||||
public:
|
||||
Token() :
|
||||
type(tt_bad)
|
||||
{
|
||||
}
|
||||
QPDF_DLL
|
||||
Token(token_type_e type, std::string const& value);
|
||||
Token(
|
||||
token_type_e type,
|
||||
std::string const& value,
|
||||
std::string raw_value,
|
||||
std::string error_message) :
|
||||
type(type),
|
||||
value(value),
|
||||
raw_value(raw_value),
|
||||
error_message(error_message)
|
||||
{
|
||||
}
|
||||
token_type_e
|
||||
getType() const
|
||||
{
|
||||
return this->type;
|
||||
}
|
||||
std::string const&
|
||||
getValue() const
|
||||
{
|
||||
return this->value;
|
||||
}
|
||||
std::string const&
|
||||
getRawValue() const
|
||||
{
|
||||
return this->raw_value;
|
||||
}
|
||||
std::string const&
|
||||
getErrorMessage() const
|
||||
{
|
||||
return this->error_message;
|
||||
}
|
||||
bool
|
||||
operator==(Token const& rhs) const
|
||||
{
|
||||
// Ignore fields other than type and value
|
||||
return (
|
||||
(this->type != tt_bad) && (this->type == rhs.type) && (this->value == rhs.value));
|
||||
}
|
||||
bool
|
||||
isInteger() const
|
||||
{
|
||||
return this->type == tt_integer;
|
||||
}
|
||||
bool
|
||||
isWord() const
|
||||
{
|
||||
return this->type == tt_word;
|
||||
}
|
||||
bool
|
||||
isWord(std::string const& value) const
|
||||
{
|
||||
return this->type == tt_word && this->value == value;
|
||||
}
|
||||
|
||||
private:
|
||||
token_type_e type;
|
||||
std::string value;
|
||||
std::string raw_value;
|
||||
std::string error_message;
|
||||
};
|
||||
|
||||
QPDF_DLL
|
||||
QPDFTokenizer();
|
||||
|
||||
QPDF_DLL
|
||||
~QPDFTokenizer();
|
||||
|
||||
// If called, treat EOF as a separate token type instead of an error. This was introduced in
|
||||
// QPDF 4.1 to facilitate tokenizing content streams.
|
||||
QPDF_DLL
|
||||
void allowEOF();
|
||||
|
||||
// If called, readToken will return "ignorable" tokens for space and comments. This was added in
|
||||
// QPDF 8.
|
||||
QPDF_DLL
|
||||
void includeIgnorable();
|
||||
|
||||
// There are two modes of operation: push and pull. The pull method is easier but requires an
|
||||
// input source. The push method is more complicated but can be used to tokenize a stream of
|
||||
// incoming characters in a pipeline.
|
||||
|
||||
// Push mode:
|
||||
|
||||
// deprecated, please see <https:manual.qpdf.org/release-notes.html#r12-0-0-deprecate>
|
||||
|
||||
// Keep presenting characters with presentCharacter() and presentEOF() and calling getToken()
|
||||
// until getToken() returns true. When it does, be sure to check unread_ch and to unread ch if
|
||||
// it is true. If these are called when a token is available, an exception will be thrown.
|
||||
QPDF_DLL
|
||||
void presentCharacter(char ch);
|
||||
QPDF_DLL
|
||||
void presentEOF();
|
||||
|
||||
// If a token is available, return true and initialize token with the token, unread_char with
|
||||
// whether or not we have to unread the last character, and if unread_char, ch with the
|
||||
// character to unread.
|
||||
QPDF_DLL
|
||||
bool getToken(Token& token, bool& unread_char, char& ch);
|
||||
|
||||
// This function returns true of the current character is between tokens (i.e., white space that
|
||||
// is not part of a string) or is part of a comment. A tokenizing filter can call this to
|
||||
// determine whether to output the character.
|
||||
[[deprecated("see <https:manual.qpdf.org/release-notes.html#r12-0-0-deprecate>")]] QPDF_DLL bool
|
||||
betweenTokens();
|
||||
|
||||
// Pull mode:
|
||||
|
||||
// Read a token from an input source. Context describes the context in which the token is being
|
||||
// read and is used in the exception thrown if there is an error. After a token is read, the
|
||||
// position of the input source returned by input->tell() points to just after the token, and
|
||||
// the input source's "last offset" as returned by input->getLastOffset() points to the
|
||||
// beginning of the token.
|
||||
QPDF_DLL
|
||||
Token readToken(
|
||||
InputSource& input, std::string const& context, bool allow_bad = false, size_t max_len = 0);
|
||||
QPDF_DLL
|
||||
Token readToken(
|
||||
std::shared_ptr<InputSource> input,
|
||||
std::string const& context,
|
||||
bool allow_bad = false,
|
||||
size_t max_len = 0);
|
||||
|
||||
// Calling this method puts the tokenizer in a state for reading inline images. You should call
|
||||
// this method after reading the character following the ID operator. In that state, it will
|
||||
// return all data up to BUT NOT INCLUDING the next EI token. After you call this method, the
|
||||
// next call to readToken (or the token created next time getToken returns true) will either be
|
||||
// tt_inline_image or tt_bad. This is the only way readToken
|
||||
// returns a tt_inline_image token.
|
||||
QPDF_DLL
|
||||
void expectInlineImage(std::shared_ptr<InputSource> input);
|
||||
QPDF_DLL
|
||||
void expectInlineImage(InputSource& input);
|
||||
|
||||
private:
|
||||
friend class qpdf::impl::Parser;
|
||||
|
||||
QPDFTokenizer(QPDFTokenizer const&) = delete;
|
||||
QPDFTokenizer& operator=(QPDFTokenizer const&) = delete;
|
||||
|
||||
std::unique_ptr<qpdf::Tokenizer> m;
|
||||
};
|
||||
|
||||
#endif // QPDFTOKENIZER_HH
|
||||
@@ -0,0 +1,36 @@
|
||||
// Copyright (c) 2005-2021 Jay Berkenbilt
|
||||
// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger
|
||||
//
|
||||
// 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 QPDFUSAGE_HH
|
||||
#define QPDFUSAGE_HH
|
||||
|
||||
#include <qpdf/DLL.h>
|
||||
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
class QPDF_DLL_CLASS QPDFUsage: public std::runtime_error
|
||||
{
|
||||
public:
|
||||
QPDF_DLL
|
||||
QPDFUsage(std::string const& msg);
|
||||
~QPDFUsage() noexcept override = default;
|
||||
};
|
||||
|
||||
#endif // QPDFUSAGE_HH
|
||||
+455
@@ -0,0 +1,455 @@
|
||||
// Copyright (c) 2005-2021 Jay Berkenbilt
|
||||
// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger
|
||||
//
|
||||
// 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 QPDFWRITER_HH
|
||||
#define QPDFWRITER_HH
|
||||
|
||||
#include <qpdf/Constants.h>
|
||||
#include <qpdf/DLL.h>
|
||||
#include <qpdf/Types.h>
|
||||
|
||||
#include <qpdf/Buffer.hh>
|
||||
#include <qpdf/PDFVersion.hh>
|
||||
#include <qpdf/Pipeline.hh>
|
||||
#include <qpdf/Pl_Buffer.hh>
|
||||
#include <qpdf/QPDFObjGen.hh>
|
||||
#include <qpdf/QPDFObjectHandle.hh>
|
||||
#include <qpdf/QPDFXRefEntry.hh>
|
||||
|
||||
#include <bitset>
|
||||
#include <cstdio>
|
||||
#include <functional>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
namespace qpdf
|
||||
{
|
||||
class Writer;
|
||||
}
|
||||
|
||||
class QPDF;
|
||||
|
||||
// This class implements a simple writer for saving QPDF objects to new PDF files. See comments
|
||||
// through the header file for additional details.
|
||||
class QPDFWriter
|
||||
{
|
||||
public:
|
||||
// Construct a QPDFWriter object without specifying output. You must call one of the output
|
||||
// setting routines defined below.
|
||||
QPDF_DLL
|
||||
QPDFWriter(QPDF& pdf);
|
||||
|
||||
// Create a QPDFWriter object that writes its output to a file or to stdout. This is equivalent
|
||||
// to using the previous constructor and then calling setOutputFilename(). See
|
||||
// setOutputFilename() for details.
|
||||
QPDF_DLL
|
||||
QPDFWriter(QPDF& pdf, char const* filename);
|
||||
|
||||
// Create a QPDFWriter object that writes its output to an already open FILE*. This is
|
||||
// equivalent to calling the first constructor and then calling setOutputFile(). See
|
||||
// setOutputFile() for details.
|
||||
QPDF_DLL
|
||||
QPDFWriter(QPDF& pdf, char const* description, FILE* file, bool close_file);
|
||||
|
||||
~QPDFWriter() = default;
|
||||
|
||||
class QPDF_DLL_CLASS ProgressReporter
|
||||
{
|
||||
public:
|
||||
QPDF_DLL
|
||||
virtual ~ProgressReporter();
|
||||
|
||||
// This method is called with a value from 0 to 100 to indicate approximate progress through
|
||||
// the write process. See registerProgressReporter.
|
||||
virtual void reportProgress(int) = 0;
|
||||
};
|
||||
|
||||
// This is a progress reporter that takes a function. It is used by the C APIs, but it is
|
||||
// available if you want to just register a C function as a handler.
|
||||
class QPDF_DLL_CLASS FunctionProgressReporter: public ProgressReporter
|
||||
{
|
||||
public:
|
||||
QPDF_DLL
|
||||
FunctionProgressReporter(std::function<void(int)>);
|
||||
QPDF_DLL
|
||||
~FunctionProgressReporter() override;
|
||||
QPDF_DLL
|
||||
void reportProgress(int) override;
|
||||
|
||||
private:
|
||||
std::function<void(int)> handler;
|
||||
};
|
||||
|
||||
// Setting Output. Output may be set only one time. If you don't use the filename version of
|
||||
// the QPDFWriter constructor, you must call exactly one of these methods.
|
||||
|
||||
// Passing nullptr as filename means write to stdout. QPDFWriter will create a zero-length
|
||||
// output file upon construction. If write fails, the empty or partially written file will not
|
||||
// be deleted. This is by design: sometimes the partial file may be useful for tracking down
|
||||
// problems. If your application doesn't want the partially written file to be left behind, you
|
||||
// should delete it if the eventual call to write fails.
|
||||
QPDF_DLL
|
||||
void setOutputFilename(char const* filename);
|
||||
|
||||
// Write to the given FILE*, which must be opened by the caller. If close_file is true,
|
||||
// QPDFWriter will close the file. Otherwise, the caller must close the file. The file does not
|
||||
// need to be seekable; it will be written to in a single pass. It must be open in binary mode.
|
||||
QPDF_DLL
|
||||
void setOutputFile(char const* description, FILE* file, bool close_file);
|
||||
|
||||
// Indicate that QPDFWriter should create a memory buffer to contain the final PDF file. Obtain
|
||||
// the memory by calling getBuffer().
|
||||
QPDF_DLL
|
||||
void setOutputMemory();
|
||||
|
||||
// Return the buffer object containing the PDF file. If setOutputMemory() has been called, this
|
||||
// method may be called exactly one time after write() has returned. The caller is responsible
|
||||
// for deleting the buffer when done. See also getBufferSharedPointer().
|
||||
QPDF_DLL
|
||||
Buffer* getBuffer();
|
||||
|
||||
// Return getBuffer() in a shared pointer.
|
||||
QPDF_DLL
|
||||
std::shared_ptr<Buffer> getBufferSharedPointer();
|
||||
|
||||
// Supply your own pipeline object. Output will be written to this pipeline, and QPDFWriter
|
||||
// will call finish() on the pipeline. It is the caller's responsibility to manage the memory
|
||||
// for the pipeline. The pipeline is never deleted by QPDFWriter, which makes it possible for
|
||||
// you to call additional methods on the pipeline after the writing is finished.
|
||||
QPDF_DLL
|
||||
void setOutputPipeline(Pipeline*);
|
||||
|
||||
// Setting Parameters
|
||||
|
||||
// Set the value of object stream mode. In disable mode, we never generate any object streams.
|
||||
// In preserve mode, we preserve object stream structure from the original file. In generate
|
||||
// mode, we generate our own object streams. In all cases, we generate a conventional
|
||||
// cross-reference table if there are no object streams and a cross-reference stream if there
|
||||
// are object streams. The default is o_preserve.
|
||||
QPDF_DLL
|
||||
void setObjectStreamMode(qpdf_object_stream_e);
|
||||
|
||||
// Set value of stream data mode. This is an older interface. Instead of using this, prefer
|
||||
// setCompressStreams() and setDecodeLevel(). This method is retained for compatibility, but it
|
||||
// does not cover the full range of available configurations. The mapping between this and the
|
||||
// new methods is as follows:
|
||||
//
|
||||
// qpdf_s_uncompress:
|
||||
// setCompressStreams(false)
|
||||
// setDecodeLevel(qpdf_dl_generalized)
|
||||
// qpdf_s_preserve:
|
||||
// setCompressStreams(false)
|
||||
// setDecodeLevel(qpdf_dl_none)
|
||||
// qpdf_s_compress:
|
||||
// setCompressStreams(true)
|
||||
// setDecodeLevel(qpdf_dl_generalized)
|
||||
//
|
||||
// The default is qpdf_s_compress.
|
||||
QPDF_DLL
|
||||
void setStreamDataMode(qpdf_stream_data_e);
|
||||
|
||||
// If true, compress any uncompressed streams when writing them. Metadata streams are a special
|
||||
// case and are not compressed even if this is true. This is true by default for QPDFWriter. If
|
||||
// you want QPDFWriter to leave uncompressed streams uncompressed, pass false to this method.
|
||||
QPDF_DLL
|
||||
void setCompressStreams(bool);
|
||||
|
||||
// When QPDFWriter encounters streams, this parameter controls the behavior with respect to
|
||||
// attempting to apply any filters to the streams when copying to the output. The decode levels
|
||||
// are as follows:
|
||||
//
|
||||
// qpdf_dl_none: Do not attempt to apply any filters. Streams remain as they appear in the
|
||||
// original file. Note that uncompressed streams may still be compressed on output. You can
|
||||
// disable that by calling setCompressStreams(false).
|
||||
//
|
||||
// qpdf_dl_generalized: This is the default. QPDFWriter will apply LZWDecode, ASCII85Decode,
|
||||
// ASCIIHexDecode, and FlateDecode filters on the input. When combined with
|
||||
// setCompressStreams(true), which is the default, the effect of this is that streams filtered
|
||||
// with these older and less efficient filters will be recompressed with the Flate filter. By
|
||||
// default, as a special case, if a stream is already compressed with FlateDecode and
|
||||
// setCompressStreams is enabled, the original compressed data will be preserved. This behavior
|
||||
// can be overridden by calling setRecompressFlate(true).
|
||||
//
|
||||
// qpdf_dl_specialized: In addition to uncompressing the generalized compression formats,
|
||||
// supported non-lossy compression will also be decoded. At present, this includes the
|
||||
// RunLengthDecode filter.
|
||||
//
|
||||
// qpdf_dl_all: In addition to generalized and non-lossy specialized filters, supported lossy
|
||||
// compression filters will be applied. At present, this includes DCTDecode (JPEG) compression.
|
||||
// Note that compressing the resulting data with DCTDecode again will accumulate loss, so avoid
|
||||
// multiple compression and decompression cycles. This is mostly useful for retrieving image
|
||||
// data.
|
||||
QPDF_DLL
|
||||
void setDecodeLevel(qpdf_stream_decode_level_e);
|
||||
|
||||
// By default, when both the input and output contents of a stream are compressed with Flate,
|
||||
// qpdf does not uncompress and recompress the stream. Passing true here causes it to do so.
|
||||
// This can be useful if recompressing all streams with a higher compression level, which can be
|
||||
// set by calling the static method Pl_Flate::setCompressionLevel.
|
||||
QPDF_DLL
|
||||
void setRecompressFlate(bool);
|
||||
|
||||
// Set value of content stream normalization. The default is "false". If true, we attempt to
|
||||
// normalize newlines inside of content streams. Some constructs such as inline images may
|
||||
// thwart our efforts. There may be some cases where this can damage the content stream. This
|
||||
// flag should be used only for debugging and experimenting with PDF content streams. Never use
|
||||
// it for production files.
|
||||
QPDF_DLL
|
||||
void setContentNormalization(bool);
|
||||
|
||||
// Set QDF mode. QDF mode causes special "pretty printing" of PDF objects, adds comments for
|
||||
// easier perusing of files. Resulting PDF files can be edited in a text editor and then run
|
||||
// through fix-qdf to update cross reference tables and stream lengths.
|
||||
QPDF_DLL
|
||||
void setQDFMode(bool);
|
||||
|
||||
// Preserve unreferenced objects. The default behavior is to discard any object that is not
|
||||
// visited during a traversal of the object structure from the trailer.
|
||||
QPDF_DLL
|
||||
void setPreserveUnreferencedObjects(bool);
|
||||
|
||||
// Always write a newline before the endstream keyword. This helps with PDF/A compliance, though
|
||||
// it is not sufficient for it.
|
||||
QPDF_DLL
|
||||
void setNewlineBeforeEndstream(bool);
|
||||
|
||||
// Set the minimum PDF version. If the PDF version of the input file (or previously set minimum
|
||||
// version) is less than the version passed to this method, the PDF version of the output file
|
||||
// will be set to this value. If the original PDF file's version or previously set minimum
|
||||
// version is already this version or later, the original file's version will be used.
|
||||
// QPDFWriter automatically sets the minimum version to 1.4 when R3 encryption parameters are
|
||||
// used, and to 1.5 when object streams are used.
|
||||
QPDF_DLL
|
||||
void setMinimumPDFVersion(std::string const&, int extension_level = 0);
|
||||
QPDF_DLL
|
||||
void setMinimumPDFVersion(PDFVersion const&);
|
||||
|
||||
// Force the PDF version of the output file to be a given version. Use of this function may
|
||||
// create PDF files that will not work properly with older PDF viewers. When a PDF version is
|
||||
// set using this function, qpdf will use this version even if the file contains features that
|
||||
// are not supported in that version of PDF. In other words, you should only use this function
|
||||
// if you are sure the PDF file in question has no features of newer versions of PDF or if you
|
||||
// are willing to create files that old viewers may try to open but not be able to properly
|
||||
// interpret. If any encryption has been applied to the document either explicitly or by
|
||||
// preserving the encryption of the source document, forcing the PDF version to a value too low
|
||||
// to support that type of encryption will explicitly disable decryption. Additionally, forcing
|
||||
// to a version below 1.5 will disable object streams.
|
||||
QPDF_DLL
|
||||
void forcePDFVersion(std::string const&, int extension_level = 0);
|
||||
|
||||
// Provide additional text to insert in the PDF file somewhere near the beginning of the file.
|
||||
// This can be used to add comments to the beginning of a PDF file, for example, if those
|
||||
// comments are to be consumed by some other application. No checks are performed to ensure
|
||||
// that the text inserted here is valid PDF. If you want to insert multiline comments, you will
|
||||
// need to include \n in the string yourself and start each line with %. An extra newline will
|
||||
// be appended if one is not already present at the end of your text.
|
||||
QPDF_DLL
|
||||
void setExtraHeaderText(std::string const&);
|
||||
|
||||
// Causes a deterministic /ID value to be generated. When this is set, the current time and
|
||||
// output file name are not used as part of /ID generation. Instead, a digest of all significant
|
||||
// parts of the output file's contents is included in the /ID calculation. Use of a
|
||||
// deterministic /ID can be handy when it is desirable for a repeat of the same qpdf operation
|
||||
// on the same inputs being written to the same outputs with the same parameters to generate
|
||||
// exactly the same results. This feature is incompatible with encrypted files because, for
|
||||
// encrypted files, the /ID is generated before any part of the file is written since it is an
|
||||
// input to the encryption process.
|
||||
QPDF_DLL
|
||||
void setDeterministicID(bool);
|
||||
|
||||
// Cause a static /ID value to be generated. Use only in test suites. See also
|
||||
// setDeterministicID.
|
||||
QPDF_DLL
|
||||
void setStaticID(bool);
|
||||
|
||||
// Use a fixed initialization vector for AES-CBC encryption. This is not secure. It should be
|
||||
// used only in test suites for creating predictable encrypted output.
|
||||
QPDF_DLL
|
||||
void setStaticAesIV(bool);
|
||||
|
||||
// Suppress inclusion of comments indicating original object IDs when writing QDF files. This
|
||||
// can also be useful for testing, particularly when using comparison of two qdf files to
|
||||
// determine whether two PDF files have identical content.
|
||||
QPDF_DLL
|
||||
void setSuppressOriginalObjectIDs(bool);
|
||||
|
||||
// Preserve encryption. The default is true unless prefiltering, content normalization, or qdf
|
||||
// mode has been selected in which case encryption is never preserved. Encryption is also not
|
||||
// preserved if we explicitly set encryption parameters.
|
||||
QPDF_DLL
|
||||
void setPreserveEncryption(bool);
|
||||
|
||||
// Copy encryption parameters from another QPDF object. If you want to copy encryption from the
|
||||
// object you are writing, call setPreserveEncryption(true) instead.
|
||||
QPDF_DLL
|
||||
void copyEncryptionParameters(QPDF&);
|
||||
|
||||
// Set up for encrypted output. User and owner password both must be specified. Either or both
|
||||
// may be the empty string. Note that qpdf does not apply any special treatment to the empty
|
||||
// string, which makes it possible to create encrypted files with empty owner passwords and
|
||||
// non-empty user passwords or with the same password for both user and owner. Some PDF reading
|
||||
// products don't handle such files very well. Enabling encryption disables stream prefiltering
|
||||
// and content normalization. Note that setting R2 encryption parameters sets the PDF version
|
||||
// to at least 1.3, setting R3 encryption parameters pushes the PDF version number to at
|
||||
// least 1.4, setting R4 parameters pushes the version to at least 1.5, or if AES is used, 1.6,
|
||||
// and setting R5 or R6 parameters pushes the version to at least 1.7 with extension level 3.
|
||||
//
|
||||
// Note about Unicode passwords: the PDF specification requires passwords to be encoded with PDF
|
||||
// Doc encoding for R <= 4 and UTF-8 for R >= 5. In all cases, these methods take strings of
|
||||
// bytes as passwords. It is up to the caller to ensure that passwords are properly encoded. The
|
||||
// qpdf command-line tool tries to do this, as discussed in the manual. If you are doing this
|
||||
// from your own application, QUtil contains many transcoding functions that could be useful to
|
||||
// you, most notably utf8_to_pdf_doc.
|
||||
|
||||
// R2 uses RC4, which is a weak cryptographic algorithm. Don't use it unless you have to. See
|
||||
// "Weak Cryptography" in the manual. This encryption format is deprecated in the PDF 2.0
|
||||
// specification.
|
||||
QPDF_DLL
|
||||
void setR2EncryptionParametersInsecure(
|
||||
char const* user_password,
|
||||
char const* owner_password,
|
||||
bool allow_print,
|
||||
bool allow_modify,
|
||||
bool allow_extract,
|
||||
bool allow_annotate);
|
||||
// R3 uses RC4, which is a weak cryptographic algorithm. Don't use it unless you have to. See
|
||||
// "Weak Cryptography" in the manual. This encryption format is deprecated in the PDF 2.0
|
||||
// specification.
|
||||
QPDF_DLL
|
||||
void setR3EncryptionParametersInsecure(
|
||||
char const* user_password,
|
||||
char const* owner_password,
|
||||
bool allow_accessibility,
|
||||
bool allow_extract,
|
||||
bool allow_assemble,
|
||||
bool allow_annotate_and_form,
|
||||
bool allow_form_filling,
|
||||
bool allow_modify_other,
|
||||
qpdf_r3_print_e print);
|
||||
// When use_aes=false, this call enables R4 with RC4, which is a weak cryptographic algorithm.
|
||||
// Even with use_aes=true, the overall encryption scheme is weak. Don't use it unless you have
|
||||
// to. See "Weak Cryptography" in the manual. This encryption format is deprecated in the
|
||||
// PDF 2.0 specification.
|
||||
QPDF_DLL
|
||||
void setR4EncryptionParametersInsecure(
|
||||
char const* user_password,
|
||||
char const* owner_password,
|
||||
bool allow_accessibility,
|
||||
bool allow_extract,
|
||||
bool allow_assemble,
|
||||
bool allow_annotate_and_form,
|
||||
bool allow_form_filling,
|
||||
bool allow_modify_other,
|
||||
qpdf_r3_print_e print,
|
||||
bool encrypt_metadata,
|
||||
bool use_aes);
|
||||
// R5 is deprecated. Do not use it for production use. Writing R5 is supported by qpdf
|
||||
// primarily to generate test files for applications that may need to test R5 support.
|
||||
QPDF_DLL
|
||||
void setR5EncryptionParameters(
|
||||
char const* user_password,
|
||||
char const* owner_password,
|
||||
bool allow_accessibility,
|
||||
bool allow_extract,
|
||||
bool allow_assemble,
|
||||
bool allow_annotate_and_form,
|
||||
bool allow_form_filling,
|
||||
bool allow_modify_other,
|
||||
qpdf_r3_print_e print,
|
||||
bool encrypt_metadata);
|
||||
// This is the only password-based encryption format supported by the PDF specification.
|
||||
QPDF_DLL
|
||||
void setR6EncryptionParameters(
|
||||
char const* user_password,
|
||||
char const* owner_password,
|
||||
bool allow_accessibility,
|
||||
bool allow_extract,
|
||||
bool allow_assemble,
|
||||
bool allow_annotate_and_form,
|
||||
bool allow_form_filling,
|
||||
bool allow_modify_other,
|
||||
qpdf_r3_print_e print,
|
||||
bool encrypt_metadata_aes);
|
||||
|
||||
// Create linearized output. Disables qdf mode, content normalization, and stream prefiltering.
|
||||
QPDF_DLL
|
||||
void setLinearization(bool);
|
||||
|
||||
// For debugging QPDF: provide the name of a file to write pass1 of linearization to. The only
|
||||
// reason to use this is to debug QPDF. To linearize, QPDF writes out the file in two passes.
|
||||
// Usually the first pass is discarded, but lots of computations are made in pass 1. If a
|
||||
// linearized file comes out wrong, it can be helpful to look at the first pass.
|
||||
QPDF_DLL
|
||||
void setLinearizationPass1Filename(std::string const&);
|
||||
|
||||
// Create PCLm output. This is only useful for clients that know how to create PCLm files. If a
|
||||
// file is structured exactly as PCLm requires, this call will tell QPDFWriter to write the PCLm
|
||||
// header, create certain unreferenced streams required by the standard, and write the objects
|
||||
// in the required order. Calling this on an ordinary PDF serves no purpose. There is no
|
||||
// command-line argument that causes this method to be called.
|
||||
QPDF_DLL
|
||||
void setPCLm(bool);
|
||||
|
||||
// If you want to be notified of progress, derive a class from ProgressReporter and override the
|
||||
// reportProgress method.
|
||||
QPDF_DLL
|
||||
void registerProgressReporter(std::shared_ptr<ProgressReporter>);
|
||||
|
||||
// Return the PDF version that will be written into the header. Calling this method does all the
|
||||
// preparation for writing, so it is an error to call any methods that may cause a change to the
|
||||
// version. Adding new objects to the original file after calling this may also cause problems.
|
||||
// It is safe to update existing objects or stream contents after calling this method, e.g., to
|
||||
// include the final version number in metadata.
|
||||
QPDF_DLL
|
||||
std::string getFinalVersion();
|
||||
|
||||
// Write the final file. There is no expectation of being able to call write() more than once.
|
||||
QPDF_DLL
|
||||
void write();
|
||||
|
||||
// Return renumbered ObjGen that was written into the final file. This method can be used after
|
||||
// calling write().
|
||||
QPDF_DLL
|
||||
QPDFObjGen getRenumberedObjGen(QPDFObjGen);
|
||||
|
||||
// Return XRef entry that was written into the final file. This method can be used after calling
|
||||
// write().
|
||||
QPDF_DLL
|
||||
std::map<QPDFObjGen, QPDFXRefEntry> getWrittenXRefTable();
|
||||
|
||||
// The following structs / classes are not part of the public API.
|
||||
struct Object;
|
||||
struct NewObject;
|
||||
class ObjTable;
|
||||
class NewObjTable;
|
||||
|
||||
private:
|
||||
friend class qpdf::Writer;
|
||||
|
||||
class Members;
|
||||
|
||||
std::shared_ptr<Members> m;
|
||||
};
|
||||
|
||||
#endif // QPDFWRITER_HH
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
// Copyright (c) 2005-2021 Jay Berkenbilt
|
||||
// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger
|
||||
//
|
||||
// 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 QPDFXREFENTRY_HH
|
||||
#define QPDFXREFENTRY_HH
|
||||
|
||||
#include <qpdf/DLL.h>
|
||||
#include <qpdf/Types.h>
|
||||
|
||||
class QPDFXRefEntry
|
||||
{
|
||||
public:
|
||||
// Type constants are from the PDF spec section "Cross-Reference Streams":
|
||||
// 0 = free entry; not used
|
||||
// 1 = "uncompressed"; field 1 = offset
|
||||
// 2 = "compressed"; field 1 = object stream number, field 2 = index
|
||||
|
||||
// Create a type 0 "free" entry.
|
||||
QPDF_DLL
|
||||
QPDFXRefEntry();
|
||||
QPDF_DLL
|
||||
QPDFXRefEntry(int type, qpdf_offset_t field1, int field2);
|
||||
// Create a type 1 "uncompressed" entry.
|
||||
QPDFXRefEntry(qpdf_offset_t offset) :
|
||||
type(1),
|
||||
field1(offset)
|
||||
{
|
||||
}
|
||||
// Create a type 2 "compressed" entry.
|
||||
QPDFXRefEntry(int stream_number, int index) :
|
||||
type(2),
|
||||
field1(stream_number),
|
||||
field2(index)
|
||||
{
|
||||
}
|
||||
|
||||
QPDF_DLL
|
||||
int getType() const;
|
||||
QPDF_DLL
|
||||
qpdf_offset_t getOffset() const; // only for type 1
|
||||
QPDF_DLL
|
||||
int getObjStreamNumber() const; // only for type 2
|
||||
QPDF_DLL
|
||||
int getObjStreamIndex() const; // only for type 2
|
||||
|
||||
private:
|
||||
// This class does not use the Members pattern to avoid a memory allocation for every one of
|
||||
// these. A lot of these get created.
|
||||
|
||||
// The layout can be changed to reduce the size from 24 to 16 bytes. However, this would have a
|
||||
// definite runtime cost.
|
||||
int type{0};
|
||||
qpdf_offset_t field1{0};
|
||||
int field2{0};
|
||||
};
|
||||
|
||||
#endif // QPDFXREFENTRY_HH
|
||||
@@ -0,0 +1,43 @@
|
||||
// Copyright (c) 2005-2021 Jay Berkenbilt
|
||||
// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger
|
||||
//
|
||||
// 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 QTC_HH
|
||||
#define QTC_HH
|
||||
|
||||
#include <qpdf/DLL.h>
|
||||
|
||||
// Defining QPDF_DISABLE_QTC will effectively compile out any QTC::TC calls in any code that
|
||||
// includes this file, but QTC will still be built into the library. That way, it is possible to
|
||||
// build and package qpdf with QPDF_DISABLE_QTC while still making QTC::TC available to end users.
|
||||
|
||||
namespace QTC
|
||||
{
|
||||
QPDF_DLL
|
||||
void TC_real(char const* const scope, char const* const ccase, int n = 0);
|
||||
|
||||
inline void
|
||||
TC(char const* const scope, char const* const ccase, int n = 0)
|
||||
{
|
||||
#ifndef QPDF_DISABLE_QTC
|
||||
TC_real(scope, ccase, n);
|
||||
#endif // QPDF_DISABLE_QTC
|
||||
}
|
||||
}; // namespace QTC
|
||||
|
||||
#endif // QTC_HH
|
||||
@@ -0,0 +1,512 @@
|
||||
// Copyright (c) 2005-2021 Jay Berkenbilt
|
||||
// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger
|
||||
//
|
||||
// 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 QUTIL_HH
|
||||
#define QUTIL_HH
|
||||
|
||||
#include <qpdf/Constants.h>
|
||||
#include <qpdf/DLL.h>
|
||||
#include <qpdf/Types.h>
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <ctime>
|
||||
#include <functional>
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class RandomDataProvider;
|
||||
class Pipeline;
|
||||
|
||||
namespace QUtil
|
||||
{
|
||||
// This is a collection of useful utility functions that don't really go anywhere else.
|
||||
QPDF_DLL
|
||||
std::string int_to_string(long long, int length = 0);
|
||||
QPDF_DLL
|
||||
std::string uint_to_string(unsigned long long, int length = 0);
|
||||
QPDF_DLL
|
||||
std::string int_to_string_base(long long, int base, int length = 0);
|
||||
QPDF_DLL
|
||||
std::string uint_to_string_base(unsigned long long, int base, int length = 0);
|
||||
QPDF_DLL
|
||||
std::string double_to_string(double, int decimal_places = 0, bool trim_trailing_zeroes = true);
|
||||
|
||||
// These string to number methods throw std::runtime_error on underflow/overflow.
|
||||
QPDF_DLL
|
||||
long long string_to_ll(char const* str);
|
||||
QPDF_DLL
|
||||
int string_to_int(char const* str);
|
||||
QPDF_DLL
|
||||
unsigned long long string_to_ull(char const* str);
|
||||
QPDF_DLL
|
||||
unsigned int string_to_uint(char const* str);
|
||||
|
||||
// Returns true if this exactly represents a long long. The determination is made by converting
|
||||
// the string to a long long, then converting the result back to a string, and then comparing
|
||||
// that result with the original string.
|
||||
QPDF_DLL
|
||||
bool is_long_long(char const* str);
|
||||
|
||||
// Pipeline's write method wants unsigned char*, but we often have some other type of string.
|
||||
// These methods do combinations of const_cast and reinterpret_cast to give us an unsigned
|
||||
// char*. They should only be used when it is known that it is safe. None of the pipelines in
|
||||
// qpdf modify the data passed to them, so within qpdf, it should always be safe.
|
||||
QPDF_DLL
|
||||
unsigned char* unsigned_char_pointer(std::string const& str);
|
||||
QPDF_DLL
|
||||
unsigned char* unsigned_char_pointer(char const* str);
|
||||
|
||||
// Throw QPDFSystemError, which is derived from std::runtime_error, with a string formed by
|
||||
// appending to "description: " the standard string corresponding to the current value of errno.
|
||||
// You can retrieve the value of errno by calling getErrno() on the QPDFSystemError. Prior to
|
||||
// qpdf 8.2.0, this method threw system::runtime_error directly, but since QPDFSystemError is
|
||||
// derived from system::runtime_error, old code that specifically catches std::runtime_error
|
||||
// will still work.
|
||||
QPDF_DLL
|
||||
void throw_system_error(std::string const& description);
|
||||
|
||||
// The status argument is assumed to be the return value of a standard library call that sets
|
||||
// errno when it fails. If status is -1, convert the current value of errno to a
|
||||
// std::runtime_error that includes the standard error string. Otherwise, return status.
|
||||
QPDF_DLL
|
||||
int os_wrapper(std::string const& description, int status);
|
||||
|
||||
// If the open fails, throws std::runtime_error. Otherwise, the FILE* is returned. The filename
|
||||
// should be UTF-8 encoded, even on Windows. It will be converted as needed on Windows.
|
||||
QPDF_DLL
|
||||
FILE* safe_fopen(char const* filename, char const* mode);
|
||||
|
||||
// The FILE* argument is assumed to be the return of fopen. If null, throw std::runtime_error.
|
||||
// Otherwise, return the FILE* argument.
|
||||
QPDF_DLL
|
||||
FILE* fopen_wrapper(std::string const&, FILE*);
|
||||
|
||||
// This is a little class to help with automatic closing files. You can do something like
|
||||
//
|
||||
// QUtil::FileCloser fc(QUtil::safe_fopen(filename, "rb"));
|
||||
//
|
||||
// and then use fc.f to the file. Be sure to actually declare a variable of type FileCloser.
|
||||
// Using it as a temporary won't work because it will close the file as soon as it goes out of
|
||||
// scope.
|
||||
class FileCloser
|
||||
{
|
||||
public:
|
||||
FileCloser(FILE* f) :
|
||||
f(f)
|
||||
{
|
||||
}
|
||||
|
||||
~FileCloser()
|
||||
{
|
||||
if (f) {
|
||||
fclose(f);
|
||||
f = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
FILE* f;
|
||||
};
|
||||
|
||||
// Attempt to open the file read only and then close again
|
||||
QPDF_DLL
|
||||
bool file_can_be_opened(char const* filename);
|
||||
|
||||
// Wrap around off_t versions of fseek and ftell if available
|
||||
QPDF_DLL
|
||||
int seek(FILE* stream, qpdf_offset_t offset, int whence);
|
||||
QPDF_DLL
|
||||
qpdf_offset_t tell(FILE* stream);
|
||||
|
||||
QPDF_DLL
|
||||
bool same_file(char const* name1, char const* name2);
|
||||
|
||||
QPDF_DLL
|
||||
void remove_file(char const* path);
|
||||
|
||||
// rename_file will overwrite newname if it exists
|
||||
QPDF_DLL
|
||||
void rename_file(char const* oldname, char const* newname);
|
||||
|
||||
// Write the contents of filename as a binary file to the pipeline.
|
||||
QPDF_DLL
|
||||
void pipe_file(char const* filename, Pipeline* p);
|
||||
|
||||
// Return a function that will send the contents of the given file through the given pipeline as
|
||||
// binary data.
|
||||
QPDF_DLL
|
||||
std::function<void(Pipeline*)> file_provider(std::string const& filename);
|
||||
|
||||
// Return the last path element. On Windows, either / or \ are path separators. Otherwise, only
|
||||
// / is a path separator. Strip any trailing path separators. Then, if any path separators
|
||||
// remain, return everything after the last path separator. Otherwise, return the whole string.
|
||||
// As a special case, if a string consists entirely of path separators, the first character is
|
||||
// returned.
|
||||
QPDF_DLL
|
||||
std::string path_basename(std::string const& filename);
|
||||
|
||||
// Returns a dynamically allocated copy of a string that the caller has to delete with delete[].
|
||||
QPDF_DLL
|
||||
char* copy_string(std::string const&);
|
||||
|
||||
// Returns a shared_ptr<char> with the correct deleter.
|
||||
QPDF_DLL
|
||||
std::shared_ptr<char> make_shared_cstr(std::string const&);
|
||||
|
||||
// Copy string as a unique_ptr to an array.
|
||||
QPDF_DLL
|
||||
std::unique_ptr<char[]> make_unique_cstr(std::string const&);
|
||||
|
||||
// Create a shared pointer to an array. From c++20, std::make_shared<T[]>(n) does this.
|
||||
template <typename T>
|
||||
std::shared_ptr<T>
|
||||
make_shared_array(size_t n)
|
||||
{
|
||||
return std::shared_ptr<T>(new T[n], std::default_delete<T[]>());
|
||||
}
|
||||
|
||||
// Returns lower-case hex-encoded version of the string, treating each character in the input
|
||||
// string as unsigned. The output string will be twice as long as the input string.
|
||||
QPDF_DLL
|
||||
std::string hex_encode(std::string const&);
|
||||
|
||||
// Returns lower-case hex-encoded version of the char including a leading "#".
|
||||
QPDF_DLL
|
||||
std::string hex_encode_char(char);
|
||||
|
||||
// Returns a string that is the result of decoding the input string. The input string may
|
||||
// consist of mixed case hexadecimal digits. Any characters that are not hexadecimal digits will
|
||||
// be silently ignored. If there are an odd number of hexadecimal digits, a trailing 0 will be
|
||||
// assumed.
|
||||
QPDF_DLL
|
||||
std::string hex_decode(std::string const&);
|
||||
|
||||
// Decode a single hex digit into a char in the range 0 <= char < 16. Return a char >= 16 if
|
||||
// digit is not a valid hex digit.
|
||||
QPDF_DLL
|
||||
char hex_decode_char(char digit);
|
||||
|
||||
// Set stdin, stdout to binary mode
|
||||
QPDF_DLL
|
||||
void binary_stdout();
|
||||
QPDF_DLL
|
||||
void binary_stdin();
|
||||
// Set stdout to line buffered
|
||||
QPDF_DLL
|
||||
void setLineBuf(FILE*);
|
||||
|
||||
// May modify argv0
|
||||
QPDF_DLL
|
||||
char* getWhoami(char* argv0);
|
||||
|
||||
// Get the value of an environment variable in a portable fashion. Returns true iff the variable
|
||||
// is defined. If `value' is non-null, initializes it with the value of the variable.
|
||||
QPDF_DLL
|
||||
bool get_env(std::string const& var, std::string* value = nullptr);
|
||||
|
||||
QPDF_DLL
|
||||
time_t get_current_time();
|
||||
|
||||
// Portable structure representing a point in time with second granularity and time zone offset.
|
||||
struct QPDFTime
|
||||
{
|
||||
QPDFTime() = default;
|
||||
QPDFTime(QPDFTime const&) = default;
|
||||
QPDFTime& operator=(QPDFTime const&) = default;
|
||||
QPDFTime(int year, int month, int day, int hour, int minute, int second, int tz_delta) :
|
||||
year(year),
|
||||
month(month),
|
||||
day(day),
|
||||
hour(hour),
|
||||
minute(minute),
|
||||
second(second),
|
||||
tz_delta(tz_delta)
|
||||
{
|
||||
}
|
||||
int year; // actual year, no 1900 stuff
|
||||
int month; // 1--12
|
||||
int day; // 1--31
|
||||
int hour;
|
||||
int minute;
|
||||
int second;
|
||||
int tz_delta; // minutes before UTC
|
||||
};
|
||||
|
||||
QPDF_DLL
|
||||
QPDFTime get_current_qpdf_time();
|
||||
|
||||
// Convert a QPDFTime structure to a PDF timestamp string, which is "D:yyyymmddhhmmss<z>" where
|
||||
// <z> is either "Z" for UTC or "-hh'mm'" or "+hh'mm'" for timezone offset. <z> may also be
|
||||
// omitted.
|
||||
// Examples: "D:20210207161528-05'00'", "D:20210207211528Z", "D:20210207211528".
|
||||
// See get_current_qpdf_time and the QPDFTime structure above.
|
||||
QPDF_DLL
|
||||
std::string qpdf_time_to_pdf_time(QPDFTime const&);
|
||||
|
||||
// Convert QPDFTime to a second-granularity ISO-8601 timestamp.
|
||||
QPDF_DLL
|
||||
std::string qpdf_time_to_iso8601(QPDFTime const&);
|
||||
|
||||
// Convert a PDF timestamp string to a QPDFTime. If syntactically valid, return true and fill in
|
||||
// qtm. If not valid, return false, and do not modify qtm. If qtm is null, just check the
|
||||
// validity of the string.
|
||||
QPDF_DLL
|
||||
bool pdf_time_to_qpdf_time(std::string const&, QPDFTime* qtm = nullptr);
|
||||
|
||||
// Convert PDF timestamp to a second-granularity ISO-8601 timestamp. If syntactically valid,
|
||||
// return true and initialize iso8601. Otherwise, return false.
|
||||
bool pdf_time_to_iso8601(std::string const& pdf_time, std::string& iso8601);
|
||||
|
||||
// Return a string containing the byte representation of the UTF-8 encoding for the unicode
|
||||
// value passed in.
|
||||
QPDF_DLL
|
||||
std::string toUTF8(unsigned long uval);
|
||||
|
||||
// Return a string containing the byte representation of the UTF-16 big-endian encoding for the
|
||||
// unicode value passed in. Unrepresentable code points are converted to U+FFFD.
|
||||
QPDF_DLL
|
||||
std::string toUTF16(unsigned long uval);
|
||||
|
||||
// If utf8_val.at(pos) points to the beginning of a valid UTF-8-encoded character, return the
|
||||
// codepoint of the character and set error to false. Otherwise, return 0xfffd and set error to
|
||||
// true. In all cases, pos is advanced to the next position that may begin a valid character.
|
||||
// When the string has been consumed, pos will be set to the string length. It is an error to
|
||||
// pass a value of pos that is greater than or equal to the length of the string.
|
||||
QPDF_DLL
|
||||
unsigned long get_next_utf8_codepoint(std::string const& utf8_val, size_t& pos, bool& error);
|
||||
|
||||
// Test whether this is a UTF-16 string. This is indicated by first two bytes being 0xFE 0xFF
|
||||
// (big-endian) or 0xFF 0xFE (little-endian), each of which is the encoding of U+FEFF, the
|
||||
// Unicode marker. Starting in qpdf 10.6.2, this detects little-endian as well as big-endian.
|
||||
// Even though the PDF spec doesn't allow little-endian, most readers seem to accept it.
|
||||
QPDF_DLL
|
||||
bool is_utf16(std::string const&);
|
||||
|
||||
// Test whether this is an explicit UTF-8 string as allowed by the PDF 2.0 spec. This is
|
||||
// indicated by first three bytes being 0xEF 0xBB 0xBF, which is the UTF-8 encoding of U+FEFF.
|
||||
QPDF_DLL
|
||||
bool is_explicit_utf8(std::string const&);
|
||||
|
||||
// Convert a UTF-8 encoded string to UTF-16 big-endian. Unrepresentable code points are
|
||||
// converted to U+FFFD.
|
||||
QPDF_DLL
|
||||
std::string utf8_to_utf16(std::string const& utf8);
|
||||
|
||||
// Convert a UTF-8 encoded string to the specified single-byte encoding system by replacing all
|
||||
// unsupported characters with the given unknown_char.
|
||||
QPDF_DLL
|
||||
std::string utf8_to_ascii(std::string const& utf8, char unknown_char = '?');
|
||||
QPDF_DLL
|
||||
std::string utf8_to_win_ansi(std::string const& utf8, char unknown_char = '?');
|
||||
QPDF_DLL
|
||||
std::string utf8_to_mac_roman(std::string const& utf8, char unknown_char = '?');
|
||||
QPDF_DLL
|
||||
std::string utf8_to_pdf_doc(std::string const& utf8, char unknown_char = '?');
|
||||
|
||||
// These versions return true if the conversion was successful and false if any unrepresentable
|
||||
// characters were found and had to be substituted with the unknown character.
|
||||
QPDF_DLL
|
||||
bool utf8_to_ascii(std::string const& utf8, std::string& ascii, char unknown_char = '?');
|
||||
QPDF_DLL
|
||||
bool utf8_to_win_ansi(std::string const& utf8, std::string& win, char unknown_char = '?');
|
||||
QPDF_DLL
|
||||
bool utf8_to_mac_roman(std::string const& utf8, std::string& mac, char unknown_char = '?');
|
||||
QPDF_DLL
|
||||
bool utf8_to_pdf_doc(std::string const& utf8, std::string& pdfdoc, char unknown_char = '?');
|
||||
|
||||
// Convert a UTF-16 encoded string to UTF-8. Unrepresentable code
|
||||
// points are converted to U+FFFD.
|
||||
QPDF_DLL
|
||||
std::string utf16_to_utf8(std::string const& utf16);
|
||||
|
||||
// Convert from the specified single-byte encoding system to UTF-8. There is no ascii_to_utf8
|
||||
// because all ASCII strings are already valid UTF-8.
|
||||
QPDF_DLL
|
||||
std::string win_ansi_to_utf8(std::string const& win);
|
||||
QPDF_DLL
|
||||
std::string mac_roman_to_utf8(std::string const& mac);
|
||||
QPDF_DLL
|
||||
std::string pdf_doc_to_utf8(std::string const& pdfdoc);
|
||||
|
||||
// Analyze a string for encoding. We can't tell the difference between any single-byte
|
||||
// encodings, and we can't tell for sure whether a string that happens to be valid UTF-8 isn't a
|
||||
// different encoding, but we can at least tell a few things to help us guess. If there are no
|
||||
// characters with the high bit set, has_8bit_chars is false, and the other values are also
|
||||
// false, even though ASCII strings are valid UTF-8. is_valid_utf8 means that the string is
|
||||
// non-trivially valid UTF-8. Although the PDF spec requires UTF-16 to be UTF-16BE, qpdf (and
|
||||
// just about everything else) accepts UTF-16LE (as of 10.6.2).
|
||||
QPDF_DLL
|
||||
void analyze_encoding(
|
||||
std::string const& str, bool& has_8bit_chars, bool& is_valid_utf8, bool& is_utf16);
|
||||
|
||||
// Try to compensate for previously incorrectly encoded strings. We want to compensate for the
|
||||
// following errors:
|
||||
//
|
||||
// * The string was supposed to be UTF-8 but was one of the single-byte encodings
|
||||
// * The string was supposed to be PDF Doc but was either UTF-8 or one of the other single-byte
|
||||
// encodings
|
||||
//
|
||||
// The returned vector always contains the original string first, and then it contains what the
|
||||
// correct string would be in the event that the original string was the result of any of the
|
||||
// above errors.
|
||||
//
|
||||
// This method is useful for attempting to recover a password that may have been previously
|
||||
// incorrectly encoded. For example, the password was supposed to be UTF-8 but the previous
|
||||
// application used a password encoded in WinAnsi, or if the previous password was supposed to
|
||||
// be PDFDoc but was actually given as UTF-8 or WinAnsi, this method would find the correct
|
||||
// password.
|
||||
QPDF_DLL
|
||||
std::vector<std::string> possible_repaired_encodings(std::string);
|
||||
|
||||
// Return a cryptographically secure random number.
|
||||
QPDF_DLL
|
||||
long random();
|
||||
|
||||
// Initialize a buffer with cryptographically secure random bytes.
|
||||
QPDF_DLL
|
||||
void initializeWithRandomBytes(unsigned char* data, size_t len);
|
||||
|
||||
// Supply a random data provider. Starting in qpdf 10.0.0, qpdf uses the crypto provider as its
|
||||
// source of random numbers. If you are using the native crypto provider, then qpdf will either
|
||||
// use the operating system's secure random number source or, only if enabled at build time, an
|
||||
// insecure random source from stdlib. The caller is responsible for managing the memory for the
|
||||
// RandomDataProvider. This method modifies a static variable. If you are providing your own
|
||||
// random data provider, you should call this at the beginning of your program before creating
|
||||
// any QPDF objects. Passing a null to this method will reset the library back to its default
|
||||
// random data provider.
|
||||
QPDF_DLL
|
||||
void setRandomDataProvider(RandomDataProvider*);
|
||||
|
||||
// This returns the random data provider that would be used the next time qpdf needs random
|
||||
// data. It will never return null. If no random data provider has been provided and the
|
||||
// library was not compiled with any random data provider available, an exception will be
|
||||
// thrown.
|
||||
QPDF_DLL
|
||||
RandomDataProvider* getRandomDataProvider();
|
||||
|
||||
// Filename is UTF-8 encoded, even on Windows, as described in the comments for safe_fopen.
|
||||
QPDF_DLL
|
||||
std::list<std::string> read_lines_from_file(char const* filename, bool preserve_eol = false);
|
||||
QPDF_DLL
|
||||
std::list<std::string> read_lines_from_file(std::istream&, bool preserve_eol = false);
|
||||
QPDF_DLL
|
||||
std::list<std::string> read_lines_from_file(FILE*, bool preserve_eol = false);
|
||||
QPDF_DLL
|
||||
void read_lines_from_file(
|
||||
std::function<bool(char&)> next_char,
|
||||
std::list<std::string>& lines,
|
||||
bool preserve_eol = false);
|
||||
|
||||
QPDF_DLL
|
||||
void read_file_into_memory(char const* filename, std::shared_ptr<char>& file_buf, size_t& size);
|
||||
|
||||
QPDF_DLL
|
||||
std::string read_file_into_string(char const* filename);
|
||||
QPDF_DLL
|
||||
std::string read_file_into_string(FILE* f, std::string_view filename = "");
|
||||
|
||||
// This used to be called strcasecmp, but that is a macro on some platforms, so we have to give
|
||||
// it a name that is not likely to be a macro anywhere.
|
||||
QPDF_DLL
|
||||
int str_compare_nocase(char const*, char const*);
|
||||
|
||||
// These routines help the tokenizer recognize certain character classes without using ctype,
|
||||
// which we avoid because of locale considerations.
|
||||
QPDF_DLL
|
||||
bool is_hex_digit(char);
|
||||
|
||||
QPDF_DLL
|
||||
bool is_space(char);
|
||||
|
||||
QPDF_DLL
|
||||
bool is_digit(char);
|
||||
|
||||
QPDF_DLL
|
||||
bool is_number(char const*);
|
||||
|
||||
/// @brief Handles the result code from qpdf functions.
|
||||
///
|
||||
/// **For qpdf internal use only - not part of the public API**
|
||||
/// @par
|
||||
/// Depending on the result code, either continues execution or throws an
|
||||
/// exception in case of an invalid parameter.
|
||||
///
|
||||
/// @param result The result code of type qpdf_result_e, indicating success or failure status.
|
||||
/// @param context A string describing the context where this function is invoked, used for
|
||||
/// error reporting if an exception is thrown.
|
||||
///
|
||||
/// @throws std::logic_error If the result code is `qpdf_bad_parameter`, indicating an invalid
|
||||
/// parameter was supplied to a function. The exception message will
|
||||
/// include the provided context for easier debugging.
|
||||
///
|
||||
/// @since 12.3
|
||||
QPDF_DLL
|
||||
void handle_result_code(qpdf_result_e result, std::string_view context);
|
||||
|
||||
// This method parses the numeric range syntax used by the qpdf command-line tool. May throw
|
||||
// std::runtime_error. A numeric range is as comma-separated list of groups. A group may be a
|
||||
// number specification or a range of number specifications separated by a dash. A number
|
||||
// specification may be one of the following (where <n> is a number):
|
||||
// * <n> -- the numeric value of n
|
||||
// * z -- the value of the `max` parameter
|
||||
// * r<n> -- represents max + 1 - <n> (<n> from the end)
|
||||
//
|
||||
// If the group is two number specifications separated by a dash, it represents the range of
|
||||
// numbers from the first to the second, inclusive. If the first is greater than the second, the
|
||||
// numbers are descending.
|
||||
//
|
||||
// From qpdf 11.7.1: if a group starts with `x`, its members are excluded from the previous
|
||||
// group that didn't start with `x1.
|
||||
//
|
||||
// Example: with max of 15, the range "4-10,x7-9,12-8,xr5" is 4, 5, 6, 10, 12, 10, 9, 8. This is
|
||||
// 4 through 10 inclusive without 7 through 9 inclusive followed by 12 to 8 inclusive
|
||||
// (descending) without 11 (the fifth value counting backwards from 15). For more information
|
||||
// and additional examples, see the "Page Ranges" section in the manual.
|
||||
QPDF_DLL
|
||||
std::vector<int> parse_numrange(char const* range, int max);
|
||||
|
||||
#ifndef QPDF_NO_WCHAR_T
|
||||
// If you are building qpdf on a stripped down system that doesn't have wchar_t, such as may be
|
||||
// the case in some embedded environments, you may define QPDF_NO_WCHAR_T in your build. This
|
||||
// symbol is never defined automatically. Search for wchar_t in qpdf's top-level README.md file
|
||||
// for details.
|
||||
|
||||
// Take an argv array consisting of wchar_t, as when wmain is invoked, convert all UTF-16
|
||||
// encoded strings to UTF-8, and call another main.
|
||||
QPDF_DLL
|
||||
int call_main_from_wmain(int argc, wchar_t* argv[], std::function<int(int, char*[])> realmain);
|
||||
QPDF_DLL
|
||||
int call_main_from_wmain(
|
||||
int argc,
|
||||
wchar_t const* const argv[],
|
||||
std::function<int(int, char const* const[])> realmain);
|
||||
#endif // QPDF_NO_WCHAR_T
|
||||
|
||||
// Try to return the maximum amount of memory allocated by the current process and its threads.
|
||||
// Return 0 if unable to determine. This is Linux-specific and not implemented to be completely
|
||||
// reliable. It is used during development for performance testing to detect changes that may
|
||||
// significantly change memory usage. It is not recommended for use for other purposes.
|
||||
QPDF_DLL
|
||||
size_t get_max_memory_usage();
|
||||
}; // namespace QUtil
|
||||
|
||||
#endif // QUTIL_HH
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
// Copyright (c) 2005-2021 Jay Berkenbilt
|
||||
// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger
|
||||
//
|
||||
// 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 RANDOMDATAPROVIDER_HH
|
||||
#define RANDOMDATAPROVIDER_HH
|
||||
|
||||
#include <qpdf/DLL.h>
|
||||
#include <cstring> // for size_t
|
||||
|
||||
class QPDF_DLL_CLASS RandomDataProvider
|
||||
{
|
||||
public:
|
||||
virtual ~RandomDataProvider() = default;
|
||||
virtual void provideRandomData(unsigned char* data, size_t len) = 0;
|
||||
|
||||
protected:
|
||||
QPDF_DLL_PRIVATE
|
||||
RandomDataProvider() = default;
|
||||
|
||||
private:
|
||||
RandomDataProvider(RandomDataProvider const&) = delete;
|
||||
RandomDataProvider& operator=(RandomDataProvider const&) = delete;
|
||||
};
|
||||
|
||||
#endif // RANDOMDATAPROVIDER_HH
|
||||
@@ -0,0 +1,34 @@
|
||||
/* Copyright (c) 2005-2021 Jay Berkenbilt
|
||||
* Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger
|
||||
*
|
||||
* 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 QPDFTYPES_H
|
||||
#define QPDFTYPES_H
|
||||
|
||||
/* Provide an offset type that should be as big as off_t on just about
|
||||
* any system. If your compiler doesn't support C99 (or at least the
|
||||
* "long long" type), then you may have to modify this definition.
|
||||
*/
|
||||
|
||||
typedef long long int qpdf_offset_t;
|
||||
|
||||
#endif /* QPDFTYPES_H */
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
//
|
||||
// This file is automatically generated by generate_auto_job.
|
||||
// Edits will be automatically overwritten if the build is
|
||||
// run in maintainer mode.
|
||||
//
|
||||
// clang-format off
|
||||
//
|
||||
QPDF_DLL AttConfig* replace();
|
||||
QPDF_DLL AttConfig* key(std::string const& parameter);
|
||||
QPDF_DLL AttConfig* filename(std::string const& parameter);
|
||||
QPDF_DLL AttConfig* creationdate(std::string const& parameter);
|
||||
QPDF_DLL AttConfig* moddate(std::string const& parameter);
|
||||
QPDF_DLL AttConfig* mimetype(std::string const& parameter);
|
||||
QPDF_DLL AttConfig* description(std::string const& parameter);
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
//
|
||||
// This file is automatically generated by generate_auto_job.
|
||||
// Edits will be automatically overwritten if the build is
|
||||
// run in maintainer mode.
|
||||
//
|
||||
// clang-format off
|
||||
//
|
||||
QPDF_DLL CopyAttConfig* prefix(std::string const& parameter);
|
||||
QPDF_DLL CopyAttConfig* password(std::string const& parameter);
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
//
|
||||
// This file is automatically generated by generate_auto_job.
|
||||
// Edits will be automatically overwritten if the build is
|
||||
// run in maintainer mode.
|
||||
//
|
||||
// clang-format off
|
||||
//
|
||||
QPDF_DLL EncConfig* extract(std::string const& parameter);
|
||||
QPDF_DLL EncConfig* annotate(std::string const& parameter);
|
||||
QPDF_DLL EncConfig* print(std::string const& parameter);
|
||||
QPDF_DLL EncConfig* modify(std::string const& parameter);
|
||||
QPDF_DLL EncConfig* cleartextMetadata();
|
||||
QPDF_DLL EncConfig* forceV4();
|
||||
QPDF_DLL EncConfig* accessibility(std::string const& parameter);
|
||||
QPDF_DLL EncConfig* assemble(std::string const& parameter);
|
||||
QPDF_DLL EncConfig* form(std::string const& parameter);
|
||||
QPDF_DLL EncConfig* modifyOther(std::string const& parameter);
|
||||
QPDF_DLL EncConfig* useAes(std::string const& parameter);
|
||||
QPDF_DLL EncConfig* forceR5();
|
||||
QPDF_DLL EncConfig* allowInsecure();
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
//
|
||||
// This file is automatically generated by generate_auto_job.
|
||||
// Edits will be automatically overwritten if the build is
|
||||
// run in maintainer mode.
|
||||
//
|
||||
// clang-format off
|
||||
//
|
||||
QPDF_DLL GlobalConfig* noDefaultLimits();
|
||||
QPDF_DLL GlobalConfig* parserMaxContainerSize(std::string const& parameter);
|
||||
QPDF_DLL GlobalConfig* parserMaxContainerSizeDamaged(std::string const& parameter);
|
||||
QPDF_DLL GlobalConfig* parserMaxErrors(std::string const& parameter);
|
||||
QPDF_DLL GlobalConfig* parserMaxNesting(std::string const& parameter);
|
||||
QPDF_DLL GlobalConfig* maxStreamFilters(std::string const& parameter);
|
||||
+97
@@ -0,0 +1,97 @@
|
||||
//
|
||||
// This file is automatically generated by generate_auto_job.
|
||||
// Edits will be automatically overwritten if the build is
|
||||
// run in maintainer mode.
|
||||
//
|
||||
// clang-format off
|
||||
//
|
||||
QPDF_DLL Config* allowWeakCrypto();
|
||||
QPDF_DLL Config* check();
|
||||
QPDF_DLL Config* checkLinearization();
|
||||
QPDF_DLL Config* coalesceContents();
|
||||
QPDF_DLL Config* decrypt();
|
||||
QPDF_DLL Config* deterministicId();
|
||||
QPDF_DLL Config* externalizeInlineImages();
|
||||
QPDF_DLL Config* filteredStreamData();
|
||||
QPDF_DLL Config* flattenRotation();
|
||||
QPDF_DLL Config* generateAppearances();
|
||||
QPDF_DLL Config* ignoreXrefStreams();
|
||||
QPDF_DLL Config* isEncrypted();
|
||||
QPDF_DLL Config* jsonInput();
|
||||
QPDF_DLL Config* keepInlineImages();
|
||||
QPDF_DLL Config* linearize();
|
||||
QPDF_DLL Config* listAttachments();
|
||||
QPDF_DLL Config* newlineBeforeEndstream();
|
||||
QPDF_DLL Config* noOriginalObjectIds();
|
||||
QPDF_DLL Config* noWarn();
|
||||
QPDF_DLL Config* optimizeImages();
|
||||
QPDF_DLL Config* passwordIsHexKey();
|
||||
QPDF_DLL Config* preserveUnreferenced();
|
||||
QPDF_DLL Config* preserveUnreferencedResources();
|
||||
QPDF_DLL Config* progress();
|
||||
QPDF_DLL Config* qdf();
|
||||
QPDF_DLL Config* rawStreamData();
|
||||
QPDF_DLL Config* recompressFlate();
|
||||
QPDF_DLL Config* removeAcroform();
|
||||
QPDF_DLL Config* removeInfo();
|
||||
QPDF_DLL Config* removeMetadata();
|
||||
QPDF_DLL Config* removePageLabels();
|
||||
QPDF_DLL Config* removeStructure();
|
||||
QPDF_DLL Config* reportMemoryUsage();
|
||||
QPDF_DLL Config* requiresPassword();
|
||||
QPDF_DLL Config* removeRestrictions();
|
||||
QPDF_DLL Config* showEncryption();
|
||||
QPDF_DLL Config* showEncryptionKey();
|
||||
QPDF_DLL Config* showLinearization();
|
||||
QPDF_DLL Config* showNpages();
|
||||
QPDF_DLL Config* showPages();
|
||||
QPDF_DLL Config* showXref();
|
||||
QPDF_DLL Config* staticAesIv();
|
||||
QPDF_DLL Config* staticId();
|
||||
QPDF_DLL Config* suppressPasswordRecovery();
|
||||
QPDF_DLL Config* suppressRecovery();
|
||||
QPDF_DLL Config* testJsonSchema();
|
||||
QPDF_DLL Config* verbose();
|
||||
QPDF_DLL Config* warningExit0();
|
||||
QPDF_DLL Config* withImages();
|
||||
QPDF_DLL Config* compressionLevel(std::string const& parameter);
|
||||
QPDF_DLL Config* jpegQuality(std::string const& parameter);
|
||||
QPDF_DLL Config* copyEncryption(std::string const& parameter);
|
||||
QPDF_DLL Config* encryptionFilePassword(std::string const& parameter);
|
||||
QPDF_DLL Config* forceVersion(std::string const& parameter);
|
||||
QPDF_DLL Config* iiMinBytes(std::string const& parameter);
|
||||
QPDF_DLL Config* jobJsonFile(std::string const& parameter);
|
||||
QPDF_DLL Config* jsonObject(std::string const& parameter);
|
||||
QPDF_DLL Config* keepFilesOpenThreshold(std::string const& parameter);
|
||||
QPDF_DLL Config* linearizePass1(std::string const& parameter);
|
||||
QPDF_DLL Config* minVersion(std::string const& parameter);
|
||||
QPDF_DLL Config* oiMinArea(std::string const& parameter);
|
||||
QPDF_DLL Config* oiMinHeight(std::string const& parameter);
|
||||
QPDF_DLL Config* oiMinWidth(std::string const& parameter);
|
||||
QPDF_DLL Config* password(std::string const& parameter);
|
||||
QPDF_DLL Config* passwordFile(std::string const& parameter);
|
||||
QPDF_DLL Config* removeAttachment(std::string const& parameter);
|
||||
QPDF_DLL Config* rotate(std::string const& parameter);
|
||||
QPDF_DLL Config* showAttachment(std::string const& parameter);
|
||||
QPDF_DLL Config* showObject(std::string const& parameter);
|
||||
QPDF_DLL Config* jsonStreamPrefix(std::string const& parameter);
|
||||
QPDF_DLL Config* updateFromJson(std::string const& parameter);
|
||||
QPDF_DLL Config* collate(std::string const& parameter);
|
||||
QPDF_DLL Config* collate();
|
||||
QPDF_DLL Config* splitPages(std::string const& parameter);
|
||||
QPDF_DLL Config* splitPages();
|
||||
QPDF_DLL Config* compressStreams(std::string const& parameter);
|
||||
QPDF_DLL Config* decodeLevel(std::string const& parameter);
|
||||
QPDF_DLL Config* flattenAnnotations(std::string const& parameter);
|
||||
QPDF_DLL Config* jsonKey(std::string const& parameter);
|
||||
QPDF_DLL Config* jsonStreamData(std::string const& parameter);
|
||||
QPDF_DLL Config* keepFilesOpen(std::string const& parameter);
|
||||
QPDF_DLL Config* normalizeContent(std::string const& parameter);
|
||||
QPDF_DLL Config* objectStreams(std::string const& parameter);
|
||||
QPDF_DLL Config* passwordMode(std::string const& parameter);
|
||||
QPDF_DLL Config* removeUnreferencedResources(std::string const& parameter);
|
||||
QPDF_DLL Config* streamData(std::string const& parameter);
|
||||
QPDF_DLL Config* json(std::string const& parameter);
|
||||
QPDF_DLL Config* json();
|
||||
QPDF_DLL Config* jsonOutput(std::string const& parameter);
|
||||
QPDF_DLL Config* jsonOutput();
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
//
|
||||
// This file is automatically generated by generate_auto_job.
|
||||
// Edits will be automatically overwritten if the build is
|
||||
// run in maintainer mode.
|
||||
//
|
||||
// clang-format off
|
||||
//
|
||||
QPDF_DLL PagesConfig* file(std::string const& parameter);
|
||||
QPDF_DLL PagesConfig* range(std::string const& parameter);
|
||||
QPDF_DLL PagesConfig* password(std::string const& parameter);
|
||||
Vendored
+7
@@ -0,0 +1,7 @@
|
||||
//
|
||||
// This file is automatically generated by generate_auto_job.
|
||||
// Edits will be automatically overwritten if the build is
|
||||
// run in maintainer mode.
|
||||
//
|
||||
// clang-format off
|
||||
//
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
//
|
||||
// This file is automatically generated by generate_auto_job.
|
||||
// Edits will be automatically overwritten if the build is
|
||||
// run in maintainer mode.
|
||||
//
|
||||
// clang-format off
|
||||
//
|
||||
QPDF_DLL UOConfig* file(std::string const& parameter);
|
||||
QPDF_DLL UOConfig* to(std::string const& parameter);
|
||||
QPDF_DLL UOConfig* from(std::string const& parameter);
|
||||
QPDF_DLL UOConfig* repeat(std::string const& parameter);
|
||||
QPDF_DLL UOConfig* password(std::string const& parameter);
|
||||
@@ -0,0 +1,264 @@
|
||||
// Copyright (c) 2005-2021 Jay Berkenbilt
|
||||
// Copyright (c) 2022-2026 Jay Berkenbilt and Manfred Holger
|
||||
//
|
||||
// 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 GLOBAL_HH
|
||||
#define GLOBAL_HH
|
||||
|
||||
#include <qpdf/Constants.h>
|
||||
|
||||
#include <qpdf/QUtil.hh>
|
||||
#include <qpdf/qpdf-c.h>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace qpdf::global
|
||||
{
|
||||
/// Helper function to translate result codes into C++ exceptions - for qpdf internal use only.
|
||||
inline void
|
||||
handle_result(qpdf_result_e result)
|
||||
{
|
||||
if (result != qpdf_r_ok) {
|
||||
QUtil::handle_result_code(result, "qpdf::global");
|
||||
}
|
||||
}
|
||||
|
||||
/// Helper function to wrap calls to qpdf_global_get_uint32 - for qpdf internal use only.
|
||||
inline uint32_t
|
||||
get_uint32(qpdf_param_e param)
|
||||
{
|
||||
uint32_t value;
|
||||
handle_result(qpdf_global_get_uint32(param, &value));
|
||||
return value;
|
||||
}
|
||||
|
||||
/// Helper function to wrap calls to qpdf_global_set_uint32 - for qpdf internal use only.
|
||||
inline void
|
||||
set_uint32(qpdf_param_e param, uint32_t value)
|
||||
{
|
||||
handle_result(qpdf_global_set_uint32(param, value));
|
||||
}
|
||||
|
||||
/// @brief Retrieves the number of limit errors.
|
||||
///
|
||||
/// Returns the number of times a global limit was exceeded. This item is read only.
|
||||
///
|
||||
/// @return The number of limit errors.
|
||||
///
|
||||
/// @since 12.3
|
||||
uint32_t inline limit_errors()
|
||||
{
|
||||
return get_uint32(qpdf_p_limit_errors);
|
||||
}
|
||||
|
||||
namespace options
|
||||
{
|
||||
/// @brief Retrieves whether inspection mode is set.
|
||||
///
|
||||
/// @return True if inspection mode is set.
|
||||
///
|
||||
/// @since 12.3
|
||||
bool inline inspection_mode()
|
||||
{
|
||||
return get_uint32(qpdf_p_inspection_mode) != 0;
|
||||
}
|
||||
|
||||
/// @brief Set inspection mode if `true` is passed.
|
||||
///
|
||||
/// This function enables restrictive inspection mode if `true` is passed. Inspection mode
|
||||
/// must be enabled before a QPDF object is created. By default inspection mode is off.
|
||||
/// Calling `inspection_mode(false)` is not supported and currently is a no-op.
|
||||
///
|
||||
/// @param value A boolean indicating whether to enable (true) inspection mode.
|
||||
///
|
||||
/// @since 12.3
|
||||
void inline inspection_mode(bool value)
|
||||
{
|
||||
set_uint32(qpdf_p_inspection_mode, value ? QPDF_TRUE : QPDF_FALSE);
|
||||
}
|
||||
|
||||
/// @brief Retrieves whether default limits are enabled.
|
||||
///
|
||||
/// @return True if default limits are enabled.
|
||||
///
|
||||
/// @since 12.3
|
||||
bool inline default_limits()
|
||||
{
|
||||
return get_uint32(qpdf_p_default_limits) != 0;
|
||||
}
|
||||
|
||||
/// @brief Disable all optional default limits if `false` is passed.
|
||||
///
|
||||
/// This function disables all optional default limits if `false` is passed. Once default
|
||||
/// values have been disabled they cannot be re-enabled. Passing `true` has no effect. This
|
||||
/// function will leave any limits that have been explicitly set unchanged. Some limits,
|
||||
/// such as limits imposed to avoid stack overflows, cannot be disabled but can be changed.
|
||||
///
|
||||
/// @param value A boolean indicating whether to disable (false) the default limits.
|
||||
///
|
||||
/// @since 12.3
|
||||
void inline default_limits(bool value)
|
||||
{
|
||||
set_uint32(qpdf_p_default_limits, value ? QPDF_TRUE : QPDF_FALSE);
|
||||
}
|
||||
|
||||
} // namespace options
|
||||
|
||||
namespace limits
|
||||
{
|
||||
/// @brief Retrieves the maximum nesting level while parsing objects.
|
||||
///
|
||||
/// @return The maximum nesting level while parsing objects.
|
||||
///
|
||||
/// @note The maximum nesting level cannot be disabled by calling `default_limit(false)`.
|
||||
///
|
||||
/// @since 12.3
|
||||
uint32_t inline parser_max_nesting()
|
||||
{
|
||||
return get_uint32(qpdf_p_parser_max_nesting);
|
||||
}
|
||||
|
||||
/// @brief Sets the maximum nesting level while parsing objects.
|
||||
///
|
||||
/// @param value The maximum nesting level to set.
|
||||
///
|
||||
/// @note The maximum nesting level cannot be disabled by calling `default_limit(false)`.
|
||||
///
|
||||
/// @since 12.3
|
||||
void inline parser_max_nesting(uint32_t value)
|
||||
{
|
||||
set_uint32(qpdf_p_parser_max_nesting, value);
|
||||
}
|
||||
|
||||
/// @brief Retrieves the maximum number of errors allowed while parsing objects.
|
||||
///
|
||||
/// A value of 0 means that there is no maximum imposed.
|
||||
///
|
||||
/// @return The maximum number of errors allowed while parsing objects.
|
||||
///
|
||||
/// @since 12.3
|
||||
uint32_t inline parser_max_errors()
|
||||
{
|
||||
return get_uint32(qpdf_p_parser_max_errors);
|
||||
}
|
||||
|
||||
/// Sets the maximum number of errors allowed while parsing objects.
|
||||
///
|
||||
/// A value of 0 means that there is no maximum imposed.
|
||||
///
|
||||
/// @param value The maximum number of errors allowed while parsing objects to set.
|
||||
///
|
||||
/// @since 12.3
|
||||
void inline parser_max_errors(uint32_t value)
|
||||
{
|
||||
set_uint32(qpdf_p_parser_max_errors, value);
|
||||
}
|
||||
|
||||
/// @brief Retrieves the maximum number of top-level objects allowed in a container while
|
||||
/// parsing.
|
||||
///
|
||||
/// The limit applies when the PDF document's xref table is undamaged and the object itself
|
||||
/// can be parsed without errors. The default limit is 4,294,967,295.
|
||||
///
|
||||
/// @return The maximum number of top-level objects allowed in a container while parsing
|
||||
/// objects.
|
||||
///
|
||||
/// @since 12.3
|
||||
uint32_t inline parser_max_container_size()
|
||||
{
|
||||
return get_uint32(qpdf_p_parser_max_container_size);
|
||||
}
|
||||
|
||||
/// @brief Sets the maximum number of top-level objects allowed in a container while
|
||||
/// parsing.
|
||||
///
|
||||
/// The limit applies when the PDF document's xref table is undamaged and the object itself
|
||||
/// can be parsed without errors. The default limit is 4,294,967,295.
|
||||
///
|
||||
/// @param value The maximum number of top-level objects allowed in a container while
|
||||
/// parsing objects to set.
|
||||
///
|
||||
/// @since 12.3
|
||||
void inline parser_max_container_size(uint32_t value)
|
||||
{
|
||||
set_uint32(qpdf_p_parser_max_container_size, value);
|
||||
}
|
||||
|
||||
/// @brief Retrieves the maximum number of top-level objects allowed in a container while
|
||||
/// parsing objects.
|
||||
///
|
||||
/// The limit applies when the PDF document's xref table is damaged or the object itself is
|
||||
/// damaged. The limit also applies when parsing xref streams. The default limit is 5,000.
|
||||
///
|
||||
/// @return The maximum number of top-level objects allowed in a container while parsing
|
||||
/// objects.
|
||||
///
|
||||
/// @since 12.3
|
||||
uint32_t inline parser_max_container_size_damaged()
|
||||
{
|
||||
return get_uint32(qpdf_p_parser_max_container_size_damaged);
|
||||
}
|
||||
|
||||
/// @brief Sets the maximum number of top-level objects allowed in a container while
|
||||
/// parsing.
|
||||
///
|
||||
/// The limit applies when the PDF document's xref table is damaged or the object itself is
|
||||
/// damaged. The limit also applies when parsing trailer dictionaries and xref streams. The
|
||||
/// default limit is 5,000.
|
||||
///
|
||||
/// @param value The maximum number of top-level objects allowed in a container while
|
||||
/// parsing objects to set.
|
||||
///
|
||||
/// @since 12.3
|
||||
void inline parser_max_container_size_damaged(uint32_t value)
|
||||
{
|
||||
set_uint32(qpdf_p_parser_max_container_size_damaged, value);
|
||||
}
|
||||
|
||||
/// @brief Retrieves the maximum number of filters allowed when filtering streams.
|
||||
///
|
||||
/// An excessive number of stream filters is usually a sign that a file is damaged or
|
||||
/// specially constructed. If the maximum is exceeded for a stream the stream is treated as
|
||||
/// unfilterable. The default maximum is 25.
|
||||
///
|
||||
/// @return The maximum number of filters allowed when filtering streams.
|
||||
///
|
||||
/// @since 12.3
|
||||
uint32_t inline max_stream_filters()
|
||||
{
|
||||
return get_uint32(qpdf_p_max_stream_filters);
|
||||
}
|
||||
|
||||
/// @brief Sets the maximum number of filters allowed when filtering streams.
|
||||
///
|
||||
/// An excessive number of stream filters is usually a sign that a file is damaged or
|
||||
/// specially constructed. If the maximum is exceeded for a stream the stream is treated as
|
||||
/// unfilterable. The default maximum is 25.
|
||||
///
|
||||
/// @param value The maximum number of filters allowed when filtering streams to set.
|
||||
///
|
||||
/// @since 12.3
|
||||
void inline max_stream_filters(uint32_t value)
|
||||
{
|
||||
set_uint32(qpdf_p_max_stream_filters, value);
|
||||
}
|
||||
} // namespace limits
|
||||
|
||||
} // namespace qpdf::global
|
||||
|
||||
#endif // GLOBAL_HH
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user