aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog5
-rw-r--r--include/qpdf/QUtil.hh13
-rw-r--r--libqpdf/QUtil.cc32
-rw-r--r--libtests/qutil.cc7
-rw-r--r--manual/qpdf-manual.xml7
5 files changed, 63 insertions, 1 deletions
diff --git a/ChangeLog b/ChangeLog
index d5ceeea2..c81f88e0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2021-02-07 Jay Berkenbilt <ejb@ql.org>
+
+ * Add new functions QUtil::pipe_file and QUtil::file_provider for
+ sending the contents of a file through a pipeline as binary data.
+
2021-02-04 Jay Berkenbilt <ejb@ql.org>
* Add new option --pasword-file=file for reading the decryption
diff --git a/include/qpdf/QUtil.hh b/include/qpdf/QUtil.hh
index 30a73441..fe18c9b7 100644
--- a/include/qpdf/QUtil.hh
+++ b/include/qpdf/QUtil.hh
@@ -34,6 +34,7 @@
#include <time.h>
class RandomDataProvider;
+class Pipeline;
namespace QUtil
{
@@ -119,6 +120,18 @@ namespace QUtil
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);
+
QPDF_DLL
char* copy_string(std::string const&);
diff --git a/libqpdf/QUtil.cc b/libqpdf/QUtil.cc
index 5442b5ff..dc847679 100644
--- a/libqpdf/QUtil.cc
+++ b/libqpdf/QUtil.cc
@@ -7,6 +7,7 @@
#include <qpdf/QPDFSystemError.hh>
#include <qpdf/QTC.hh>
#include <qpdf/QIntC.hh>
+#include <qpdf/Pipeline.hh>
#include <cmath>
#include <iomanip>
@@ -612,6 +613,35 @@ QUtil::rename_file(char const* oldname, char const* newname)
#endif
}
+void
+QUtil::pipe_file(char const* filename, Pipeline* p)
+{
+ // Exercised in test suite by testing file_provider.
+ FILE* f = safe_fopen(filename, "rb");
+ FileCloser fc(f);
+ size_t len = 0;
+ int constexpr size = 8192;
+ unsigned char buf[size];
+ while ((len = fread(buf, 1, size, f)) > 0)
+ {
+ p->write(buf, len);
+ }
+ p->finish();
+ if (ferror(f))
+ {
+ throw std::runtime_error(
+ std::string("failure reading file ") + filename);
+ }
+}
+
+std::function<void(Pipeline*)>
+QUtil::file_provider(std::string const& filename)
+{
+ return [filename](Pipeline* p) {
+ pipe_file(filename.c_str(), p);
+ };
+}
+
char*
QUtil::copy_string(std::string const& str)
{
@@ -1018,6 +1048,7 @@ QUtil::read_file_into_memory(
PointerHolder<char>& file_buf, size_t& size)
{
FILE* f = safe_fopen(filename, "rb");
+ FileCloser fc(f);
fseek(f, 0, SEEK_END);
size = QIntC::to_size(QUtil::tell(f));
fseek(f, 0, SEEK_SET);
@@ -1048,7 +1079,6 @@ QUtil::read_file_into_memory(
uint_to_string(size));
}
}
- fclose(f);
}
static bool read_char_from_FILE(char& ch, FILE* f)
diff --git a/libtests/qutil.cc b/libtests/qutil.cc
index abfefce0..bc12a6ea 100644
--- a/libtests/qutil.cc
+++ b/libtests/qutil.cc
@@ -6,6 +6,7 @@
#include <qpdf/QUtil.hh>
#include <qpdf/PointerHolder.hh>
#include <qpdf/QPDFSystemError.hh>
+#include <qpdf/Pl_Buffer.hh>
#include <string.h>
#include <limits.h>
#include <assert.h>
@@ -483,6 +484,12 @@ void read_from_file_test()
assert(memcmp(p, "This file is used for qutil testing.", 36) == 0);
assert(p[59] == static_cast<char>(13));
assert(memcmp(p + 24641, "very long.", 10) == 0);
+ Pl_Buffer b2("buffer");
+ // QUtil::file_provider also exercises QUtil::pipe_file
+ QUtil::file_provider("other-file")(&b2);
+ auto buf2 = b2.getBuffer();
+ assert(buf2->getSize() == size);
+ assert(memcmp(buf2->getBuffer(), p, size) == 0);
}
void assert_hex_encode(std::string const& input, std::string const& expected)
diff --git a/manual/qpdf-manual.xml b/manual/qpdf-manual.xml
index 09ba7408..39f3d969 100644
--- a/manual/qpdf-manual.xml
+++ b/manual/qpdf-manual.xml
@@ -4964,6 +4964,13 @@ print "\n";
read/write implementation of name and number trees.
</para>
</listitem>
+ <listitem>
+ <para>
+ Add new functions <function>QUtil::pipe_file</function> and
+ <function>QUtil::file_provider</function> for sending the
+ contents of a file through a pipeline as binary data.
+ </para>
+ </listitem>
</itemizedlist>
</listitem>
<listitem>