QPDFJob increment: basic QPDFJob structure

Move most of the methods called from qpdf.cc after argument parsing
into QPDFJob. In this increment, enough QPDFJob API has been added to
handle the branch of QPDFJob::run() that creates output with an
appropriate division between qpdf.cc and QPDFJob.

There are temporary bits of code to enable everything to compile and
pass the test suite, including some duplication and hard-coded values.
This commit is contained in:
Jay Berkenbilt 2022-01-03 10:16:28 -05:00
parent 8c718b7e6f
commit 0910e767ad
12 changed files with 3960 additions and 3672 deletions

View File

@ -333,6 +333,7 @@
"qpdffake",
"qpdffilespecobjecthelper",
"qpdfformfieldobjecthelper",
"qpdfjob",
"qpdfmatrix",
"qpdfnametreeobjecthelper",
"qpdfnumbertreeobjecthelper",

View File

@ -176,4 +176,11 @@ enum pdf_annotation_flag_e
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
};
#endif /* QPDFCONSTANTS_H */

307
include/qpdf/QPDFJob.hh Normal file
View File

@ -0,0 +1,307 @@
// Copyright (c) 2005-2021 Jay Berkenbilt
//
// This file is part of qpdf.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Versions of qpdf prior to version 7 were released under the terms
// of version 2.0 of the Artistic License. At your option, you may
// continue to consider qpdf to be licensed under those terms. Please
// see the manual for additional information.
#ifndef QPDFJOB_HH
#define QPDFJOB_HH
#include <qpdf/DLL.h>
#include <qpdf/PointerHolder.hh>
#include <qpdf/QPDF.hh>
#include <qpdf/Constants.h>
#include <string>
#include <list>
#include <vector>
#include <set>
#include <map>
#include <iostream>
class QPDFWriter;
class QPDFJob
{
public:
QPDF_DLL
QPDFJob();
QPDF_DLL
void setOutputStreams(std::ostream* out_stream, std::ostream* err_stream);
QPDF_DLL
void run();
QPDF_DLL
bool hasWarnings();
QPDF_DLL
bool createsOutput();
QPDF_DLL
bool suppressWarnings();
QPDF_DLL
bool checkRequiresPassword();
QPDF_DLL
bool checkIsEncrypted();
// Return value is bitwise OR of values from qpdf_encryption_status_e
QPDF_DLL
unsigned long getEncryptionStatus();
// QXXXQ From here to END-PUBLIC should all be private
public:
QPDF_DLL
static JSON json_schema(std::set<std::string>* keys = 0);
QPDF_DLL
static void parse_object_id(
std::string const& objspec, bool& trailer, int& obj, int& gen);
struct PageSpec
{
PageSpec(std::string const& filename,
char const* password,
char const* range) :
filename(filename),
password(password),
range(range)
{
}
std::string filename;
char const* password;
char const* range;
};
struct RotationSpec
{
RotationSpec(int angle = 0, bool relative = false) :
angle(angle),
relative(relative)
{
}
int angle;
bool relative;
};
enum password_mode_e { pm_bytes, pm_hex_bytes, pm_unicode, pm_auto };
struct UnderOverlay
{
UnderOverlay(char const* which) :
which(which),
filename(0),
password(0),
to_nr("1-z"),
from_nr("1-z"),
repeat_nr("")
{
}
std::string which;
char const* filename;
char const* password;
char const* to_nr;
char const* from_nr;
char const* repeat_nr;
PointerHolder<QPDF> pdf;
std::vector<int> to_pagenos;
std::vector<int> from_pagenos;
std::vector<int> repeat_pagenos;
};
struct AddAttachment
{
AddAttachment() :
replace(false)
{
}
std::string path;
std::string key;
std::string filename;
std::string creationdate;
std::string moddate;
std::string mimetype;
std::string description;
bool replace;
};
struct CopyAttachmentFrom
{
std::string path;
std::string password;
std::string prefix;
};
PointerHolder<QPDF> processFile(
char const* filename, char const* password);
void validateUnderOverlay(QPDF& pdf, QPDFJob::UnderOverlay* uo);
void handleUnderOverlay(QPDF& pdf);
void copyAttachments(QPDF& pdf);
void handleTransformations(QPDF& pdf);
void addAttachments(QPDF& pdf);
void setWriterOptions(QPDF& pdf, QPDFWriter& w);
void doSplitPages(QPDF& pdf, bool& warnings);
void writeOutfile(QPDF& pdf);
enum remove_unref_e { re_auto, re_yes, re_no };
char const* password;
std::shared_ptr<char> password_alloc;
bool linearize;
bool decrypt;
int split_pages;
bool verbose;
bool progress;
bool suppress_warnings;
bool copy_encryption;
char const* encryption_file;
char const* encryption_file_password;
bool encrypt;
bool password_is_hex_key;
bool suppress_password_recovery;
password_mode_e password_mode;
bool allow_insecure;
bool allow_weak_crypto;
std::string user_password;
std::string owner_password;
int keylen;
bool r2_print;
bool r2_modify;
bool r2_extract;
bool r2_annotate;
bool r3_accessibility;
bool r3_extract;
bool r3_assemble;
bool r3_annotate_and_form;
bool r3_form_filling;
bool r3_modify_other;
qpdf_r3_print_e r3_print;
bool force_V4;
bool force_R5;
bool cleartext_metadata;
bool use_aes;
bool stream_data_set;
qpdf_stream_data_e stream_data_mode;
bool compress_streams;
bool compress_streams_set;
bool recompress_flate;
bool recompress_flate_set;
int compression_level;
qpdf_stream_decode_level_e decode_level;
bool decode_level_set;
bool normalize_set;
bool normalize;
bool suppress_recovery;
bool object_stream_set;
qpdf_object_stream_e object_stream_mode;
bool ignore_xref_streams;
bool qdf_mode;
bool preserve_unreferenced_objects;
remove_unref_e remove_unreferenced_page_resources;
bool keep_files_open;
bool keep_files_open_set;
size_t keep_files_open_threshold;
bool newline_before_endstream;
std::string linearize_pass1;
bool coalesce_contents;
bool flatten_annotations;
int flatten_annotations_required;
int flatten_annotations_forbidden;
bool generate_appearances;
std::string min_version;
std::string force_version;
bool show_npages;
bool deterministic_id;
bool static_id;
bool static_aes_iv;
bool suppress_original_object_id;
bool show_encryption;
bool show_encryption_key;
bool check_linearization;
bool show_linearization;
bool show_xref;
bool show_trailer;
int show_obj;
int show_gen;
bool show_raw_stream_data;
bool show_filtered_stream_data;
bool show_pages;
bool show_page_images;
size_t collate;
bool flatten_rotation;
bool list_attachments;
std::string attachment_to_show;
std::list<std::string> attachments_to_remove;
std::list<AddAttachment> attachments_to_add;
std::list<CopyAttachmentFrom> attachments_to_copy;
bool json;
std::set<std::string> json_keys;
std::set<std::string> json_objects;
bool check;
bool optimize_images;
bool externalize_inline_images;
bool keep_inline_images;
bool remove_page_labels;
size_t oi_min_width;
size_t oi_min_height;
size_t oi_min_area;
size_t ii_min_bytes;
UnderOverlay underlay;
UnderOverlay overlay;
UnderOverlay* under_overlay;
std::vector<PageSpec> page_specs;
std::map<std::string, RotationSpec> rotations;
bool require_outfile;
bool replace_input;
bool check_is_encrypted;
bool check_requires_password;
char const* infilename;
char const* outfilename;
// QXXXQ END-PUBLIC
private:
class Members
{
friend class QPDFJob;
public:
QPDF_DLL
~Members() = default;
private:
Members();
Members(Members const&) = delete;
bool warnings;
bool creates_output;
std::ostream* out_stream;
std::ostream* err_stream;
unsigned long encryption_status;
};
PointerHolder<Members> m;
};
#endif // QPDFOBJECT_HH

View File

@ -24,6 +24,11 @@ QPDFArgParser::Members::Members(
option_table(nullptr),
final_check_handler(nullptr)
{
// Remove prefix added by libtool for consistency during testing.
if (strncmp(whoami, "lt-", 3) == 0)
{
whoami += 3;
}
}
QPDFArgParser::QPDFArgParser(int argc, char* argv[], char const* progname_env) :

3548
libqpdf/QPDFJob.cc Normal file

File diff suppressed because it is too large Load Diff

View File

@ -64,6 +64,7 @@ SRCS_libqpdf = \
libqpdf/QPDFExc.cc \
libqpdf/QPDFFileSpecObjectHelper.cc \
libqpdf/QPDFFormFieldObjectHelper.cc \
libqpdf/QPDFJob.cc \
libqpdf/QPDFMatrix.cc \
libqpdf/QPDFNameTreeObjectHelper.cc \
libqpdf/QPDFNumberTreeObjectHelper.cc \

File diff suppressed because it is too large Load Diff

View File

@ -626,3 +626,8 @@ qpdf-c called qpdf_oh_get_binary_string_value 0
qpdf-c called qpdf_oh_new_binary_string 0
qpdf duplicated pages password 0
qpdf misplaced pages password 0
qpdf check encrypted encrypted 0
qpdf check encrypted not encrypted 0
qpdf check password password incorrect 0
qpdf check password password correct 0
qpdf check password not encrypted 0

View File

@ -1,2 +1 @@
qpdf: a.pdf already has an attachment with key = auto-1; use --replace to replace or --key to specify a different key
qpdf: wrote file b.pdf
qpdf: a.pdf already has attachments with the following keys: auto-1; use --replace to replace or --key to specify a different key

View File

@ -1,7 +1,5 @@
qpdf: copying attachments from a.pdf
auto-1 -> auto-1
qpdf: copying attachments from a.pdf
auto-3 -> auto-3
qpdf: copying attachments from a.pdf
auto-Two -> auto-Two
qpdf: wrote file b.pdf

View File

@ -1,7 +1,5 @@
qpdf: copying attachments from b.pdf
auto-1 -> 1-auto-1
qpdf: copying attachments from b.pdf
auto-3 -> 1-auto-3
qpdf: copying attachments from b.pdf
auto-Two -> 1-auto-Two
qpdf: wrote file c.pdf

View File

@ -1,7 +1,2 @@
qpdf: copying attachments from b.pdf
qpdfb.pdf and a.pdf both have attachments with key auto-1; use --prefix with --copy-attachments-from or manually copy individual attachments
qpdf: copying attachments from b.pdf
qpdfb.pdf and a.pdf both have attachments with key auto-3; use --prefix with --copy-attachments-from or manually copy individual attachments
qpdf: copying attachments from b.pdf
qpdfb.pdf and a.pdf both have attachments with key auto-Two; use --prefix with --copy-attachments-from or manually copy individual attachments
qpdf: wrote file c.pdf
qpdf: a.pdf already has attachments with keys that conflict with attachments from other files: file: b.pdf, key: auto-1; file: b.pdf, key: auto-3; file: b.pdf, key: auto-Two. Use --prefix with --copy-attachments-from or manually copy individual attachments.