diff options
-rw-r--r-- | CMakeLists.txt | 2 | ||||
-rw-r--r-- | examples/CMakeLists.txt | 1 | ||||
-rw-r--r-- | examples/qpdfjob-remove-annotations.cc | 78 | ||||
-rw-r--r-- | examples/qtest/qpdfjob-remove-annotations.test | 28 | ||||
-rw-r--r-- | examples/qtest/qpdfjob-remove-annotations/annotations-out.pdf | bin | 0 -> 5284 bytes | |||
-rw-r--r-- | examples/qtest/qpdfjob-remove-annotations/annotations.pdf | 942 | ||||
-rw-r--r-- | include/qpdf/DLL.h | 6 | ||||
-rw-r--r-- | include/qpdf/QPDFJob.hh | 27 | ||||
-rw-r--r-- | libqpdf/QPDFJob.cc | 48 | ||||
-rw-r--r-- | manual/conf.py | 2 |
10 files changed, 1106 insertions, 28 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 655ae174..d2ec8ffd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,7 +5,7 @@ cmake_minimum_required(VERSION 3.16) # the project line. When updating the version, check make_dist for all # the places it has to be updated. project(qpdf - VERSION 11.3.1 + VERSION 11.4.0 LANGUAGES C CXX) # Enable correct rpath handling for MacOSX diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 947068dd..9af85fe2 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -15,6 +15,7 @@ set(EXAMPLE_CXX_PROGRAMS pdf-set-form-values pdf-split-pages qpdf-job + qpdfjob-remove-annotations qpdfjob-save-attachment) set(EXAMPLE_C_PROGRAMS pdf-c-objects diff --git a/examples/qpdfjob-remove-annotations.cc b/examples/qpdfjob-remove-annotations.cc new file mode 100644 index 00000000..dfab3f7b --- /dev/null +++ b/examples/qpdfjob-remove-annotations.cc @@ -0,0 +1,78 @@ +#include <qpdf/QPDFJob.hh> +#include <qpdf/QPDFUsage.hh> +#include <qpdf/QUtil.hh> + +#include <cstdio> +#include <cstdlib> +#include <cstring> +#include <iostream> + +// This example demonstrates how we can use the QPDFJob createQPDF and writeQPDF +// methods to add custom transformations to the output produced by QPDFJob runs. +// The example is a full copy of the qpdf program modified to allways remove all +// annotations from the final output. + +static char const* whoami = 0; + +static void +usageExit(std::string const& msg) +{ + std::cerr << std::endl + << whoami << ": " << msg << std::endl + << std::endl + << "For help:" << std::endl + << " " << whoami << " --help=usage usage information" + << std::endl + << " " << whoami << " --help=topic help on a topic" + << std::endl + << " " << whoami << " --help=--option help on an option" + << std::endl + << " " << whoami + << " --help general help and a topic list" + << std::endl + << std::endl; + exit(QPDFJob::EXIT_ERROR); +} + +int +realmain(int argc, char* argv[]) +{ + whoami = QUtil::getWhoami(argv[0]); + QUtil::setLineBuf(stdout); + + QPDFJob j; + try { + // See "HOW TO ADD A COMMAND-LINE ARGUMENT" in README-maintainer. + j.initializeFromArgv(argv); + auto qpdf_sp = j.createQPDF(); + auto& pdf = *qpdf_sp; + for (auto page: pdf.getAllPages()) { + page.replaceKey("/Annots", "null"_qpdf); + } + j.writeQPDF(pdf); + } catch (QPDFUsage& e) { + usageExit(e.what()); + } catch (std::exception& e) { + std::cerr << whoami << ": " << e.what() << std::endl; + return QPDFJob::EXIT_ERROR; + } + return j.getExitCode(); +} + +#ifdef WINDOWS_WMAIN + +extern "C" int +wmain(int argc, wchar_t* argv[]) +{ + return QUtil::call_main_from_wmain(argc, argv, realmain); +} + +#else + +int +main(int argc, char* argv[]) +{ + return realmain(argc, argv); +} + +#endif diff --git a/examples/qtest/qpdfjob-remove-annotations.test b/examples/qtest/qpdfjob-remove-annotations.test new file mode 100644 index 00000000..32abf3ef --- /dev/null +++ b/examples/qtest/qpdfjob-remove-annotations.test @@ -0,0 +1,28 @@ +#!/usr/bin/env perl +require 5.008; +use warnings; +use strict; + +chdir("qpdfjob-remove-annotations"); + +require TestDriver; + +my $td = new TestDriver('qpdfjob-remove-annotations'); + +cleanup(); + +$td->runtest("remove-annotations", + {$td->COMMAND => "qpdfjob-remove-annotations --static-id annotations.pdf out.pdf"}, + {$td->STRING => "", $td->EXIT_STATUS => 0}); +$td->runtest("compare files", + {$td->FILE => "out.pdf"}, + {$td->FILE => "annotations-out.pdf"}); + +cleanup(); + +$td->report(2); + +sub cleanup +{ + unlink("out.pdf"); +} diff --git a/examples/qtest/qpdfjob-remove-annotations/annotations-out.pdf b/examples/qtest/qpdfjob-remove-annotations/annotations-out.pdf Binary files differnew file mode 100644 index 00000000..88056506 --- /dev/null +++ b/examples/qtest/qpdfjob-remove-annotations/annotations-out.pdf diff --git a/examples/qtest/qpdfjob-remove-annotations/annotations.pdf b/examples/qtest/qpdfjob-remove-annotations/annotations.pdf new file mode 100644 index 00000000..118363d7 --- /dev/null +++ b/examples/qtest/qpdfjob-remove-annotations/annotations.pdf @@ -0,0 +1,942 @@ +%PDF-1.6 +%¿÷¢þ +%QDF-1.0 + +1 0 obj +<< + /AcroForm << + /DR 2 0 R + /Fields [ + 3 0 R + 4 0 R + 5 0 R + ] + >> + /Names << + /EmbeddedFiles 6 0 R + >> + /Pages 7 0 R + /Type /Catalog +>> +endobj + +2 0 obj +<< + /Font << + /F1 8 0 R + >> +>> +endobj + +3 0 obj +<< + /AP << + /N 9 0 R + >> + /DA (0 0.4 0 rg /F1 18 Tf) + /DR 2 0 R + /DV () + /FT /Tx + /Ff 0 + /Rect [ + 72 + 470.774 + 190.8 + 484.922 + ] + /Subtype /Widget + /T (Text Box 1) + /Type /Annot + /V (Formy field) +>> +endobj + +4 0 obj +<< + /AP << + /N 11 0 R + >> + /DA (0 0.4 0 rg /F1 18 Tf) + /DR 2 0 R + /DV () + /FT /Tx + /Ff 0 + /Rect [ + 372 + 330.774 + 386.148 + 470.374 + ] + /Subtype /Widget + /T (Text Box 1) + /Type /Annot + /V (Rot-ccw field) +>> +endobj + +5 0 obj +<< + /DV /1 + /FT /Btn + /Ff 49152 + /Kids [ + 13 0 R + 14 0 R + 15 0 R + ] + /T (r1) + /V /2 +>> +endobj + +6 0 obj +<< + /Names [ + (attachment1.txt) + 16 0 R + ] +>> +endobj + +7 0 obj +<< + /Count 1 + /Kids [ + 17 0 R + ] + /Type /Pages +>> +endobj + +8 0 obj +<< + /BaseFont /Courier + /Encoding /WinAnsiEncoding + /Subtype /Type1 + /Type /Font +>> +endobj + +9 0 obj +<< + /BBox [ + 0 + -2.826 + 118.8 + 11.322 + ] + /Resources 2 0 R + /Subtype /Form + /Type /XObject + /Length 10 0 R +>> +stream +/Tx BMC +q +BT + /F1 18 Tf + (Formy field) Tj +ET +Q +EMC +endstream +endobj + +10 0 obj +53 +endobj + +11 0 obj +<< + /BBox [ + 0 + -2.826 + 140.4 + 11.322 + ] + /Matrix [ + 0 + 1 + -1 + 0 + 0 + 0 + ] + /Resources 2 0 R + /Subtype /Form + /Type /XObject + /Length 12 0 R +>> +stream +/Tx BMC +q +BT + /F1 18 Tf + (Rot-ccw field) Tj +ET +Q +EMC +endstream +endobj + +12 0 obj +55 +endobj + +13 0 obj +<< + /AP << + /N << + /1 18 0 R + /Off 20 0 R + >> + >> + /AS /1 + /DA (0.18039 0.20392 0.21176 rg /ZaDi 0 Tf) + /DR << + /Font << + /ZaDi 22 0 R + >> + >> + /F 4 + /FT /Btn + /MK << + /CA (l) + >> + /Parent 5 0 R + /Rect [ + 152.749 + 648.501 + 164.801 + 660.549 + ] + /Subtype /Widget + /Type /Annot +>> +endobj + +14 0 obj +<< + /AP << + /N << + /2 23 0 R + /Off 25 0 R + >> + >> + /AS /2 + /DA (0.18039 0.20392 0.21176 rg /ZaDi 0 Tf) + /DR << + /Font << + /ZaDi 22 0 R + >> + >> + /F 4 + /FT /Btn + /MK << + /CA (l) + >> + /Parent 5 0 R + /Rect [ + 152.749 + 627.301 + 164.801 + 639.349 + ] + /Subtype /Widget + /Type /Annot +>> +endobj + +15 0 obj +<< + /AP << + /N << + /3 27 0 R + /Off 29 0 R + >> + >> + /AS /3 + /DA (0.18039 0.20392 0.21176 rg /ZaDi 0 Tf) + /DR << + /Font << + /ZaDi 22 0 R + >> + >> + /F 4 + /FT /Btn + /MK << + /CA (l) + >> + /Parent 5 0 R + /Rect [ + 151.399 + 606.501 + 163.451 + 618.549 + ] + /Subtype /Widget + /Type /Annot +>> +endobj + +16 0 obj +<< + /EF << + /F 31 0 R + /UF 31 0 R + >> + /F (attachment1.txt) + /Type /Filespec + /UF (attachment1.txt) +>> +endobj + +%% Page 1 +17 0 obj +<< + /Annots [ + 33 0 R + 3 0 R + 34 0 R + 4 0 R + 35 0 R + 36 0 R + 37 0 R + 38 0 R + 13 0 R + 14 0 R + 15 0 R + ] + /Contents 39 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 7 0 R + /Resources 2 0 R + /Type /Page +>> +endobj + +18 0 obj +<< + /BBox [ + 0 + 0 + 12.05 + 12.05 + ] + /Resources 41 0 R + /Subtype /Form + /Type /XObject + /Length 19 0 R +>> +stream +/Tx BMC +q BT +0.18039 0.20392 0.21176 rg /ZaDi 12.05 Tf +0 0 Td +ET +Q +1 0 0 rg +6 8.4 m 7.35 8.4 8.45 7.35 8.45 6 c +8.45 4.65 7.35 3.55 6 3.55 c +4.65 3.55 3.6 4.65 3.6 6 c +3.6 7.35 4.65 8.4 6 8.4 c f* + +EMC +endstream +endobj + +19 0 obj +202 +endobj + +20 0 obj +<< + /BBox [ + 0 + 0 + 12.05 + 12.05 + ] + /Resources 41 0 R + /Subtype /Form + /Type /XObject + /Length 21 0 R +>> +stream +/Tx BMC +EMC +endstream +endobj + +21 0 obj +12 +endobj + +22 0 obj +<< + /BaseFont /ZapfDingbats + /Subtype /Type1 + /Type /Font +>> +endobj + +23 0 obj +<< + /BBox [ + 0 + 0 + 12.05 + 12.05 + ] + /Resources 41 0 R + /Subtype /Form + /Type /XObject + /Length 24 0 R +>> +stream +/Tx BMC +q BT +0.18039 0.20392 0.21176 rg /ZaDi 12.05 Tf +0 0 Td +ET +Q +0 1 0 rg +6 8.4 m 7.35 8.4 8.45 7.35 8.45 6 c +8.45 4.65 7.35 3.55 6 3.55 c +4.65 3.55 3.6 4.65 3.6 6 c +3.6 7.35 4.65 8.4 6 8.4 c f* + +EMC +endstream +endobj + +24 0 obj +202 +endobj + +25 0 obj +<< + /BBox [ + 0 + 0 + 12.05 + 12.05 + ] + /Resources 41 0 R + /Subtype /Form + /Type /XObject + /Length 26 0 R +>> +stream +/Tx BMC +EMC +endstream +endobj + +26 0 obj +12 +endobj + +27 0 obj +<< + /BBox [ + 0 + 0 + 12.05 + 12.05 + ] + /Resources 41 0 R + /Subtype /Form + /Type /XObject + /Length 28 0 R +>> +stream +/Tx BMC +q BT +0.18039 0.20392 0.21176 rg /ZaDi 12.05 Tf +0 0 Td +ET +Q +0 0 1 rg +6 8.4 m 7.35 8.4 8.45 7.35 8.45 6 c +8.45 4.65 7.35 3.55 6 3.55 c +4.65 3.55 3.6 4.65 3.6 6 c +3.6 7.35 4.65 8.4 6 8.4 c f* + +EMC +endstream +endobj + +28 0 obj +202 +endobj + +29 0 obj +<< + /BBox [ + 0 + 0 + 12.05 + 12.05 + ] + /Resources 41 0 R + /Subtype /Form + /Type /XObject + /Length 30 0 R +>> +stream +/Tx BMC +EMC +endstream +endobj + +30 0 obj +12 +endobj + +31 0 obj +<< + /Params << + /CheckSum <80a33fc110b5a7b8b4d58b8d57e814bc> + /Size 22 + /Subtype /text#2fplain + >> + /Type /EmbeddedFile + /Length 32 0 R +>> +stream +content of attachment +endstream +endobj + +32 0 obj +22 +endobj + +33 0 obj +<< + /A << + /S /URI + /URI (https://www.qbilt.org/) + >> + /Border [ + 0 + 0 + .4 + ] + /C [ + .8 + .6 + .6 + ] + /H /I + /Rect [ + 72 + 501.832 + 374.4 + 520.696 + ] + /Subtype /Link + /Type /Annot +>> +endobj + +34 0 obj +<< + /AP << + /N 42 0 R + >> + /Contents (attachment1.txt) + /FS 16 0 R + /NM (attachment1.txt) + /Rect [ + 72 + 400 + 92 + 420 + ] + /Subtype /FileAttachment + /Type /Annot +>> +endobj + +35 0 obj +<< + /AP << + /N 44 0 R + >> + /DA () + /Rect [ + 72 + 350 + 92 + 360 + ] + /Subtype /FreeText + /Type /Annot +>> +endobj + +36 0 obj +<< + /AP << + /N 46 0 R + >> + /DA () + /Rect [ + 102 + 350 + 112 + 370 + ] + /Subtype /FreeText + /Type /Annot +>> +endobj + +37 0 obj +<< + /AP << + /N 48 0 R + >> + /DA () + /Rect [ + 122 + 350 + 142 + 360 + ] + /Subtype /FreeText + /Type /Annot +>> +endobj + +38 0 obj +<< + /AP << + /N 50 0 R + >> + /DA () + /Rect [ + 152 + 350 + 162 + 370 + ] + /Subtype /FreeText + /Type /Annot +>> +endobj + +%% Contents for page 1 +39 0 obj +<< + /Length 40 0 R +>> +stream +q +1 1 .7 rg +.5 .5 0 RG +72 470.77 118.8 14.15 re +B +Q +q +0 .5 .5 RG +0 1 1 rg +372 330.77 14.15 139.4 re +B +Q +q +1 0 0 RG +72 310 20 10 re +72 310 5 10 re +S +0 1 0 RG +102 310 10 20 re +102 310 10 5 re +S +0 0 1 RG +122 310 20 10 re +137 310 5 10 re +S +0.5 0 1 RG +152 310 10 20 re +152 325 10 5 re +S +10 w +0.14 .33 .18 RG +5 5 602 782 re +S +Q +BT + /F1 16 Tf + 20.6 TL + 170 650 Td + (radio button 1) Tj + (radio button 2) ' + (radio button 3) ' + 1 0 0 1 72 546 Tm + /F1 20 Tf + (Thick green border surrounds page.) Tj + 0 -40 Td + /F1 24 Tf + 0 0 1 rg + (https://www.qbilt.org) Tj + /F1 12 Tf + 1 0 0 1 202 474 Tm + (<- Formy field in yellow) Tj + 1 0 0 1 392 410 Tm + 14.4 TL + (<- Rot-ccw field) Tj + (with "Rot" at bottom) ' + (and text going up) ' + 0 g + 1 0 0 1 102 405 Tm + (Arrow to the left points down.) Tj + 1 0 0 1 182 310 Tm + (<- Drawn rectangles appear below annotations.) Tj +ET +endstream +endobj + +40 0 obj +874 +endobj + +41 0 obj +<< + /Font 52 0 R + /ProcSet [ + /PDF + /Text + ] +>> +endobj + +42 0 obj +<< + /BBox [ + 0 + 0 + 20 + 20 + ] + /Resources << + >> + /Subtype /Form + /Type /XObject + /Length 43 0 R +>> +stream +0 10 m +10 0 l +20 10 l +10 0 m +10 20 l +0 0 20 20 re +S +endstream +endobj + +43 0 obj +52 +endobj + +44 0 obj +<< + /BBox [ + 0 + 0 + 20 + 10 + ] + /Resources 2 0 R + /Subtype /Form + /Type /XObject + /Length 45 0 R +>> +stream +1 0 0 RG +0 0 20 10 re +0 0 5 10 re +S +endstream +endobj + +45 0 obj +36 +endobj + +46 0 obj +<< + /BBox [ + 0 + 0 + 20 + 10 + ] + /Matrix [ + 0 + 1 + -1 + 0 + 0 + 0 + ] + /Resources 2 0 R + /Subtype /Form + /Type /XObject + /Length 47 0 R +>> +stream +0 1 0 RG +0 0 20 10 re +0 0 5 10 re +S +endstream +endobj + +47 0 obj +36 +endobj + +48 0 obj +<< + /BBox [ + 0 + 0 + 20 + 10 + ] + /Matrix [ + -1 + 0 + 0 + -1 + 0 + 0 + ] + /Resources 2 0 R + /Subtype /Form + /Type /XObject + /Length 49 0 R +>> +stream +0 0 1 RG +0 0 20 10 re +0 0 5 10 re +S +endstream +endobj + +49 0 obj +36 +endobj + +50 0 obj +<< + /BBox [ + 0 + 0 + 20 + 10 + ] + /Matrix [ + 0 + -1 + 1 + 0 + 0 + 0 + ] + /Resources 2 0 R + /Subtype /Form + /Type /XObject + /Length 51 0 R +>> +stream +0.5 0 1 RG +0 0 20 10 re +0 0 5 10 re +S +endstream +endobj + +51 0 obj +38 +endobj + +52 0 obj +<< + /ZaDi 22 0 R +>> +endobj + +xref +0 53 +0000000000 65535 f +0000000025 00000 n +0000000211 00000 n +0000000263 00000 n +0000000506 00000 n +0000000755 00000 n +0000000874 00000 n +0000000944 00000 n +0000001017 00000 n +0000001121 00000 n +0000001335 00000 n +0000001355 00000 n +0000001625 00000 n +0000001645 00000 n +0000001997 00000 n +0000002349 00000 n +0000002701 00000 n +0000002842 00000 n +0000003114 00000 n +0000003473 00000 n +0000003494 00000 n +0000003663 00000 n +0000003683 00000 n +0000003764 00000 n +0000004123 00000 n +0000004144 00000 n +0000004313 00000 n +0000004333 00000 n +0000004692 00000 n +0000004713 00000 n +0000004882 00000 n +0000004902 00000 n +0000005110 00000 n +0000005130 00000 n +0000005374 00000 n +0000005578 00000 n +0000005718 00000 n +0000005860 00000 n +0000006002 00000 n +0000006167 00000 n +0000007098 00000 n +0000007119 00000 n +0000007193 00000 n +0000007397 00000 n +0000007417 00000 n +0000007603 00000 n +0000007623 00000 n +0000007862 00000 n +0000007882 00000 n +0000008122 00000 n +0000008142 00000 n +0000008383 00000 n +0000008403 00000 n +trailer << + /Root 1 0 R + /Size 53 + /ID [<a2f146daeb6d814a742556489dab9882><7b639c67bfc16b5e891fa5468aac3a14>] +>> +startxref +8441 +%%EOF diff --git a/include/qpdf/DLL.h b/include/qpdf/DLL.h index f6e17740..667a0cf5 100644 --- a/include/qpdf/DLL.h +++ b/include/qpdf/DLL.h @@ -25,9 +25,9 @@ /* The first version of qpdf to include the version constants is 10.6.0. */ #define QPDF_MAJOR_VERSION 11 -#define QPDF_MINOR_VERSION 3 -#define QPDF_PATCH_VERSION 1 -#define QPDF_VERSION "11.3.1" +#define QPDF_MINOR_VERSION 4 +#define QPDF_PATCH_VERSION 0 +#define QPDF_VERSION "11.4.0" /* * This file defines symbols that control the which functions, diff --git a/include/qpdf/QPDFJob.hh b/include/qpdf/QPDFJob.hh index 9bf81fcc..2a82d61c 100644 --- a/include/qpdf/QPDFJob.hh +++ b/include/qpdf/QPDFJob.hh @@ -397,6 +397,21 @@ class QPDFJob 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. @@ -474,7 +489,7 @@ class QPDFJob std::string to_nr; std::string from_nr; std::string repeat_nr; - std::shared_ptr<QPDF> pdf; + std::unique_ptr<QPDF> pdf; std::vector<int> to_pagenos; std::vector<int> from_pagenos; std::vector<int> repeat_pagenos; @@ -490,25 +505,25 @@ class QPDFJob // Basic file processing void processFile( - std::shared_ptr<QPDF>&, + std::unique_ptr<QPDF>&, char const* filename, char const* password, bool used_for_input, bool main_input); void processInputSource( - std::shared_ptr<QPDF>&, + std::unique_ptr<QPDF>&, std::shared_ptr<InputSource> is, char const* password, bool used_for_input); void doProcess( - std::shared_ptr<QPDF>&, + 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::shared_ptr<QPDF>&, + std::unique_ptr<QPDF>&, std::function<void(QPDF*, char const*)> fn, char const* password, bool empty, @@ -518,7 +533,7 @@ class QPDFJob // Transformations void setQPDFOptions(QPDF& pdf); void - handlePageSpecs(QPDF& pdf, std::vector<std::shared_ptr<QPDF>>& page_heap); + handlePageSpecs(QPDF& pdf, std::vector<std::unique_ptr<QPDF>>& page_heap); bool shouldRemoveUnreferencedResources(QPDF& pdf); void handleRotations(QPDF& pdf); void diff --git a/libqpdf/QPDFJob.cc b/libqpdf/QPDFJob.cc index 87ec32b9..b57a791b 100644 --- a/libqpdf/QPDFJob.cc +++ b/libqpdf/QPDFJob.cc @@ -447,11 +447,11 @@ QPDFJob::parseNumrange(char const* range, int max) return std::vector<int>(); } -void -QPDFJob::run() +std::unique_ptr<QPDF> +QPDFJob::createQPDF() { checkConfiguration(); - std::shared_ptr<QPDF> pdf_sp; + std::unique_ptr<QPDF> pdf_sp; try { processFile(pdf_sp, m->infilename.get(), m->password.get(), true, true); } catch (QPDFExc& e) { @@ -461,12 +461,12 @@ QPDFJob::run() if (m->check_is_encrypted || m->check_requires_password) { this->m->encryption_status = qpdf_es_encrypted | qpdf_es_password_incorrect; - return; + return nullptr; } if (m->show_encryption && pdf_sp) { this->m->log->info("Incorrect password supplied\n"); showEncryption(*pdf_sp); - return; + return nullptr; } } throw e; @@ -477,7 +477,7 @@ QPDFJob::run() } if (m->check_is_encrypted || m->check_requires_password) { - return; + return nullptr; } // If we are updating from JSON, this has to be done first before @@ -486,7 +486,7 @@ QPDFJob::run() pdf.updateFromJSON(this->m->update_from_json); } - std::vector<std::shared_ptr<QPDF>> page_heap; + std::vector<std::unique_ptr<QPDF>> page_heap; if (!m->page_specs.empty()) { handlePageSpecs(pdf, page_heap); } @@ -495,7 +495,12 @@ QPDFJob::run() } handleUnderOverlay(pdf); handleTransformations(pdf); + return pdf_sp; +} +void +QPDFJob::writeQPDF(QPDF& pdf) +{ if (!createsOutput()) { doInspection(pdf); } else if (m->split_pages) { @@ -527,6 +532,15 @@ QPDFJob::run() } } +void +QPDFJob::run() +{ + auto pdf = createQPDF(); + if (pdf) { + writeQPDF(*pdf); + } +} + bool QPDFJob::hasWarnings() const { @@ -1868,14 +1882,14 @@ QPDFJob::doInspection(QPDF& pdf) void QPDFJob::doProcessOnce( - std::shared_ptr<QPDF>& pdf, + std::unique_ptr<QPDF>& pdf, std::function<void(QPDF*, char const*)> fn, char const* password, bool empty, bool used_for_input, bool main_input) { - pdf = QPDF::create(); + pdf = std::make_unique<QPDF>(); setQPDFOptions(*pdf); if (empty) { pdf->emptyPDF(); @@ -1892,7 +1906,7 @@ QPDFJob::doProcessOnce( void QPDFJob::doProcess( - std::shared_ptr<QPDF>& pdf, + std::unique_ptr<QPDF>& pdf, std::function<void(QPDF*, char const*)> fn, char const* password, bool empty, @@ -1976,7 +1990,7 @@ QPDFJob::doProcess( void QPDFJob::processFile( - std::shared_ptr<QPDF>& pdf, + std::unique_ptr<QPDF>& pdf, char const* filename, char const* password, bool used_for_input, @@ -1996,7 +2010,7 @@ QPDFJob::processFile( void QPDFJob::processInputSource( - std::shared_ptr<QPDF>& pdf, + std::unique_ptr<QPDF>& pdf, std::shared_ptr<InputSource> is, char const* password, bool used_for_input) @@ -2278,7 +2292,7 @@ QPDFJob::copyAttachments(QPDF& pdf) v << prefix << ": copying attachments from " << to_copy.path << "\n"; }); - std::shared_ptr<QPDF> other; + std::unique_ptr<QPDF> other; processFile( other, to_copy.path.c_str(), @@ -2540,7 +2554,7 @@ added_page(QPDF& pdf, QPDFPageObjectHelper page) void QPDFJob::handlePageSpecs( - QPDF& pdf, std::vector<std::shared_ptr<QPDF>>& page_heap) + QPDF& pdf, std::vector<std::unique_ptr<QPDF>>& page_heap) { // Parse all page specifications and translate them into lists of // actual pages. @@ -2612,10 +2626,10 @@ QPDFJob::handlePageSpecs( new FileInputSource(page_spec.filename.c_str()); is = std::shared_ptr<InputSource>(fis); } - std::shared_ptr<QPDF> qpdf_sp; + std::unique_ptr<QPDF> qpdf_sp; processInputSource(qpdf_sp, is, password, true); - page_heap.push_back(qpdf_sp); page_spec_qpdfs[page_spec.filename] = qpdf_sp.get(); + page_heap.push_back(std::move(qpdf_sp)); if (cis) { cis->stayOpen(false); page_spec_cfis[page_spec.filename] = cis; @@ -3116,7 +3130,7 @@ QPDFJob::setWriterOptions(QPDF& pdf, QPDFWriter& w) w.setSuppressOriginalObjectIDs(true); } if (m->copy_encryption) { - std::shared_ptr<QPDF> encryption_pdf; + std::unique_ptr<QPDF> encryption_pdf; processFile( encryption_pdf, m->encryption_file.c_str(), diff --git a/manual/conf.py b/manual/conf.py index 3597ebbe..9d3148a3 100644 --- a/manual/conf.py +++ b/manual/conf.py @@ -16,7 +16,7 @@ project = 'QPDF' copyright = '2005-2023, Jay Berkenbilt' author = 'Jay Berkenbilt' # make_dist and the CI build lexically find the release version from this file. -release = '11.3.1' +release = '11.4.0' version = release extensions = [ 'sphinx_rtd_theme', |