summaryrefslogtreecommitdiffstats
path: root/qpdf
diff options
context:
space:
mode:
authorJay Berkenbilt <ejb@ql.org>2011-08-10 18:42:48 +0200
committerJay Berkenbilt <ejb@ql.org>2011-08-10 18:42:48 +0200
commit7dc197ef88a3f19a830f38d19aba649175d53c5e (patch)
treea143dac62c1779d855120a6e616c84fc08e586be /qpdf
parentb1a5b7e5d4c05a505c009668efa4472b6d4953d5 (diff)
downloadqpdf-7dc197ef88a3f19a830f38d19aba649175d53c5e.tar.zst
implement replace and swap
Diffstat (limited to 'qpdf')
-rw-r--r--qpdf/qpdf.testcov1
-rw-r--r--qpdf/qtest/qpdf.test11
-rw-r--r--qpdf/qtest/qpdf/test14-in.pdf264
-rw-r--r--qpdf/qtest/qpdf/test14-out.pdf105
-rw-r--r--qpdf/qtest/qpdf/test14.out6
-rw-r--r--qpdf/test_driver.cc56
6 files changed, 442 insertions, 1 deletions
diff --git a/qpdf/qpdf.testcov b/qpdf/qpdf.testcov
index 4e7e292a..37ad350a 100644
--- a/qpdf/qpdf.testcov
+++ b/qpdf/qpdf.testcov
@@ -192,3 +192,4 @@ QPDF stream without newline 0
QPDF stream with CR only 0
QPDF stream with CRNL 0
QPDF stream with NL only 0
+QPDF replaceObject called with indirect object 0
diff --git a/qpdf/qtest/qpdf.test b/qpdf/qtest/qpdf.test
index 75a92aa4..de82ce3b 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 += 31;
+$n_tests += 33;
$td->runtest("qpdf version",
{$td->COMMAND => "qpdf --version"},
@@ -276,6 +276,15 @@ $td->runtest("check output",
{$td->FILE => "a.qdf"},
{$td->FILE => "stream-line-enders.qdf"});
+$td->runtest("swap and replace",
+ {$td->COMMAND => "test_driver 14 test14-in.pdf"},
+ {$td->FILE => "test14.out",
+ $td->EXIT_STATUS => 0},
+ $td->NORMALIZE_NEWLINES);
+$td->runtest("check output",
+ {$td->FILE => "a.pdf"},
+ {$td->FILE => "test14-out.pdf"});
+
show_ntests();
# ----------
$td->notify("--- Error Condition Tests ---");
diff --git a/qpdf/qtest/qpdf/test14-in.pdf b/qpdf/qtest/qpdf/test14-in.pdf
new file mode 100644
index 00000000..4d761020
--- /dev/null
+++ b/qpdf/qtest/qpdf/test14-in.pdf
@@ -0,0 +1,264 @@
+%PDF-1.3
+%¿÷¢þ
+%QDF-1.0
+
+1 0 obj
+<<
+ /Pages 4 0 R
+ /Type /Catalog
+>>
+endobj
+
+2 0 obj
+[
+ /Array
+]
+endobj
+
+3 0 obj
+<<
+ /Dict 1
+>>
+endobj
+
+4 0 obj
+<<
+ /Count 4
+ /Kids [
+ 5 0 R
+ 6 0 R
+ 7 0 R
+ 8 0 R
+ ]
+ /Type /Pages
+>>
+endobj
+
+%% Page 1
+5 0 obj
+<<
+ /Contents 9 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 4 0 R
+ /Resources <<
+ /Font <<
+ /F1 11 0 R
+ >>
+ /ProcSet 12 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 2
+6 0 obj
+<<
+ /Contents 13 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 4 0 R
+ /Resources <<
+ /Font <<
+ /F1 11 0 R
+ >>
+ /ProcSet 15 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 3
+7 0 obj
+<<
+ /Contents 16 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 4 0 R
+ /Resources <<
+ /Font <<
+ /F1 11 0 R
+ >>
+ /ProcSet 18 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Page 4
+8 0 obj
+<<
+ /Contents 19 0 R
+ /MediaBox [
+ 0
+ 0
+ 612
+ 792
+ ]
+ /Parent 4 0 R
+ /Resources <<
+ /Font <<
+ /F1 11 0 R
+ >>
+ /ProcSet 21 0 R
+ >>
+ /Type /Page
+>>
+endobj
+
+%% Contents for page 1
+9 0 obj
+<<
+ /Length 10 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 1) Tj
+ET
+endstream
+endobj
+
+10 0 obj
+46
+endobj
+
+11 0 obj
+<<
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+ /Name /F1
+ /Subtype /Type1
+ /Type /Font
+>>
+endobj
+
+12 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+%% Contents for page 2
+13 0 obj
+<<
+ /Length 14 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 2) Tj
+ET
+endstream
+endobj
+
+14 0 obj
+46
+endobj
+
+15 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+%% Contents for page 3
+16 0 obj
+<<
+ /Length 17 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 3) Tj
+ET
+endstream
+endobj
+
+17 0 obj
+46
+endobj
+
+18 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+%% Contents for page 4
+19 0 obj
+<<
+ /Length 20 0 R
+>>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 4) Tj
+ET
+endstream
+endobj
+
+20 0 obj
+46
+endobj
+
+21 0 obj
+[
+ /PDF
+ /Text
+]
+endobj
+
+xref
+0 22
+0000000000 65535 f
+0000000025 00000 n
+0000000079 00000 n
+0000000108 00000 n
+0000000140 00000 n
+0000000252 00000 n
+0000000456 00000 n
+0000000661 00000 n
+0000000866 00000 n
+0000001084 00000 n
+0000001186 00000 n
+0000001206 00000 n
+0000001325 00000 n
+0000001384 00000 n
+0000001487 00000 n
+0000001507 00000 n
+0000001566 00000 n
+0000001669 00000 n
+0000001689 00000 n
+0000001748 00000 n
+0000001851 00000 n
+0000001871 00000 n
+trailer <<
+ /QArray 2 0 R
+ /QDict 3 0 R
+ /Root 1 0 R
+ /Size 22
+ /ID [<20eb74876a3e8212c1b4fd43153860b0><1bb7a926da191c58f675435d77997d21>]
+>>
+startxref
+1907
+%%EOF
diff --git a/qpdf/qtest/qpdf/test14-out.pdf b/qpdf/qtest/qpdf/test14-out.pdf
new file mode 100644
index 00000000..315d174d
--- /dev/null
+++ b/qpdf/qtest/qpdf/test14-out.pdf
@@ -0,0 +1,105 @@
+%PDF-1.3
+%¿÷¢þ
+1 0 obj
+<< /Pages 4 0 R /Type /Catalog >>
+endobj
+2 0 obj
+<< /NewDict 2 >>
+endobj
+3 0 obj
+[ /Array ]
+endobj
+4 0 obj
+<< /Count 4 /Kids [ 5 0 R 6 0 R 7 0 R 8 0 R ] /Type /Pages >>
+endobj
+5 0 obj
+<< /Contents 9 0 R /MediaBox [ 0 0 612 792 ] /Parent 4 0 R /Resources << /Font << /F1 10 0 R >> /ProcSet 11 0 R >> /Type /Page >>
+endobj
+6 0 obj
+<< /Contents 12 0 R /MediaBox [ 0 0 612 792 ] /Parent 4 0 R /Resources << /Font << /F1 10 0 R >> /ProcSet 13 0 R >> /Type /Page >>
+endobj
+7 0 obj
+<< /Contents 14 0 R /MediaBox [ 0 0 612 792 ] /Parent 4 0 R /Resources << /Font << /F1 10 0 R >> /ProcSet 15 0 R >> /Type /Page >>
+endobj
+8 0 obj
+<< /Contents 16 0 R /MediaBox [ 0 0 612 792 ] /Parent 4 0 R /Resources << /Font << /F1 10 0 R >> /ProcSet 17 0 R >> /Type /Page >>
+endobj
+9 0 obj
+<< /Length 46 >>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 1) Tj
+ET
+endstream
+endobj
+10 0 obj
+<< /BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font >>
+endobj
+11 0 obj
+[ /PDF /Text ]
+endobj
+12 0 obj
+<< /Length 46 >>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 3) Tj
+ET
+endstream
+endobj
+13 0 obj
+[ /PDF /Text ]
+endobj
+14 0 obj
+<< /Length 46 >>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 2) Tj
+ET
+endstream
+endobj
+15 0 obj
+[ /PDF /Text ]
+endobj
+16 0 obj
+<< /Length 46 >>
+stream
+BT
+ /F1 24 Tf
+ 72 720 Td
+ (Potato 4) Tj
+ET
+endstream
+endobj
+17 0 obj
+[ /PDF /Text ]
+endobj
+xref
+0 18
+0000000000 65535 f
+0000000015 00000 n
+0000000064 00000 n
+0000000096 00000 n
+0000000122 00000 n
+0000000199 00000 n
+0000000344 00000 n
+0000000490 00000 n
+0000000636 00000 n
+0000000782 00000 n
+0000000877 00000 n
+0000000985 00000 n
+0000001016 00000 n
+0000001112 00000 n
+0000001143 00000 n
+0000001239 00000 n
+0000001270 00000 n
+0000001366 00000 n
+trailer << /QArray 2 0 R /QDict 3 0 R /Root 1 0 R /Size 18 /ID [<20eb74876a3e8212c1b4fd43153860b0><31415926535897932384626433832795>] >>
+startxref
+1397
+%%EOF
diff --git a/qpdf/qtest/qpdf/test14.out b/qpdf/qtest/qpdf/test14.out
new file mode 100644
index 00000000..5b68d9f6
--- /dev/null
+++ b/qpdf/qtest/qpdf/test14.out
@@ -0,0 +1,6 @@
+caught logic error as expected
+old dict: 1
+old dict: 1
+new dict: 2
+swapped array: /Array
+test 14 done
diff --git a/qpdf/test_driver.cc b/qpdf/test_driver.cc
index c7b6a6b4..17451dc7 100644
--- a/qpdf/test_driver.cc
+++ b/qpdf/test_driver.cc
@@ -519,6 +519,62 @@ void runtest(int n, char const* filename)
<< "---error---" << std::endl
<< err.str();
}
+ else if (n == 14)
+ {
+ // Exercise swap and replace. This test case is designed for
+ // a specific file.
+ std::vector<QPDFObjectHandle> pages = pdf.getAllPages();
+ if (pages.size() != 4)
+ {
+ throw std::logic_error("test " + QUtil::int_to_string(n) +
+ " not called 4-page file");
+ }
+ // Swap pages 2 and 3
+ pdf.swapObjects(pages[1].getObjectID(), pages[1].getGeneration(),
+ pages[2].getObjectID(), pages[2].getGeneration());
+ // Replace object and swap objects
+ QPDFObjectHandle trailer = pdf.getTrailer();
+ QPDFObjectHandle qdict = trailer.getKey("/QDict");
+ QPDFObjectHandle qarray = trailer.getKey("/QArray");
+ // Force qdict but not qarray to resolve
+ qdict.isDictionary();
+ std::map<std::string, QPDFObjectHandle> dict_keys;
+ dict_keys["/NewDict"] = QPDFObjectHandle::newInteger(2);
+ QPDFObjectHandle new_dict = QPDFObjectHandle::newDictionary(dict_keys);
+ try
+ {
+ // Do it wrong first...
+ pdf.replaceObject(qdict.getObjectID(), qdict.getGeneration(),
+ qdict);
+ }
+ catch (std::logic_error)
+ {
+ std::cout << "caught logic error as expected" << std::endl;
+ }
+ pdf.replaceObject(qdict.getObjectID(), qdict.getGeneration(),
+ new_dict);
+ // Now qdict still points to the old dictionary
+ std::cout << "old dict: " << qdict.getKey("/Dict").getIntValue()
+ << std::endl;
+ // Swap dict and array
+ pdf.swapObjects(qdict.getObjectID(), qdict.getGeneration(),
+ qarray.getObjectID(), qarray.getGeneration());
+ // Now qarray will resolve to new object but qdict is still
+ // the old object
+ std::cout << "old dict: " << qdict.getKey("/Dict").getIntValue()
+ << std::endl;
+ std::cout << "new dict: " << qarray.getKey("/NewDict").getIntValue()
+ << std::endl;
+ // Reread qdict, now pointing to an array
+ qdict = pdf.getObjectByID(qdict.getObjectID(), qdict.getGeneration());
+ std::cout << "swapped array: " << qdict.getArrayItem(0).getName()
+ << std::endl;
+
+ QPDFWriter w(pdf, "a.pdf");
+ w.setStaticID(true);
+ w.setStreamDataMode(qpdf_s_preserve);
+ w.write();
+ }
else
{
throw std::runtime_error(std::string("invalid test ") +