aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJay Berkenbilt <ejb@ql.org>2011-08-11 16:48:37 +0200
committerJay Berkenbilt <ejb@ql.org>2011-08-11 16:48:37 +0200
commit14fe2e6de3ae3b91436ccb4948fca75c29565440 (patch)
tree7db510d20d62b298408ddf50c8302b7c5c0bc0dc
parentce358f103e51f5779b2e58a70b1439f5da7c5298 (diff)
downloadqpdf-14fe2e6de3ae3b91436ccb4948fca75c29565440.tar.zst
qpdf_set_info_key, qpdf_get_info_key
-rw-r--r--ChangeLog6
-rw-r--r--TODO4
-rw-r--r--include/qpdf/qpdf-c.h32
-rw-r--r--libqpdf/qpdf-c.cc59
-rw-r--r--manual/qpdf-manual.xml8
-rw-r--r--qpdf/qpdf-ctest.c31
-rw-r--r--qpdf/qpdf.testcov5
-rw-r--r--qpdf/qtest/qpdf.test22
-rw-r--r--qpdf/qtest/qpdf/c-info-out.pdf44
-rw-r--r--qpdf/qtest/qpdf/c-info1.out6
-rw-r--r--qpdf/qtest/qpdf/c-info2-in.pdfbin0 -> 926 bytes
-rw-r--r--qpdf/qtest/qpdf/c-info2.out6
12 files changed, 216 insertions, 7 deletions
diff --git a/ChangeLog b/ChangeLog
index 454cf44c..77447a38 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2011-08-11 Jay Berkenbilt <ejb@ql.org>
+
+ * include/qpdf/qpdf-c.h ("C"): add new methods qpdf_get_info_key
+ and qpdf_set_info_key for manipulating text fields of the /Info
+ dictionary.
+
2011-08-10 Jay Berkenbilt <ejb@ql.org>
* libqpdf/QPDFWriter.cc (copyEncryptionParameters): preserve
diff --git a/TODO b/TODO
index 59864149..61848ba5 100644
--- a/TODO
+++ b/TODO
@@ -3,10 +3,6 @@
* Provide an example of using replace and swap. Maybe.
- * Figure out a way to update the C API with something that can
- update dictionary keys at least with strings. Make sure it is
- possible to implement something akin to pdf-mod-info in C.
-
* Add C API for writing to memory if possible
General
diff --git a/include/qpdf/qpdf-c.h b/include/qpdf/qpdf-c.h
index 34c21bec..98a6f07b 100644
--- a/include/qpdf/qpdf-c.h
+++ b/include/qpdf/qpdf-c.h
@@ -199,18 +199,46 @@ extern "C" {
/* Read functions below must be called after qpdf_read or
* qpdf_read_memory. */
- /* Return the version of the PDF file. */
+ /*
+ * NOTE: Functions that return char* are returning a pointer to an
+ * internal buffer that will be reused for each call to a function
+ * that returns a char*. You must use or copy the value before
+ * calling any other qpdf library functions.
+ */
+
+ /* Return the version of the PDF file. See warning above about
+ * functions that return char*. */
QPDF_DLL
char const* qpdf_get_pdf_version(qpdf_data qpdf);
/* Return the user password. If the file is opened using the
* owner password, the user password may be retrieved using this
* function. If the file is opened using the user password, this
- * function will return that user password.
+ * function will return that user password. See warning above
+ * about functions that return char*.
*/
QPDF_DLL
char const* qpdf_get_user_password(qpdf_data qpdf);
+ /* Return the string value of a key in the document's Info
+ * dictionary. The key parameter should include the leading
+ * slash, e.g. "/Author". If the key is not present or has a
+ * non-string value, a null pointer is returned. Otherwise, a
+ * pointer to an internal buffer is returned. See warning above
+ * about functions that return char*.
+ */
+ QPDF_DLL
+ char const* qpdf_get_info_key(qpdf_data qpdf, char const* key);
+
+ /* Set a value in the info dictionary, possibly replacing an
+ * existing value. The key must include the leading slash
+ * (e.g. "/Author"). Passing a null pointer as a value will
+ * remove the key from the info dictionary. Otherwise, a copy
+ * will be made of the string that is passed in.
+ */
+ QPDF_DLL
+ void qpdf_set_info_key(qpdf_data qpdf, char const* key, char const* value);
+
/* Indicate whether the input file is linearized. */
QPDF_DLL
QPDF_BOOL qpdf_is_linearized(qpdf_data qpdf);
diff --git a/libqpdf/qpdf-c.cc b/libqpdf/qpdf-c.cc
index 10260753..62dba270 100644
--- a/libqpdf/qpdf-c.cc
+++ b/libqpdf/qpdf-c.cc
@@ -8,6 +8,7 @@
#include <list>
#include <string>
#include <stdexcept>
+#include <cstring>
struct _qpdf_error
{
@@ -283,6 +284,64 @@ char const* qpdf_get_user_password(qpdf_data qpdf)
return qpdf->tmp_string.c_str();
}
+char const* qpdf_get_info_key(qpdf_data qpdf, char const* key)
+{
+ char const* result = 0;
+ QPDFObjectHandle trailer = qpdf->qpdf->getTrailer();
+ if (trailer.hasKey("/Info"))
+ {
+ QPDFObjectHandle info = trailer.getKey("/Info");
+ if (info.hasKey(key))
+ {
+ QPDFObjectHandle value = info.getKey(key);
+ if (value.isString())
+ {
+ qpdf->tmp_string = value.getStringValue();
+ result = qpdf->tmp_string.c_str();
+ }
+ }
+ }
+ QTC::TC("qpdf", "qpdf-c get_info_key", (result == 0 ? 0 : 1));
+ return result;
+}
+
+void qpdf_set_info_key(qpdf_data qpdf, char const* key, char const* value)
+{
+ if ((key == 0) || (std::strlen(key) == 0) || (key[0] != '/'))
+ {
+ return;
+ }
+ QPDFObjectHandle value_object;
+ if (value)
+ {
+ QTC::TC("qpdf", "qpdf-c set_info_key to value");
+ value_object = QPDFObjectHandle::newString(value);
+ }
+ else
+ {
+ QTC::TC("qpdf", "qpdf-c set_info_key to null");
+ value_object = QPDFObjectHandle::newNull();
+ }
+
+ QPDFObjectHandle trailer = qpdf->qpdf->getTrailer();
+ if (! trailer.hasKey("/Info"))
+ {
+ QTC::TC("qpdf", "qpdf-c add info to trailer");
+ trailer.replaceKey(
+ "/Info",
+ qpdf->qpdf->makeIndirectObject(
+ QPDFObjectHandle::newDictionary(
+ std::map<std::string, QPDFObjectHandle>())));
+ }
+ else
+ {
+ QTC::TC("qpdf", "qpdf-c set-info-key use existing info");
+ }
+
+ QPDFObjectHandle info = trailer.getKey("/Info");
+ info.replaceOrRemoveKey(key, value_object);
+}
+
QPDF_BOOL qpdf_is_linearized(qpdf_data qpdf)
{
QTC::TC("qpdf", "qpdf-c called qpdf_is_linearized");
diff --git a/manual/qpdf-manual.xml b/manual/qpdf-manual.xml
index 15130567..0d743677 100644
--- a/manual/qpdf-manual.xml
+++ b/manual/qpdf-manual.xml
@@ -2123,6 +2123,14 @@ print "\n";
objects as vectors.
</para>
</listitem>
+ <listitem>
+ <para>
+ Add functions <function>qpdf_get_info_key</function> and
+ <function>qpdf_set_info_key</function> to the C API for
+ manipulating string fields of the document's
+ <literal>/Info</literal> dictionary.
+ </para>
+ </listitem>
</itemizedlist>
</listitem>
</varlistentry>
diff --git a/qpdf/qpdf-ctest.c b/qpdf/qpdf-ctest.c
index 0797d9a2..aa61b9a1 100644
--- a/qpdf/qpdf-ctest.c
+++ b/qpdf/qpdf-ctest.c
@@ -325,6 +325,36 @@ static void test15(char const* infile,
report_errors();
}
+static void print_info(char const* key)
+{
+ char const* value = qpdf_get_info_key(qpdf, key);
+ printf("Info key %s: %s\n",
+ key, (value ? value : "(null)"));
+}
+
+static void test16(char const* infile,
+ char const* password,
+ char const* outfile,
+ char const* outfile2)
+{
+ qpdf_read(qpdf, infile, password);
+ print_info("/Author");
+ print_info("/Producer");
+ print_info("/Creator");
+ qpdf_set_info_key(qpdf, "/Author", "Mr. Potato Head");
+ qpdf_set_info_key(qpdf, "/Producer", "QPDF libary");
+ qpdf_set_info_key(qpdf, "/Creator", 0);
+ print_info("/Author");
+ print_info("/Producer");
+ print_info("/Creator");
+ qpdf_init_write(qpdf, outfile);
+ qpdf_set_static_ID(qpdf, QPDF_TRUE);
+ qpdf_set_static_aes_IV(qpdf, QPDF_TRUE);
+ qpdf_set_stream_data_mode(qpdf, qpdf_s_uncompress);
+ qpdf_write(qpdf);
+ report_errors();
+}
+
int main(int argc, char* argv[])
{
char* p = 0;
@@ -380,6 +410,7 @@ int main(int argc, char* argv[])
(n == 13) ? test13 :
(n == 14) ? test14 :
(n == 15) ? test15 :
+ (n == 16) ? test16 :
0);
if (fn == 0)
diff --git a/qpdf/qpdf.testcov b/qpdf/qpdf.testcov
index 8f5d15a3..520b7fbe 100644
--- a/qpdf/qpdf.testcov
+++ b/qpdf/qpdf.testcov
@@ -194,3 +194,8 @@ QPDF stream with CRNL 0
QPDF stream with NL only 0
QPDF replaceObject called with indirect object 0
QPDFWriter copy encrypt metadata 1
+qpdf-c get_info_key 1
+qpdf-c set_info_key to value 0
+qpdf-c set_info_key to null 0
+qpdf-c set-info-key use existing info 0
+qpdf-c add info to trailer 0
diff --git a/qpdf/qtest/qpdf.test b/qpdf/qtest/qpdf.test
index c428aec3..b9e14a36 100644
--- a/qpdf/qtest/qpdf.test
+++ b/qpdf/qtest/qpdf.test
@@ -111,7 +111,7 @@ $td->runtest("new stream",
show_ntests();
# ----------
$td->notify("--- Miscellaneous Tests ---");
-$n_tests += 33;
+$n_tests += 37;
$td->runtest("qpdf version",
{$td->COMMAND => "qpdf --version"},
@@ -285,6 +285,26 @@ $td->runtest("check output",
{$td->FILE => "a.pdf"},
{$td->FILE => "test14-out.pdf"});
+$td->runtest("C API info key functions",
+ {$td->COMMAND => "qpdf-ctest 16 minimal.pdf '' a.pdf"},
+ {$td->FILE => "c-info1.out",
+ $td->EXIT_STATUS => 0},
+ $td->NORMALIZE_NEWLINES);
+$td->runtest("check output",
+ {$td->FILE => "a.pdf"},
+ {$td->FILE => "c-info-out.pdf"});
+unlink "a.pdf" or die;
+
+$td->runtest("C API info key functions",
+ {$td->COMMAND => "qpdf-ctest 16 c-info2-in.pdf '' a.pdf"},
+ {$td->FILE => "c-info2.out",
+ $td->EXIT_STATUS => 0},
+ $td->NORMALIZE_NEWLINES);
+$td->runtest("check output",
+ {$td->FILE => "a.pdf"},
+ {$td->FILE => "c-info-out.pdf"});
+unlink "a.pdf" or die;
+
show_ntests();
# ----------
$td->notify("--- Error Condition Tests ---");
diff --git a/qpdf/qtest/qpdf/c-info-out.pdf b/qpdf/qtest/qpdf/c-info-out.pdf
new file mode 100644
index 00000000..5b4c46cf
--- /dev/null
+++ b/qpdf/qtest/qpdf/c-info-out.pdf
@@ -0,0 +1,44 @@
+%PDF-1.3
+%¿÷¢þ
+1 0 obj
+<< /Pages 3 0 R /Type /Catalog >>
+endobj
+2 0 obj
+<< /Author (Mr. Potato Head) /Producer (QPDF libary) >>
+endobj
+3 0 obj
+<< /Count 1 /Kids [ 4 0 R ] /Type /Pages >>
+endobj
+4 0 obj
+<< /Contents 5 0 R /MediaBox [ 0 0 612 792 ] /Parent 3 0 R /Resources << /Font << /F1 6 0 R >> /ProcSet 7 0 R >> /Type /Page >>
+endobj
+5 0 obj
+<< /Length 44 >>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato) Tj
+ET
+endstream
+endobj
+6 0 obj
+<< /BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font >>
+endobj
+7 0 obj
+[ /PDF /Text ]
+endobj
+xref
+0 8
+0000000000 65535 f
+0000000015 00000 n
+0000000064 00000 n
+0000000135 00000 n
+0000000194 00000 n
+0000000337 00000 n
+0000000430 00000 n
+0000000537 00000 n
+trailer << /Info 2 0 R /Root 1 0 R /Size 8 /ID [<31415926535897932384626433832795><31415926535897932384626433832795>] >>
+startxref
+567
+%%EOF
diff --git a/qpdf/qtest/qpdf/c-info1.out b/qpdf/qtest/qpdf/c-info1.out
new file mode 100644
index 00000000..8ec9497f
--- /dev/null
+++ b/qpdf/qtest/qpdf/c-info1.out
@@ -0,0 +1,6 @@
+Info key /Author: (null)
+Info key /Producer: (null)
+Info key /Creator: (null)
+Info key /Author: Mr. Potato Head
+Info key /Producer: QPDF libary
+Info key /Creator: (null)
diff --git a/qpdf/qtest/qpdf/c-info2-in.pdf b/qpdf/qtest/qpdf/c-info2-in.pdf
new file mode 100644
index 00000000..7a83ea2c
--- /dev/null
+++ b/qpdf/qtest/qpdf/c-info2-in.pdf
Binary files differ
diff --git a/qpdf/qtest/qpdf/c-info2.out b/qpdf/qtest/qpdf/c-info2.out
new file mode 100644
index 00000000..0b25722b
--- /dev/null
+++ b/qpdf/qtest/qpdf/c-info2.out
@@ -0,0 +1,6 @@
+Info key /Author: Someone Else
+Info key /Producer: Something Else
+Info key /Creator: A. Nony Mous
+Info key /Author: Mr. Potato Head
+Info key /Producer: QPDF libary
+Info key /Creator: (null)