2
1
mirror of https://github.com/qpdf/qpdf.git synced 2024-12-22 02:49:00 +00:00

Move QPDF inner class definitions to new QPDF_private.hh

This commit is contained in:
m-holger 2024-07-05 14:09:43 +01:00
parent d42fda60d5
commit f8e6274a2e
11 changed files with 597 additions and 576 deletions

View File

@ -725,165 +725,14 @@ class QPDF
void removePage(QPDFObjectHandle page);
// End legacy page helpers
// Writer class is restricted to QPDFWriter so that only it can call certain methods.
class Writer
{
friend class QPDFWriter;
// End of the public API. The following classes and methods are for qpdf internal use only.
private:
static void
optimize(
QPDF& qpdf,
QPDFWriter::ObjTable const& obj,
std::function<int(QPDFObjectHandle&)> skip_stream_parameters)
{
return qpdf.optimize(obj, skip_stream_parameters);
}
static void
getLinearizedParts(
QPDF& qpdf,
QPDFWriter::ObjTable const& obj,
std::vector<QPDFObjectHandle>& part4,
std::vector<QPDFObjectHandle>& part6,
std::vector<QPDFObjectHandle>& part7,
std::vector<QPDFObjectHandle>& part8,
std::vector<QPDFObjectHandle>& part9)
{
qpdf.getLinearizedParts(obj, part4, part6, part7, part8, part9);
}
static void
generateHintStream(
QPDF& qpdf,
QPDFWriter::NewObjTable const& new_obj,
QPDFWriter::ObjTable const& obj,
std::shared_ptr<Buffer>& hint_stream,
int& S,
int& O,
bool compressed)
{
return qpdf.generateHintStream(new_obj, obj, hint_stream, S, O, compressed);
}
static std::vector<QPDFObjGen>
getCompressibleObjGens(QPDF& qpdf)
{
return qpdf.getCompressibleObjVector();
}
static std::vector<bool>
getCompressibleObjSet(QPDF& qpdf)
{
return qpdf.getCompressibleObjSet();
}
static std::map<QPDFObjGen, QPDFXRefEntry> const&
getXRefTable(QPDF& qpdf)
{
return qpdf.getXRefTableInternal();
}
static size_t
tableSize(QPDF& qpdf)
{
return qpdf.tableSize();
}
};
// The Resolver class is restricted to QPDFObject so that only it can resolve indirect
// references.
class Resolver
{
friend class QPDFObject;
friend class QPDF_Unresolved;
private:
static QPDFObject*
resolved(QPDF* qpdf, QPDFObjGen og)
{
return qpdf->resolve(og);
}
};
// StreamCopier class is restricted to QPDFObjectHandle so it can copy stream data.
class StreamCopier
{
friend class QPDFObjectHandle;
private:
static void
copyStreamData(QPDF* qpdf, QPDFObjectHandle const& dest, QPDFObjectHandle const& src)
{
qpdf->copyStreamData(dest, src);
}
};
// The ParseGuard class allows QPDFParser to detect re-entrant parsing. It also provides
// special access to allow the parser to create unresolved objects and dangling references.
class ParseGuard
{
friend class QPDFParser;
private:
ParseGuard(QPDF* qpdf) :
qpdf(qpdf)
{
if (qpdf) {
qpdf->inParse(true);
}
}
static std::shared_ptr<QPDFObject>
getObject(QPDF* qpdf, int id, int gen, bool parse_pdf)
{
return qpdf->getObjectForParser(id, gen, parse_pdf);
}
~ParseGuard()
{
if (qpdf) {
qpdf->inParse(false);
}
}
QPDF* qpdf;
};
// Pipe class is restricted to QPDF_Stream.
class Pipe
{
friend class QPDF_Stream;
private:
static bool
pipeStreamData(
QPDF* qpdf,
QPDFObjGen const& og,
qpdf_offset_t offset,
size_t length,
QPDFObjectHandle dict,
Pipeline* pipeline,
bool suppress_warnings,
bool will_retry)
{
return qpdf->pipeStreamData(
og, offset, length, dict, pipeline, suppress_warnings, will_retry);
}
};
// JobSetter class is restricted to QPDFJob.
class JobSetter
{
friend class QPDFJob;
private:
// Enable enhanced warnings for pdf file checking.
static void
setCheckMode(QPDF& qpdf, bool val)
{
qpdf.m->check_mode = val;
}
};
class Writer;
class Resolver;
class StreamCopier;
class ParseGuard;
class Pipe;
class JobSetter;
// For testing only -- do not add to DLL
static bool test_json_validators();
@ -898,136 +747,13 @@ class QPDF
static std::string const qpdf_version;
class ObjCache
{
public:
ObjCache() :
end_before_space(0),
end_after_space(0)
{
}
ObjCache(
std::shared_ptr<QPDFObject> object,
qpdf_offset_t end_before_space = 0,
qpdf_offset_t end_after_space = 0) :
object(object),
end_before_space(end_before_space),
end_after_space(end_after_space)
{
}
std::shared_ptr<QPDFObject> object;
qpdf_offset_t end_before_space;
qpdf_offset_t end_after_space;
};
class ObjCopier
{
public:
std::map<QPDFObjGen, QPDFObjectHandle> object_map;
std::vector<QPDFObjectHandle> to_copy;
QPDFObjGen::set visiting;
};
class EncryptionParameters
{
friend class QPDF;
public:
EncryptionParameters();
private:
bool encrypted;
bool encryption_initialized;
int encryption_V;
int encryption_R;
bool encrypt_metadata;
std::map<std::string, encryption_method_e> crypt_filters;
encryption_method_e cf_stream;
encryption_method_e cf_string;
encryption_method_e cf_file;
std::string provided_password;
std::string user_password;
std::string encryption_key;
std::string cached_object_encryption_key;
QPDFObjGen cached_key_og;
bool user_password_matched;
bool owner_password_matched;
};
class ForeignStreamData
{
friend class QPDF;
public:
ForeignStreamData(
std::shared_ptr<EncryptionParameters> encp,
std::shared_ptr<InputSource> file,
QPDFObjGen const& foreign_og,
qpdf_offset_t offset,
size_t length,
QPDFObjectHandle local_dict);
private:
std::shared_ptr<EncryptionParameters> encp;
std::shared_ptr<InputSource> file;
QPDFObjGen foreign_og;
qpdf_offset_t offset;
size_t length;
QPDFObjectHandle local_dict;
};
class CopiedStreamDataProvider: public QPDFObjectHandle::StreamDataProvider
{
public:
CopiedStreamDataProvider(QPDF& destination_qpdf);
~CopiedStreamDataProvider() override = default;
bool provideStreamData(
QPDFObjGen const& og,
Pipeline* pipeline,
bool suppress_warnings,
bool will_retry) override;
void registerForeignStream(QPDFObjGen const& local_og, QPDFObjectHandle foreign_stream);
void registerForeignStream(QPDFObjGen const& local_og, std::shared_ptr<ForeignStreamData>);
private:
QPDF& destination_qpdf;
std::map<QPDFObjGen, QPDFObjectHandle> foreign_streams;
std::map<QPDFObjGen, std::shared_ptr<ForeignStreamData>> foreign_stream_data;
};
class StringDecrypter: public QPDFObjectHandle::StringDecrypter
{
friend class QPDF;
public:
StringDecrypter(QPDF* qpdf, QPDFObjGen const& og);
~StringDecrypter() override = default;
void decryptString(std::string& val) override;
private:
QPDF* qpdf;
QPDFObjGen og;
};
class ResolveRecorder
{
public:
ResolveRecorder(QPDF* qpdf, QPDFObjGen const& og) :
qpdf(qpdf),
iter(qpdf->m->resolving.insert(og).first)
{
}
virtual ~ResolveRecorder()
{
this->qpdf->m->resolving.erase(iter);
}
private:
QPDF* qpdf;
std::set<QPDFObjGen>::const_iterator iter;
};
class ObjCache;
class ObjCopier;
class EncryptionParameters;
class ForeignStreamData;
class CopiedStreamDataProvider;
class StringDecrypter;
class ResolveRecorder;
class JSONReactor;
void parse(char const* password);
@ -1196,200 +922,19 @@ class QPDF
replaceForeignIndirectObjects(QPDFObjectHandle foreign, ObjCopier& obj_copier, bool top);
void copyStreamData(QPDFObjectHandle dest_stream, QPDFObjectHandle src_stream);
// Linearization Hint table structures.
// Naming conventions:
// HSomething is the Something Hint Table or table header
// HSomethingEntry is an entry in the Something table
// delta_something + min_something = something
// nbits_something = number of bits required for something
// something_offset is the pre-adjusted offset in the file. If >=
// H0_offset, H0_length must be added to get an actual file
// offset.
// PDF 1.4: Table F.4
struct HPageOffsetEntry
{
int delta_nobjects{0}; // 1
qpdf_offset_t delta_page_length{0}; // 2
// vectors' sizes = nshared_objects
int nshared_objects{0}; // 3
std::vector<int> shared_identifiers; // 4
std::vector<int> shared_numerators; // 5
qpdf_offset_t delta_content_offset{0}; // 6
qpdf_offset_t delta_content_length{0}; // 7
};
// PDF 1.4: Table F.3
struct HPageOffset
{
int min_nobjects{0}; // 1
qpdf_offset_t first_page_offset{0}; // 2
int nbits_delta_nobjects{0}; // 3
int min_page_length{0}; // 4
int nbits_delta_page_length{0}; // 5
int min_content_offset{0}; // 6
int nbits_delta_content_offset{0}; // 7
int min_content_length{0}; // 8
int nbits_delta_content_length{0}; // 9
int nbits_nshared_objects{0}; // 10
int nbits_shared_identifier{0}; // 11
int nbits_shared_numerator{0}; // 12
int shared_denominator{0}; // 13
// vector size is npages
std::vector<HPageOffsetEntry> entries;
};
// PDF 1.4: Table F.6
struct HSharedObjectEntry
{
// Item 3 is a 128-bit signature (unsupported by Acrobat)
int delta_group_length{0}; // 1
int signature_present{0}; // 2 -- always 0
int nobjects_minus_one{0}; // 4 -- always 0
};
// PDF 1.4: Table F.5
struct HSharedObject
{
int first_shared_obj{0}; // 1
qpdf_offset_t first_shared_offset{0}; // 2
int nshared_first_page{0}; // 3
int nshared_total{0}; // 4
int nbits_nobjects{0}; // 5
int min_group_length{0}; // 6
int nbits_delta_group_length{0}; // 7
// vector size is nshared_total
std::vector<HSharedObjectEntry> entries;
};
// PDF 1.4: Table F.9
struct HGeneric
{
int first_object{0}; // 1
qpdf_offset_t first_object_offset{0}; // 2
int nobjects{0}; // 3
int group_length{0}; // 4
};
// Other linearization data structures
// Initialized from Linearization Parameter dictionary
struct LinParameters
{
qpdf_offset_t file_size{0}; // /L
int first_page_object{0}; // /O
qpdf_offset_t first_page_end{0}; // /E
int npages{0}; // /N
qpdf_offset_t xref_zero_offset{0}; // /T
int first_page{0}; // /P
qpdf_offset_t H_offset{0}; // offset of primary hint stream
qpdf_offset_t H_length{0}; // length of primary hint stream
};
// Computed hint table value data structures. These tables contain the computed values on which
// the hint table values are based. They exclude things like number of bits and store actual
// values instead of mins and deltas. File offsets are also absolute rather than being offset
// by the size of the primary hint table. We populate the hint table structures from these
// during writing and compare the hint table values with these during validation. We ignore
// some values for various reasons described in the code. Those values are omitted from these
// structures. Note also that object numbers are object numbers from the input file, not the
// output file.
// Naming convention: CHSomething is analogous to HSomething above. "CH" is computed hint.
struct CHPageOffsetEntry
{
int nobjects{0};
int nshared_objects{0};
// vectors' sizes = nshared_objects
std::vector<int> shared_identifiers;
};
struct CHPageOffset
{
// vector size is npages
std::vector<CHPageOffsetEntry> entries;
};
struct CHSharedObjectEntry
{
CHSharedObjectEntry(int object) :
object(object)
{
}
int object;
};
// PDF 1.4: Table F.5
struct CHSharedObject
{
int first_shared_obj{0};
int nshared_first_page{0};
int nshared_total{0};
// vector size is nshared_total
std::vector<CHSharedObjectEntry> entries;
};
// No need for CHGeneric -- HGeneric is fine as is.
// Data structures to support optimization -- implemented in QPDF_optimization.cc
class ObjUser
{
public:
enum user_e { ou_bad, ou_page, ou_thumb, ou_trailer_key, ou_root_key, ou_root };
// type is set to ou_bad
ObjUser();
// type must be ou_root
ObjUser(user_e type);
// type must be one of ou_page or ou_thumb
ObjUser(user_e type, int pageno);
// type must be one of ou_trailer_key or ou_root_key
ObjUser(user_e type, std::string const& key);
bool operator<(ObjUser const&) const;
user_e ou_type;
int pageno; // if ou_page;
std::string key; // if ou_trailer_key or ou_root_key
};
struct UpdateObjectMapsFrame
{
UpdateObjectMapsFrame(ObjUser const& ou, QPDFObjectHandle oh, bool top);
ObjUser const& ou;
QPDFObjectHandle oh;
bool top;
};
class PatternFinder: public InputSource::Finder
{
public:
PatternFinder(QPDF& qpdf, bool (QPDF::*checker)()) :
qpdf(qpdf),
checker(checker)
{
}
~PatternFinder() override = default;
bool
check() override
{
return (this->qpdf.*checker)();
}
private:
QPDF& qpdf;
bool (QPDF::*checker)();
};
struct HPageOffsetEntry;
struct HPageOffset;
struct HSharedObjectEntry;
struct HSharedObject;
struct HGeneric;
struct LinParameters;
struct CHPageOffsetEntry;
struct CHPageOffset;
struct CHSharedObjectEntry;
struct CHSharedObject;
class ObjUser;
struct UpdateObjectMapsFrame;
class PatternFinder;
// Methods to support pattern finding
static bool validatePDFVersion(char const*&, std::string& version);
@ -1486,90 +1031,7 @@ class QPDF
return QIntC::to_ulonglong(i);
}
class Members
{
friend class QPDF;
friend class ResolveRecorder;
public:
QPDF_DLL
~Members() = default;
private:
Members();
Members(Members const&) = delete;
std::shared_ptr<QPDFLogger> log;
unsigned long long unique_id{0};
QPDFTokenizer tokenizer;
std::shared_ptr<InputSource> file;
std::string last_object_description;
bool provided_password_is_hex_key{false};
bool ignore_xref_streams{false};
bool suppress_warnings{false};
size_t max_warnings{0};
bool attempt_recovery{true};
bool check_mode{false};
std::shared_ptr<EncryptionParameters> encp;
std::string pdf_version;
std::map<QPDFObjGen, QPDFXRefEntry> xref_table;
// Various tables are indexed by object id, with potential size id + 1
int xref_table_max_id{std::numeric_limits<int>::max() - 1};
qpdf_offset_t xref_table_max_offset{0};
std::set<int> deleted_objects;
std::map<QPDFObjGen, ObjCache> obj_cache;
std::set<QPDFObjGen> resolving;
QPDFObjectHandle trailer;
std::vector<QPDFObjectHandle> all_pages;
bool invalid_page_found{false};
std::map<QPDFObjGen, int> pageobj_to_pages_pos;
bool pushed_inherited_attributes_to_pages{false};
bool ever_pushed_inherited_attributes_to_pages{false};
bool ever_called_get_all_pages{false};
std::vector<QPDFExc> warnings;
std::map<unsigned long long, ObjCopier> object_copiers;
std::shared_ptr<QPDFObjectHandle::StreamDataProvider> copied_streams;
// copied_stream_data_provider is owned by copied_streams
CopiedStreamDataProvider* copied_stream_data_provider{nullptr};
bool reconstructed_xref{false};
bool fixed_dangling_refs{false};
bool immediate_copy_from{false};
bool in_parse{false};
bool parsed{false};
std::set<int> resolved_object_streams;
// Linearization data
qpdf_offset_t first_xref_item_offset{0}; // actual value from file
bool uncompressed_after_compressed{false};
bool linearization_warnings{false};
// Linearization parameter dictionary and hint table data: may be read from file or computed
// prior to writing a linearized file
QPDFObjectHandle lindict;
LinParameters linp;
HPageOffset page_offset_hints;
HSharedObject shared_object_hints;
HGeneric outline_hints;
// Computed linearization data: used to populate above tables during writing and to compare
// with them during validation. c_ means computed.
LinParameters c_linp;
CHPageOffset c_page_offset_data;
CHSharedObject c_shared_object_data;
HGeneric c_outline_data;
// Object ordering data for linearized files: initialized by calculateLinearizationData().
// Part numbers refer to the PDF 1.4 specification.
std::vector<QPDFObjectHandle> part4;
std::vector<QPDFObjectHandle> part6;
std::vector<QPDFObjectHandle> part7;
std::vector<QPDFObjectHandle> part8;
std::vector<QPDFObjectHandle> part9;
// Optimization data
std::map<ObjUser, std::set<QPDFObjGen>> obj_user_to_objects;
std::map<QPDFObjGen, std::set<ObjUser>> object_to_obj_users;
};
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.

View File

@ -1,6 +1,6 @@
#include <qpdf/qpdf-config.h> // include first for large file support
#include <qpdf/QPDF.hh>
#include <qpdf/QPDF_private.hh>
#include <array>
#include <atomic>

View File

@ -13,7 +13,6 @@
#include <qpdf/Pl_StdioFile.hh>
#include <qpdf/Pl_String.hh>
#include <qpdf/QIntC.hh>
#include <qpdf/QPDF.hh>
#include <qpdf/QPDFAcroFormDocumentHelper.hh>
#include <qpdf/QPDFCryptoProvider.hh>
#include <qpdf/QPDFEmbeddedFileDocumentHelper.hh>
@ -26,6 +25,7 @@
#include <qpdf/QPDFSystemError.hh>
#include <qpdf/QPDFUsage.hh>
#include <qpdf/QPDFWriter.hh>
#include <qpdf/QPDF_private.hh>
#include <qpdf/QTC.hh>
#include <qpdf/QUtil.hh>

View File

@ -14,10 +14,10 @@
#include <qpdf/Pl_RC4.hh>
#include <qpdf/Pl_StdioFile.hh>
#include <qpdf/QIntC.hh>
#include <qpdf/QPDF.hh>
#include <qpdf/QPDFObjectHandle.hh>
#include <qpdf/QPDF_Name.hh>
#include <qpdf/QPDF_String.hh>
#include <qpdf/QPDF_private.hh>
#include <qpdf/QTC.hh>
#include <qpdf/QUtil.hh>
#include <qpdf/RC4.hh>

View File

@ -10,8 +10,8 @@
#include <qpdf/Pl_Flate.hh>
#include <qpdf/Pl_QPDFTokenizer.hh>
#include <qpdf/QIntC.hh>
#include <qpdf/QPDF.hh>
#include <qpdf/QPDFExc.hh>
#include <qpdf/QPDF_private.hh>
#include <qpdf/QTC.hh>
#include <qpdf/QUtil.hh>
#include <qpdf/SF_ASCII85Decode.hh>

View File

@ -3,7 +3,7 @@
#include <qpdf/assert_debug.h>
#include <qpdf/QPDF.hh>
#include <qpdf/QPDF_private.hh>
#include <qpdf/QPDFExc.hh>

View File

@ -1,6 +1,6 @@
// See doc/linearization.
#include <qpdf/QPDF.hh>
#include <qpdf/QPDF_private.hh>
#include <qpdf/BitStream.hh>
#include <qpdf/BitWriter.hh>

View File

@ -2,7 +2,7 @@
#include <qpdf/assert_debug.h>
#include <qpdf/QPDF.hh>
#include <qpdf/QPDF_private.hh>
#include <qpdf/QPDFExc.hh>
#include <qpdf/QPDFWriter_private.hh>

View File

@ -1,4 +1,4 @@
#include <qpdf/QPDF.hh>
#include <qpdf/QPDF_private.hh>
#include <qpdf/QPDFExc.hh>
#include <qpdf/QTC.hh>

View File

@ -6,14 +6,13 @@
#include <qpdf/Constants.h>
#include <qpdf/JSON.hh>
#include <qpdf/QPDF.hh>
#include <qpdf/QPDFValue.hh>
#include <qpdf/QPDF_private.hh>
#include <qpdf/Types.h>
#include <string>
#include <string_view>
class QPDF;
class QPDFObjectHandle;
class QPDFObject

View File

@ -0,0 +1,560 @@
#ifndef QPDF_PRIVATE_HH
#define QPDF_PRIVATE_HH
#include <qpdf/QPDF.hh>
// Writer class is restricted to QPDFWriter so that only it can call certain methods.
class QPDF::Writer
{
friend class QPDFWriter;
private:
static void
optimize(
QPDF& qpdf,
QPDFWriter::ObjTable const& obj,
std::function<int(QPDFObjectHandle&)> skip_stream_parameters)
{
return qpdf.optimize(obj, skip_stream_parameters);
}
static void
getLinearizedParts(
QPDF& qpdf,
QPDFWriter::ObjTable const& obj,
std::vector<QPDFObjectHandle>& part4,
std::vector<QPDFObjectHandle>& part6,
std::vector<QPDFObjectHandle>& part7,
std::vector<QPDFObjectHandle>& part8,
std::vector<QPDFObjectHandle>& part9)
{
qpdf.getLinearizedParts(obj, part4, part6, part7, part8, part9);
}
static void
generateHintStream(
QPDF& qpdf,
QPDFWriter::NewObjTable const& new_obj,
QPDFWriter::ObjTable const& obj,
std::shared_ptr<Buffer>& hint_stream,
int& S,
int& O,
bool compressed)
{
return qpdf.generateHintStream(new_obj, obj, hint_stream, S, O, compressed);
}
static std::vector<QPDFObjGen>
getCompressibleObjGens(QPDF& qpdf)
{
return qpdf.getCompressibleObjVector();
}
static std::vector<bool>
getCompressibleObjSet(QPDF& qpdf)
{
return qpdf.getCompressibleObjSet();
}
static std::map<QPDFObjGen, QPDFXRefEntry> const&
getXRefTable(QPDF& qpdf)
{
return qpdf.getXRefTableInternal();
}
static size_t
tableSize(QPDF& qpdf)
{
return qpdf.tableSize();
}
};
// The Resolver class is restricted to QPDFObject so that only it can resolve indirect
// references.
class QPDF::Resolver
{
friend class QPDFObject;
friend class QPDF_Unresolved;
private:
static QPDFObject*
resolved(QPDF* qpdf, QPDFObjGen og)
{
return qpdf->resolve(og);
}
};
// StreamCopier class is restricted to QPDFObjectHandle so it can copy stream data.
class QPDF::StreamCopier
{
friend class QPDFObjectHandle;
private:
static void
copyStreamData(QPDF* qpdf, QPDFObjectHandle const& dest, QPDFObjectHandle const& src)
{
qpdf->copyStreamData(dest, src);
}
};
// The ParseGuard class allows QPDFParser to detect re-entrant parsing. It also provides
// special access to allow the parser to create unresolved objects and dangling references.
class QPDF::ParseGuard
{
friend class QPDFParser;
private:
ParseGuard(QPDF* qpdf) :
qpdf(qpdf)
{
if (qpdf) {
qpdf->inParse(true);
}
}
static std::shared_ptr<QPDFObject>
getObject(QPDF* qpdf, int id, int gen, bool parse_pdf)
{
return qpdf->getObjectForParser(id, gen, parse_pdf);
}
~ParseGuard()
{
if (qpdf) {
qpdf->inParse(false);
}
}
QPDF* qpdf;
};
// Pipe class is restricted to QPDF_Stream.
class QPDF::Pipe
{
friend class QPDF_Stream;
private:
static bool
pipeStreamData(
QPDF* qpdf,
QPDFObjGen const& og,
qpdf_offset_t offset,
size_t length,
QPDFObjectHandle dict,
Pipeline* pipeline,
bool suppress_warnings,
bool will_retry)
{
return qpdf->pipeStreamData(
og, offset, length, dict, pipeline, suppress_warnings, will_retry);
}
};
class QPDF::ObjCache
{
public:
ObjCache() :
end_before_space(0),
end_after_space(0)
{
}
ObjCache(
std::shared_ptr<QPDFObject> object,
qpdf_offset_t end_before_space = 0,
qpdf_offset_t end_after_space = 0) :
object(object),
end_before_space(end_before_space),
end_after_space(end_after_space)
{
}
std::shared_ptr<QPDFObject> object;
qpdf_offset_t end_before_space;
qpdf_offset_t end_after_space;
};
class QPDF::ObjCopier
{
public:
std::map<QPDFObjGen, QPDFObjectHandle> object_map;
std::vector<QPDFObjectHandle> to_copy;
QPDFObjGen::set visiting;
};
class QPDF::EncryptionParameters
{
friend class QPDF;
public:
EncryptionParameters();
private:
bool encrypted;
bool encryption_initialized;
int encryption_V;
int encryption_R;
bool encrypt_metadata;
std::map<std::string, encryption_method_e> crypt_filters;
encryption_method_e cf_stream;
encryption_method_e cf_string;
encryption_method_e cf_file;
std::string provided_password;
std::string user_password;
std::string encryption_key;
std::string cached_object_encryption_key;
QPDFObjGen cached_key_og;
bool user_password_matched;
bool owner_password_matched;
};
class QPDF::ForeignStreamData
{
friend class QPDF;
public:
ForeignStreamData(
std::shared_ptr<EncryptionParameters> encp,
std::shared_ptr<InputSource> file,
QPDFObjGen const& foreign_og,
qpdf_offset_t offset,
size_t length,
QPDFObjectHandle local_dict);
private:
std::shared_ptr<EncryptionParameters> encp;
std::shared_ptr<InputSource> file;
QPDFObjGen foreign_og;
qpdf_offset_t offset;
size_t length;
QPDFObjectHandle local_dict;
};
class QPDF::CopiedStreamDataProvider: public QPDFObjectHandle::StreamDataProvider
{
public:
CopiedStreamDataProvider(QPDF& destination_qpdf);
~CopiedStreamDataProvider() override = default;
bool provideStreamData(
QPDFObjGen const& og, Pipeline* pipeline, bool suppress_warnings, bool will_retry) override;
void registerForeignStream(QPDFObjGen const& local_og, QPDFObjectHandle foreign_stream);
void registerForeignStream(QPDFObjGen const& local_og, std::shared_ptr<ForeignStreamData>);
private:
QPDF& destination_qpdf;
std::map<QPDFObjGen, QPDFObjectHandle> foreign_streams;
std::map<QPDFObjGen, std::shared_ptr<ForeignStreamData>> foreign_stream_data;
};
class QPDF::StringDecrypter: public QPDFObjectHandle::StringDecrypter
{
friend class QPDF;
public:
StringDecrypter(QPDF* qpdf, QPDFObjGen const& og);
~StringDecrypter() override = default;
void decryptString(std::string& val) override;
private:
QPDF* qpdf;
QPDFObjGen og;
};
// PDF 1.4: Table F.4
struct QPDF::HPageOffsetEntry
{
int delta_nobjects{0}; // 1
qpdf_offset_t delta_page_length{0}; // 2
// vectors' sizes = nshared_objects
int nshared_objects{0}; // 3
std::vector<int> shared_identifiers; // 4
std::vector<int> shared_numerators; // 5
qpdf_offset_t delta_content_offset{0}; // 6
qpdf_offset_t delta_content_length{0}; // 7
};
// PDF 1.4: Table F.3
struct QPDF::HPageOffset
{
int min_nobjects{0}; // 1
qpdf_offset_t first_page_offset{0}; // 2
int nbits_delta_nobjects{0}; // 3
int min_page_length{0}; // 4
int nbits_delta_page_length{0}; // 5
int min_content_offset{0}; // 6
int nbits_delta_content_offset{0}; // 7
int min_content_length{0}; // 8
int nbits_delta_content_length{0}; // 9
int nbits_nshared_objects{0}; // 10
int nbits_shared_identifier{0}; // 11
int nbits_shared_numerator{0}; // 12
int shared_denominator{0}; // 13
// vector size is npages
std::vector<HPageOffsetEntry> entries;
};
// PDF 1.4: Table F.6
struct QPDF::HSharedObjectEntry
{
// Item 3 is a 128-bit signature (unsupported by Acrobat)
int delta_group_length{0}; // 1
int signature_present{0}; // 2 -- always 0
int nobjects_minus_one{0}; // 4 -- always 0
};
// PDF 1.4: Table F.5
struct QPDF::HSharedObject
{
int first_shared_obj{0}; // 1
qpdf_offset_t first_shared_offset{0}; // 2
int nshared_first_page{0}; // 3
int nshared_total{0}; // 4
int nbits_nobjects{0}; // 5
int min_group_length{0}; // 6
int nbits_delta_group_length{0}; // 7
// vector size is nshared_total
std::vector<HSharedObjectEntry> entries;
};
// PDF 1.4: Table F.9
struct QPDF::HGeneric
{
int first_object{0}; // 1
qpdf_offset_t first_object_offset{0}; // 2
int nobjects{0}; // 3
int group_length{0}; // 4
};
// Other linearization data structures
// Initialized from Linearization Parameter dictionary
struct QPDF::LinParameters
{
qpdf_offset_t file_size{0}; // /L
int first_page_object{0}; // /O
qpdf_offset_t first_page_end{0}; // /E
int npages{0}; // /N
qpdf_offset_t xref_zero_offset{0}; // /T
int first_page{0}; // /P
qpdf_offset_t H_offset{0}; // offset of primary hint stream
qpdf_offset_t H_length{0}; // length of primary hint stream
};
// Computed hint table value data structures. These tables contain the computed values on which
// the hint table values are based. They exclude things like number of bits and store actual
// values instead of mins and deltas. File offsets are also absolute rather than being offset
// by the size of the primary hint table. We populate the hint table structures from these
// during writing and compare the hint table values with these during validation. We ignore
// some values for various reasons described in the code. Those values are omitted from these
// structures. Note also that object numbers are object numbers from the input file, not the
// output file.
// Naming convention: CHSomething is analogous to HSomething above. "CH" is computed hint.
struct QPDF::CHPageOffsetEntry
{
int nobjects{0};
int nshared_objects{0};
// vectors' sizes = nshared_objects
std::vector<int> shared_identifiers;
};
struct QPDF::CHPageOffset
{
// vector size is npages
std::vector<CHPageOffsetEntry> entries;
};
struct QPDF::CHSharedObjectEntry
{
CHSharedObjectEntry(int object) :
object(object)
{
}
int object;
};
// PDF 1.4: Table F.5
struct QPDF::CHSharedObject
{
int first_shared_obj{0};
int nshared_first_page{0};
int nshared_total{0};
// vector size is nshared_total
std::vector<CHSharedObjectEntry> entries;
};
// No need for CHGeneric -- HGeneric is fine as is.
// Data structures to support optimization -- implemented in QPDF_optimization.cc
class QPDF::ObjUser
{
public:
enum user_e { ou_bad, ou_page, ou_thumb, ou_trailer_key, ou_root_key, ou_root };
// type is set to ou_bad
ObjUser();
// type must be ou_root
ObjUser(user_e type);
// type must be one of ou_page or ou_thumb
ObjUser(user_e type, int pageno);
// type must be one of ou_trailer_key or ou_root_key
ObjUser(user_e type, std::string const& key);
bool operator<(ObjUser const&) const;
user_e ou_type;
int pageno; // if ou_page;
std::string key; // if ou_trailer_key or ou_root_key
};
struct QPDF::UpdateObjectMapsFrame
{
UpdateObjectMapsFrame(ObjUser const& ou, QPDFObjectHandle oh, bool top);
ObjUser const& ou;
QPDFObjectHandle oh;
bool top;
};
class QPDF::PatternFinder: public InputSource::Finder
{
public:
PatternFinder(QPDF& qpdf, bool (QPDF::*checker)()) :
qpdf(qpdf),
checker(checker)
{
}
~PatternFinder() override = default;
bool
check() override
{
return (this->qpdf.*checker)();
}
private:
QPDF& qpdf;
bool (QPDF::*checker)();
};
class QPDF::Members
{
friend class QPDF;
friend class ResolveRecorder;
public:
QPDF_DLL
~Members() = default;
private:
Members();
Members(Members const&) = delete;
std::shared_ptr<QPDFLogger> log;
unsigned long long unique_id{0};
QPDFTokenizer tokenizer;
std::shared_ptr<InputSource> file;
std::string last_object_description;
bool provided_password_is_hex_key{false};
bool ignore_xref_streams{false};
bool suppress_warnings{false};
size_t max_warnings{0};
bool attempt_recovery{true};
bool check_mode{false};
std::shared_ptr<EncryptionParameters> encp;
std::string pdf_version;
std::map<QPDFObjGen, QPDFXRefEntry> xref_table;
// Various tables are indexed by object id, with potential size id + 1
int xref_table_max_id{std::numeric_limits<int>::max() - 1};
qpdf_offset_t xref_table_max_offset{0};
std::set<int> deleted_objects;
std::map<QPDFObjGen, ObjCache> obj_cache;
std::set<QPDFObjGen> resolving;
QPDFObjectHandle trailer;
std::vector<QPDFObjectHandle> all_pages;
bool invalid_page_found{false};
std::map<QPDFObjGen, int> pageobj_to_pages_pos;
bool pushed_inherited_attributes_to_pages{false};
bool ever_pushed_inherited_attributes_to_pages{false};
bool ever_called_get_all_pages{false};
std::vector<QPDFExc> warnings;
std::map<unsigned long long, ObjCopier> object_copiers;
std::shared_ptr<QPDFObjectHandle::StreamDataProvider> copied_streams;
// copied_stream_data_provider is owned by copied_streams
CopiedStreamDataProvider* copied_stream_data_provider{nullptr};
bool reconstructed_xref{false};
bool fixed_dangling_refs{false};
bool immediate_copy_from{false};
bool in_parse{false};
bool parsed{false};
std::set<int> resolved_object_streams;
// Linearization data
qpdf_offset_t first_xref_item_offset{0}; // actual value from file
bool uncompressed_after_compressed{false};
bool linearization_warnings{false};
// Linearization parameter dictionary and hint table data: may be read from file or computed
// prior to writing a linearized file
QPDFObjectHandle lindict;
LinParameters linp;
HPageOffset page_offset_hints;
HSharedObject shared_object_hints;
HGeneric outline_hints;
// Computed linearization data: used to populate above tables during writing and to compare
// with them during validation. c_ means computed.
LinParameters c_linp;
CHPageOffset c_page_offset_data;
CHSharedObject c_shared_object_data;
HGeneric c_outline_data;
// Object ordering data for linearized files: initialized by calculateLinearizationData().
// Part numbers refer to the PDF 1.4 specification.
std::vector<QPDFObjectHandle> part4;
std::vector<QPDFObjectHandle> part6;
std::vector<QPDFObjectHandle> part7;
std::vector<QPDFObjectHandle> part8;
std::vector<QPDFObjectHandle> part9;
// Optimization data
std::map<ObjUser, std::set<QPDFObjGen>> obj_user_to_objects;
std::map<QPDFObjGen, std::set<ObjUser>> object_to_obj_users;
};
// JobSetter class is restricted to QPDFJob.
class QPDF::JobSetter
{
friend class QPDFJob;
private:
// Enable enhanced warnings for pdf file checking.
static void
setCheckMode(QPDF& qpdf, bool val)
{
qpdf.m->check_mode = val;
}
};
class QPDF::ResolveRecorder
{
public:
ResolveRecorder(QPDF* qpdf, QPDFObjGen const& og) :
qpdf(qpdf),
iter(qpdf->m->resolving.insert(og).first)
{
}
virtual ~ResolveRecorder()
{
this->qpdf->m->resolving.erase(iter);
}
private:
QPDF* qpdf;
std::set<QPDFObjGen>::const_iterator iter;
};
#endif // QPDF_PRIVATE_HH