aboutsummaryrefslogtreecommitdiffstats
path: root/examples
diff options
context:
space:
mode:
authorJay Berkenbilt <ejb@ql.org>2022-06-18 20:16:56 +0200
committerJay Berkenbilt <ejb@ql.org>2022-06-19 14:46:58 +0200
commit8e361d98f0bb23d58cbc773367ba76dffced7bdb (patch)
treec3c0aebbe88f51aa43c3eb8a586f8b795b8b5a45 /examples
parent8130d50e3b5aa0235a133c3c5a3018ac01afb5e1 (diff)
downloadqpdf-8e361d98f0bb23d58cbc773367ba76dffced7bdb.tar.zst
Add examples for output capture (fixes #691)
Diffstat (limited to 'examples')
-rw-r--r--examples/CMakeLists.txt6
-rw-r--r--examples/qpdfjob-c-save-attachment.c100
-rw-r--r--examples/qpdfjob-c.c4
-rw-r--r--examples/qpdfjob-save-attachment.cc51
-rw-r--r--examples/qtest/qpdfjob-attachment/attach.pdfbin0 -> 1290 bytes
-rw-r--r--examples/qtest/save-attachment.test42
6 files changed, 201 insertions, 2 deletions
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt
index 40ecd603..947068dd 100644
--- a/examples/CMakeLists.txt
+++ b/examples/CMakeLists.txt
@@ -14,11 +14,13 @@ set(EXAMPLE_CXX_PROGRAMS
pdf-parse-content
pdf-set-form-values
pdf-split-pages
- qpdf-job)
+ qpdf-job
+ qpdfjob-save-attachment)
set(EXAMPLE_C_PROGRAMS
pdf-c-objects
pdf-linearize
- qpdfjob-c)
+ qpdfjob-c
+ qpdfjob-c-save-attachment)
foreach(PROG ${EXAMPLE_CXX_PROGRAMS})
add_executable(${PROG} ${PROG}.cc)
diff --git a/examples/qpdfjob-c-save-attachment.c b/examples/qpdfjob-c-save-attachment.c
new file mode 100644
index 00000000..950e297b
--- /dev/null
+++ b/examples/qpdfjob-c-save-attachment.c
@@ -0,0 +1,100 @@
+#include <qpdf/Constants.h>
+#include <qpdf/qpdfjob-c.h>
+#include <qpdf/qpdflogger-c.h>
+
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+// This example demonstrates how we can redirect where saved output
+// goes by calling the default logger's setSave method before running
+// something with QPDFJob. See qpdfjob-c-save-attachment.c for an
+// implementation that uses the C API.
+
+static void
+save_to_file(char const* data, size_t len, void* udata)
+{
+ FILE* f = (FILE*)udata;
+ fwrite(data, 1, len, f);
+}
+
+static FILE*
+do_fopen(char const* filename)
+{
+ FILE* f = NULL;
+#ifdef _MSC_VER
+ if (fopen_s(&f, filename, "wb") != 0) {
+ f = NULL;
+ }
+#else
+ f = fopen(filename, "wb");
+#endif
+ if (f == NULL) {
+ fprintf(stderr, "unable to open %s\n", filename);
+ exit(2);
+ }
+ return f;
+}
+
+int
+main(int argc, char* argv[])
+{
+ char const* whoami = "qpdfjob-c-save-attachment";
+ char const* filename = NULL;
+ char const* key = NULL;
+ char const* outfilename = NULL;
+ char* attachment_arg = NULL;
+ char const* attachment_flag = "--show-attachment=";
+ size_t flag_len = 0;
+ FILE* outfile = NULL;
+ int status = 0;
+ qpdfjob_handle j = NULL;
+ qpdflogger_handle l = qpdflogger_default_logger();
+
+ if (argc != 4) {
+ fprintf(stderr, "Usage: %s file attachment-key outfile\n", whoami);
+ exit(2);
+ }
+
+ filename = argv[1];
+ key = argv[2];
+ outfilename = argv[3];
+
+ flag_len = strlen(attachment_flag) + strlen(key) + 1;
+ attachment_arg = malloc(flag_len);
+#ifdef _MSC_VER
+ strncpy_s(attachment_arg, flag_len, attachment_flag, flag_len);
+ strncat_s(attachment_arg, flag_len, key, flag_len - strlen(attachment_arg));
+#else
+ strncpy(attachment_arg, attachment_flag, flag_len);
+ strncat(attachment_arg, key, flag_len - strlen(attachment_arg));
+#endif
+
+ char const* j_argv[5] = {
+ whoami,
+ filename,
+ attachment_arg,
+ "--",
+ NULL,
+ };
+ outfile = do_fopen(outfilename);
+
+ /* Use qpdflogger_set_save with a callback function to redirect
+ * saved data. You can use other qpdf logger functions to capture
+ * informational output, warnings, and errors.
+ */
+ qpdflogger_set_save(
+ l, qpdf_log_dest_custom, save_to_file, (void*)outfile, 0);
+ qpdflogger_cleanup(&l);
+ j = qpdfjob_init();
+ status = (qpdfjob_initialize_from_argv(j, j_argv) ||
+ qpdfjob_run(j));
+ qpdfjob_cleanup(&j);
+ free(attachment_arg);
+ fclose(outfile);
+ if (status == qpdf_exit_success) {
+ printf("%s: wrote attachment to %s\n", whoami, outfilename);
+ }
+ return 0;
+}
diff --git a/examples/qpdfjob-c.c b/examples/qpdfjob-c.c
index ee2ef4ab..452e689b 100644
--- a/examples/qpdfjob-c.c
+++ b/examples/qpdfjob-c.c
@@ -52,6 +52,10 @@ main(int argc, char* argv[])
* To use that from C just like the argv one, call
* qpdfjob_run_from_json instead and pass the json string as a
* single char const* argument.
+ *
+ * See qpdfjob-c-save-attachment.c for an example of using the
+ * full form of the qpdfjob interface with init and cleanup
+ * functions.
*/
r = qpdfjob_run_from_argv(new_argv);
return r;
diff --git a/examples/qpdfjob-save-attachment.cc b/examples/qpdfjob-save-attachment.cc
new file mode 100644
index 00000000..2c08620a
--- /dev/null
+++ b/examples/qpdfjob-save-attachment.cc
@@ -0,0 +1,51 @@
+#include <qpdf/Pl_StdioFile.hh>
+#include <qpdf/QPDFJob.hh>
+#include <qpdf/QPDFLogger.hh>
+#include <qpdf/QUtil.hh>
+
+// This example demonstrates how we can redirect where saved output
+// goes by calling the default logger's setSave method before running
+// something with QPDFJob. See qpdfjob-c-save-attachment.c for an
+// implementation that uses the C API.
+
+int
+main(int argc, char* argv[])
+{
+ auto whoami = QUtil::getWhoami(argv[0]);
+
+ if (argc != 4) {
+ std::cerr << "Usage: " << whoami << " file attachment-key outfile"
+ << std::endl;
+ exit(2);
+ }
+
+ char const* filename = argv[1];
+ char const* key = argv[2];
+ char const* outfilename = argv[3];
+ std::string attachment_arg = "--show-attachment=";
+ attachment_arg += key;
+
+ char const* j_argv[] = {
+ whoami,
+ filename,
+ attachment_arg.c_str(),
+ "--",
+ nullptr,
+ };
+
+ QUtil::FileCloser fc(QUtil::safe_fopen(outfilename, "wb"));
+ auto save = std::make_shared<Pl_StdioFile>("capture", fc.f);
+ QPDFLogger::defaultLogger()->setSave(save, false);
+
+ try {
+ QPDFJob j;
+ j.initializeFromArgv(j_argv);
+ j.run();
+ } catch (std::exception& e) {
+ std::cerr << whoami << ": " << e.what() << std::endl;
+ exit(2);
+ }
+
+ std::cout << whoami << ": wrote attachment to " << outfilename << std::endl;
+ return 0;
+}
diff --git a/examples/qtest/qpdfjob-attachment/attach.pdf b/examples/qtest/qpdfjob-attachment/attach.pdf
new file mode 100644
index 00000000..bbc09588
--- /dev/null
+++ b/examples/qtest/qpdfjob-attachment/attach.pdf
Binary files differ
diff --git a/examples/qtest/save-attachment.test b/examples/qtest/save-attachment.test
new file mode 100644
index 00000000..2486a29c
--- /dev/null
+++ b/examples/qtest/save-attachment.test
@@ -0,0 +1,42 @@
+#!/usr/bin/env perl
+require 5.008;
+use warnings;
+use strict;
+
+chdir("qpdfjob-attachment") or die "chdir testdir failed: $!\n";
+
+require TestDriver;
+
+cleanup();
+
+my $td = new TestDriver('qpdfjob-attachment');
+
+$td->runtest("save attachment (C)",
+ {$td->COMMAND => "qpdfjob-c-save-attachment attach.pdf a a"},
+ {$td->STRING =>
+ "qpdfjob-c-save-attachment: wrote attachment to a\n",
+ $td->EXIT_STATUS => 0},
+ $td->NORMALIZE_NEWLINES);
+$td->runtest("check output",
+ {$td->FILE => "a"},
+ {$td->STRING => "quack\n"},
+ $td->NORMALIZE_NEWLINES);
+$td->runtest("save attachment (C++)",
+ {$td->COMMAND => "qpdfjob-save-attachment attach.pdf a b"},
+ {$td->STRING =>
+ "qpdfjob-save-attachment: wrote attachment to b\n",
+ $td->EXIT_STATUS => 0},
+ $td->NORMALIZE_NEWLINES);
+$td->runtest("check output",
+ {$td->FILE => "b"},
+ {$td->STRING => "quack\n"},
+ $td->NORMALIZE_NEWLINES);
+
+cleanup();
+
+$td->report(4);
+
+sub cleanup
+{
+ unlink "a", "b";
+}