Commit 7fa5d1773b599df51df21658dff53f5b66fdbba8
1 parent
8d42eb26
Implement top-level qpdf json parsing
Showing
37 changed files
with
1053 additions
and
8 deletions
TODO
| @@ -54,6 +54,13 @@ Soon: Break ground on "Document-level work" | @@ -54,6 +54,13 @@ Soon: Break ground on "Document-level work" | ||
| 54 | Output JSON v2 | 54 | Output JSON v2 |
| 55 | ============== | 55 | ============== |
| 56 | 56 | ||
| 57 | +Try to never flatten pages tree. Make sure we do something reasonable | ||
| 58 | +with pages tree repair. The problem is that if pages tree repair is | ||
| 59 | +done as a side effect of running --json, the qpdf part of the json may | ||
| 60 | +contain object numbers that aren't there. Maybe we need to indicate | ||
| 61 | +whether pages tree repair has been done in the json, but this would | ||
| 62 | +have to be known early in parsing, which is a problem. | ||
| 63 | + | ||
| 57 | General things to remember: | 64 | General things to remember: |
| 58 | 65 | ||
| 59 | * Make sure all the information from --check and other informational | 66 | * Make sure all the information from --check and other informational |
include/qpdf/QPDF.hh
| @@ -998,6 +998,7 @@ class QPDF | @@ -998,6 +998,7 @@ class QPDF | ||
| 998 | class JSONReactor: public JSON::Reactor | 998 | class JSONReactor: public JSON::Reactor |
| 999 | { | 999 | { |
| 1000 | public: | 1000 | public: |
| 1001 | + JSONReactor(QPDF&, bool must_be_complete); | ||
| 1001 | virtual ~JSONReactor() = default; | 1002 | virtual ~JSONReactor() = default; |
| 1002 | virtual void dictionaryStart() override; | 1003 | virtual void dictionaryStart() override; |
| 1003 | virtual void arrayStart() override; | 1004 | virtual void arrayStart() override; |
| @@ -1006,6 +1007,32 @@ class QPDF | @@ -1006,6 +1007,32 @@ class QPDF | ||
| 1006 | virtual bool | 1007 | virtual bool |
| 1007 | dictionaryItem(std::string const& key, JSON const& value) override; | 1008 | dictionaryItem(std::string const& key, JSON const& value) override; |
| 1008 | virtual bool arrayItem(JSON const& value) override; | 1009 | virtual bool arrayItem(JSON const& value) override; |
| 1010 | + | ||
| 1011 | + private: | ||
| 1012 | + enum state_e { | ||
| 1013 | + st_initial, | ||
| 1014 | + st_top, | ||
| 1015 | + st_ignore, | ||
| 1016 | + st_qpdf, | ||
| 1017 | + st_objects_top, | ||
| 1018 | + st_trailer_top, | ||
| 1019 | + st_object_top, | ||
| 1020 | + st_stream, | ||
| 1021 | + st_object, | ||
| 1022 | + }; | ||
| 1023 | + | ||
| 1024 | + void containerStart(); | ||
| 1025 | + void nestedState(std::string const& key, JSON const& value, state_e); | ||
| 1026 | + | ||
| 1027 | + QPDF& pdf; | ||
| 1028 | + bool must_be_complete; | ||
| 1029 | + bool saw_qpdf; | ||
| 1030 | + bool saw_json_version; | ||
| 1031 | + bool saw_pdf_version; | ||
| 1032 | + bool saw_trailer; | ||
| 1033 | + state_e state; | ||
| 1034 | + state_e next_state; | ||
| 1035 | + std::vector<state_e> state_stack; | ||
| 1009 | }; | 1036 | }; |
| 1010 | friend class JSONReactor; | 1037 | friend class JSONReactor; |
| 1011 | 1038 |
libqpdf/QPDF_json.cc
| 1 | #include <qpdf/QPDF.hh> | 1 | #include <qpdf/QPDF.hh> |
| 2 | 2 | ||
| 3 | #include <qpdf/FileInputSource.hh> | 3 | #include <qpdf/FileInputSource.hh> |
| 4 | +#include <qpdf/QTC.hh> | ||
| 5 | +#include <qpdf/QUtil.hh> | ||
| 6 | +#include <regex> | ||
| 7 | + | ||
| 8 | +namespace | ||
| 9 | +{ | ||
| 10 | + class JSONExc: public std::runtime_error | ||
| 11 | + { | ||
| 12 | + public: | ||
| 13 | + JSONExc(JSON const& value, std::string const& msg) : | ||
| 14 | + std::runtime_error( | ||
| 15 | + "offset " + QUtil::uint_to_string(value.getStart()) + ": " + | ||
| 16 | + msg) | ||
| 17 | + { | ||
| 18 | + } | ||
| 19 | + }; | ||
| 20 | +} // namespace | ||
| 21 | + | ||
| 22 | +static std::regex PDF_VERSION_RE("^\\d+\\.\\d+$"); | ||
| 23 | +static std::regex OBJ_KEY_RE("^obj:(\\d+) (\\d+) R$"); | ||
| 24 | + | ||
| 25 | +QPDF::JSONReactor::JSONReactor(QPDF& pdf, bool must_be_complete) : | ||
| 26 | + pdf(pdf), | ||
| 27 | + must_be_complete(must_be_complete), | ||
| 28 | + saw_qpdf(false), | ||
| 29 | + saw_json_version(false), | ||
| 30 | + saw_pdf_version(false), | ||
| 31 | + saw_trailer(false), | ||
| 32 | + state(st_initial), | ||
| 33 | + next_state(st_top) | ||
| 34 | +{ | ||
| 35 | + state_stack.push_back(st_initial); | ||
| 36 | +} | ||
| 37 | + | ||
| 38 | +void | ||
| 39 | +QPDF::JSONReactor::containerStart() | ||
| 40 | +{ | ||
| 41 | + state_stack.push_back(state); | ||
| 42 | + state = next_state; | ||
| 43 | +} | ||
| 4 | 44 | ||
| 5 | void | 45 | void |
| 6 | QPDF::JSONReactor::dictionaryStart() | 46 | QPDF::JSONReactor::dictionaryStart() |
| 7 | { | 47 | { |
| 8 | - // QXXXXQ | 48 | + containerStart(); |
| 49 | + // QXXXQ | ||
| 9 | } | 50 | } |
| 10 | 51 | ||
| 11 | void | 52 | void |
| 12 | QPDF::JSONReactor::arrayStart() | 53 | QPDF::JSONReactor::arrayStart() |
| 13 | { | 54 | { |
| 14 | - // QXXXXQ | 55 | + containerStart(); |
| 56 | + if (state == st_top) { | ||
| 57 | + QTC::TC("qpdf", "QPDF_json top-level array"); | ||
| 58 | + throw std::runtime_error("QPDF JSON must be a dictionary"); | ||
| 59 | + } | ||
| 60 | + // QXXXQ | ||
| 15 | } | 61 | } |
| 16 | 62 | ||
| 17 | void | 63 | void |
| 18 | QPDF::JSONReactor::containerEnd(JSON const& value) | 64 | QPDF::JSONReactor::containerEnd(JSON const& value) |
| 19 | { | 65 | { |
| 20 | - // QXXXXQ | 66 | + state = state_stack.back(); |
| 67 | + state_stack.pop_back(); | ||
| 68 | + if (state == st_initial) { | ||
| 69 | + if (!this->saw_qpdf) { | ||
| 70 | + QTC::TC("qpdf", "QPDF_json missing qpdf"); | ||
| 71 | + throw std::runtime_error("\"qpdf\" object was not seen"); | ||
| 72 | + } | ||
| 73 | + if (!this->saw_json_version) { | ||
| 74 | + QTC::TC("qpdf", "QPDF_json missing json version"); | ||
| 75 | + throw std::runtime_error("\"qpdf.jsonversion\" was not seen"); | ||
| 76 | + } | ||
| 77 | + if (must_be_complete && !this->saw_pdf_version) { | ||
| 78 | + QTC::TC("qpdf", "QPDF_json missing pdf version"); | ||
| 79 | + throw std::runtime_error("\"qpdf.pdfversion\" was not seen"); | ||
| 80 | + } | ||
| 81 | + if (must_be_complete && !this->saw_trailer) { | ||
| 82 | + /// QTC::TC("qpdf", "QPDF_json missing trailer"); | ||
| 83 | + throw std::runtime_error("\"qpdf.objects.trailer\" was not seen"); | ||
| 84 | + } | ||
| 85 | + } | ||
| 86 | + | ||
| 87 | + // QXXXQ | ||
| 21 | } | 88 | } |
| 22 | 89 | ||
| 23 | void | 90 | void |
| 24 | QPDF::JSONReactor::topLevelScalar() | 91 | QPDF::JSONReactor::topLevelScalar() |
| 25 | { | 92 | { |
| 26 | - // QXXXXQ | 93 | + QTC::TC("qpdf", "QPDF_json top-level scalar"); |
| 94 | + throw std::runtime_error("QPDF JSON must be a dictionary"); | ||
| 95 | +} | ||
| 96 | + | ||
| 97 | +void | ||
| 98 | +QPDF::JSONReactor::nestedState( | ||
| 99 | + std::string const& key, JSON const& value, state_e next) | ||
| 100 | +{ | ||
| 101 | + // Use this method when the next state is for processing a nested | ||
| 102 | + // dictionary. | ||
| 103 | + if (!value.isDictionary()) { | ||
| 104 | + throw JSONExc(value, "\"" + key + "\" must be a dictionary"); | ||
| 105 | + } | ||
| 106 | + this->next_state = next; | ||
| 27 | } | 107 | } |
| 28 | 108 | ||
| 29 | bool | 109 | bool |
| 30 | QPDF::JSONReactor::dictionaryItem(std::string const& key, JSON const& value) | 110 | QPDF::JSONReactor::dictionaryItem(std::string const& key, JSON const& value) |
| 31 | { | 111 | { |
| 32 | - // QXXXXQ | 112 | + if (state == st_ignore) { |
| 113 | + // ignore | ||
| 114 | + } else if (state == st_top) { | ||
| 115 | + if (key == "qpdf") { | ||
| 116 | + this->saw_qpdf = true; | ||
| 117 | + nestedState(key, value, st_qpdf); | ||
| 118 | + } else { | ||
| 119 | + // Ignore all other fields for forward compatibility. | ||
| 120 | + // Don't use nestedState since this can be any type. | ||
| 121 | + next_state = st_ignore; | ||
| 122 | + } | ||
| 123 | + } else if (state == st_qpdf) { | ||
| 124 | + if (key == "jsonversion") { | ||
| 125 | + this->saw_json_version = true; | ||
| 126 | + std::string v; | ||
| 127 | + if (!(value.getNumber(v) && (v == "2"))) { | ||
| 128 | + QTC::TC("qpdf", "QPDF_json bad json version"); | ||
| 129 | + throw JSONExc(value, "only JSON version 2 is supported"); | ||
| 130 | + } | ||
| 131 | + } else if (key == "pdfversion") { | ||
| 132 | + this->saw_pdf_version = true; | ||
| 133 | + bool version_okay = false; | ||
| 134 | + std::string v; | ||
| 135 | + if (value.getString(v)) { | ||
| 136 | + std::smatch m; | ||
| 137 | + if (std::regex_match(v, m, PDF_VERSION_RE)) { | ||
| 138 | + version_okay = true; | ||
| 139 | + this->pdf.m->pdf_version = v; | ||
| 140 | + } | ||
| 141 | + } | ||
| 142 | + if (!version_okay) { | ||
| 143 | + QTC::TC("qpdf", "QPDF_json bad pdf version"); | ||
| 144 | + throw JSONExc(value, "invalid PDF version (must be x.y)"); | ||
| 145 | + } | ||
| 146 | + } else if (key == "objects") { | ||
| 147 | + nestedState(key, value, st_objects_top); | ||
| 148 | + } else { | ||
| 149 | + // ignore unknown keys for forward compatibility | ||
| 150 | + } | ||
| 151 | + } else if (state == st_objects_top) { | ||
| 152 | + std::smatch m; | ||
| 153 | + if (key == "trailer") { | ||
| 154 | + this->saw_trailer = true; | ||
| 155 | + nestedState(key, value, st_trailer_top); | ||
| 156 | + // QXXXQ | ||
| 157 | + } else if (std::regex_match(key, m, OBJ_KEY_RE)) { | ||
| 158 | + nestedState(key, value, st_object_top); | ||
| 159 | + // QXXXQ | ||
| 160 | + } else { | ||
| 161 | + QTC::TC("qpdf", "QPDF_json bad object key"); | ||
| 162 | + throw JSONExc( | ||
| 163 | + value, "object key should be \"trailer\" or \"obj:n n R\""); | ||
| 164 | + } | ||
| 165 | + } else if (state == st_object_top) { | ||
| 166 | + if (key == "value") { | ||
| 167 | + // Don't use nestedState since this can have any type. | ||
| 168 | + next_state = st_object; | ||
| 169 | + // QXXXQ | ||
| 170 | + } else if (key == "stream") { | ||
| 171 | + nestedState(key, value, st_stream); | ||
| 172 | + // QXXXQ | ||
| 173 | + } else { | ||
| 174 | + // Ignore unknown keys for forward compatibility | ||
| 175 | + } | ||
| 176 | + } else if (state == st_trailer_top) { | ||
| 177 | + if (key == "value") { | ||
| 178 | + // The trailer must be a dictionary, so we can use nestedState. | ||
| 179 | + nestedState("trailer.value", value, st_object); | ||
| 180 | + // QXXXQ | ||
| 181 | + } else if (key == "stream") { | ||
| 182 | + QTC::TC("qpdf", "QPDF_json trailer stream"); | ||
| 183 | + throw JSONExc(value, "the trailer may not be a stream"); | ||
| 184 | + } else { | ||
| 185 | + // Ignore unknown keys for forward compatibility | ||
| 186 | + } | ||
| 187 | + } else if (state == st_stream) { | ||
| 188 | + if (key == "dict") { | ||
| 189 | + // Since a stream dictionary must be a dictionary, we can | ||
| 190 | + // use nestedState to transition to st_value. | ||
| 191 | + nestedState("stream.dict", value, st_object); | ||
| 192 | + // QXXXQ | ||
| 193 | + } else if (key == "data") { | ||
| 194 | + // QXXXQ | ||
| 195 | + } else if (key == "datafile") { | ||
| 196 | + // QXXXQ | ||
| 197 | + } else { | ||
| 198 | + // Ignore unknown keys for forward compatibility. | ||
| 199 | + next_state = st_ignore; | ||
| 200 | + } | ||
| 201 | + } else if (state == st_object) { | ||
| 202 | + // QXXXQ | ||
| 203 | + } else { | ||
| 204 | + throw std::logic_error( | ||
| 205 | + "QPDF_json: unknown state " + QUtil::int_to_string(state)); | ||
| 206 | + } | ||
| 207 | + | ||
| 208 | + // QXXXQ | ||
| 33 | return true; | 209 | return true; |
| 34 | } | 210 | } |
| 35 | 211 | ||
| 36 | bool | 212 | bool |
| 37 | QPDF::JSONReactor::arrayItem(JSON const& value) | 213 | QPDF::JSONReactor::arrayItem(JSON const& value) |
| 38 | { | 214 | { |
| 39 | - // QXXXXQ | 215 | + // QXXXQ |
| 40 | return true; | 216 | return true; |
| 41 | } | 217 | } |
| 42 | 218 | ||
| @@ -65,7 +241,12 @@ QPDF::updateFromJSON(std::shared_ptr<InputSource> is) | @@ -65,7 +241,12 @@ QPDF::updateFromJSON(std::shared_ptr<InputSource> is) | ||
| 65 | } | 241 | } |
| 66 | 242 | ||
| 67 | void | 243 | void |
| 68 | -QPDF::importJSON(std::shared_ptr<InputSource>, bool must_be_complete) | 244 | +QPDF::importJSON(std::shared_ptr<InputSource> is, bool must_be_complete) |
| 69 | { | 245 | { |
| 70 | - // QXXXQ | 246 | + JSONReactor reactor(*this, must_be_complete); |
| 247 | + try { | ||
| 248 | + JSON::parse(*is, &reactor); | ||
| 249 | + } catch (std::runtime_error& e) { | ||
| 250 | + throw std::runtime_error(is->getName() + ": " + e.what()); | ||
| 251 | + } | ||
| 71 | } | 252 | } |
qpdf/qpdf.testcov
| @@ -650,3 +650,12 @@ QPDFJob json encrypt duplicate key length 0 | @@ -650,3 +650,12 @@ QPDFJob json encrypt duplicate key length 0 | ||
| 650 | QPDFJob json encrypt missing password 0 | 650 | QPDFJob json encrypt missing password 0 |
| 651 | QPDFJob json pages no file 0 | 651 | QPDFJob json pages no file 0 |
| 652 | qpdf-c called qpdf_empty_pdf 0 | 652 | qpdf-c called qpdf_empty_pdf 0 |
| 653 | +QPDF_json missing qpdf 0 | ||
| 654 | +QPDF_json missing json version 0 | ||
| 655 | +QPDF_json missing pdf version 0 | ||
| 656 | +QPDF_json top-level scalar 0 | ||
| 657 | +QPDF_json bad json version 0 | ||
| 658 | +QPDF_json bad pdf version 0 | ||
| 659 | +QPDF_json top-level array 0 | ||
| 660 | +QPDF_json bad object key 0 | ||
| 661 | +QPDF_json trailer stream 0 |
qpdf/qtest/qpdf-json.test
0 โ 100644
| 1 | +#!/usr/bin/env perl | ||
| 2 | +require 5.008; | ||
| 3 | +use warnings; | ||
| 4 | +use strict; | ||
| 5 | + | ||
| 6 | +unshift(@INC, '.'); | ||
| 7 | +require qpdf_test_helpers; | ||
| 8 | + | ||
| 9 | +chdir("qpdf") or die "chdir testdir failed: $!\n"; | ||
| 10 | + | ||
| 11 | +require TestDriver; | ||
| 12 | + | ||
| 13 | +cleanup(); | ||
| 14 | + | ||
| 15 | +my $td = new TestDriver('qpdf-json'); | ||
| 16 | + | ||
| 17 | +my $n_tests = 0; | ||
| 18 | + | ||
| 19 | +my @badfiles = ( | ||
| 20 | + 'no-qpdf-object', | ||
| 21 | + 'no-json-version', | ||
| 22 | + 'no-pdf-version', | ||
| 23 | + 'top-level-scalar', | ||
| 24 | + 'bad-json-version1', | ||
| 25 | + 'bad-json-version2', | ||
| 26 | + 'bad-pdf-version1', | ||
| 27 | + 'bad-pdf-version2', | ||
| 28 | + 'top-level-array', | ||
| 29 | + 'objects-not-dict', | ||
| 30 | + 'bad-object-key', | ||
| 31 | + 'object-not-dict', | ||
| 32 | + 'stream-not-dict', | ||
| 33 | + 'stream-dict-not-dict', | ||
| 34 | + 'trailer-not-dict', | ||
| 35 | + 'trailer-stream', | ||
| 36 | + ); | ||
| 37 | + | ||
| 38 | +$n_tests += scalar(@badfiles); | ||
| 39 | + | ||
| 40 | +foreach my $f (@badfiles) | ||
| 41 | +{ | ||
| 42 | + $td->runtest("bad: $f", | ||
| 43 | + {$td->COMMAND => | ||
| 44 | + "qpdf --create-from-json=qjson-$f.json a.pdf"}, | ||
| 45 | + {$td->FILE => "qjson-$f.out", $td->EXIT_STATUS => 2}, | ||
| 46 | + $td->NORMALIZE_NEWLINES); | ||
| 47 | +} | ||
| 48 | + | ||
| 49 | +cleanup(); | ||
| 50 | +$td->report($n_tests); |
qpdf/qtest/qpdf/qjson-bad-json-version1.json
0 โ 100644
| 1 | +{ | ||
| 2 | + "version": 2, | ||
| 3 | + "parameters": { | ||
| 4 | + "decodelevel": "none" | ||
| 5 | + }, | ||
| 6 | + "qpdf": { | ||
| 7 | + "jsonversion": 16059, | ||
| 8 | + "pdfversion": "1.3", | ||
| 9 | + "maxobjectid": 6, | ||
| 10 | + "objects": { | ||
| 11 | + "obj:1 0 R": { | ||
| 12 | + "value": { | ||
| 13 | + "/Pages": "2 0 R", | ||
| 14 | + "/Type": "/Catalog" | ||
| 15 | + } | ||
| 16 | + }, | ||
| 17 | + "obj:2 0 R": { | ||
| 18 | + "value": { | ||
| 19 | + "/Count": 1, | ||
| 20 | + "/Kids": [ | ||
| 21 | + "3 0 R" | ||
| 22 | + ], | ||
| 23 | + "/Type": "/Pages" | ||
| 24 | + } | ||
| 25 | + }, | ||
| 26 | + "obj:3 0 R": { | ||
| 27 | + "value": { | ||
| 28 | + "/Contents": "4 0 R", | ||
| 29 | + "/MediaBox": [ | ||
| 30 | + 0, | ||
| 31 | + 0, | ||
| 32 | + 612, | ||
| 33 | + 792 | ||
| 34 | + ], | ||
| 35 | + "/Parent": "2 0 R", | ||
| 36 | + "/Resources": { | ||
| 37 | + "/Font": { | ||
| 38 | + "/F1": "6 0 R" | ||
| 39 | + }, | ||
| 40 | + "/ProcSet": "5 0 R" | ||
| 41 | + }, | ||
| 42 | + "/Type": "/Page" | ||
| 43 | + } | ||
| 44 | + }, | ||
| 45 | + "obj:4 0 R": { | ||
| 46 | + "stream": { | ||
| 47 | + "data": "QlQKICAvRjEgMjQgVGYKICA3MiA3MjAgVGQKICAoUG90YXRvKSBUagpFVAo=", | ||
| 48 | + "dict": {} | ||
| 49 | + } | ||
| 50 | + }, | ||
| 51 | + "obj:5 0 R": { | ||
| 52 | + "value": [ | ||
| 53 | + "/PDF", | ||
| 54 | + "/Text" | ||
| 55 | + ] | ||
| 56 | + }, | ||
| 57 | + "obj:6 0 R": { | ||
| 58 | + "value": { | ||
| 59 | + "/BaseFont": "/Helvetica", | ||
| 60 | + "/Encoding": "/WinAnsiEncoding", | ||
| 61 | + "/Subtype": "/Type1", | ||
| 62 | + "/Type": "/Font" | ||
| 63 | + } | ||
| 64 | + }, | ||
| 65 | + "trailer": { | ||
| 66 | + "value": { | ||
| 67 | + "/Root": "1 0 R", | ||
| 68 | + "/Size": 7 | ||
| 69 | + } | ||
| 70 | + } | ||
| 71 | + } | ||
| 72 | + } | ||
| 73 | +} |
qpdf/qtest/qpdf/qjson-bad-json-version1.out
0 โ 100644
| 1 | +qpdf: qjson-bad-json-version1.json: offset 98: only JSON version 2 is supported |
qpdf/qtest/qpdf/qjson-bad-json-version2.json
0 โ 100644
| 1 | +{ | ||
| 2 | + "version": 2, | ||
| 3 | + "parameters": { | ||
| 4 | + "decodelevel": "none" | ||
| 5 | + }, | ||
| 6 | + "qpdf": { | ||
| 7 | + "jsonversion": "potato", | ||
| 8 | + "pdfversion": "1.3", | ||
| 9 | + "maxobjectid": 6, | ||
| 10 | + "objects": { | ||
| 11 | + "obj:1 0 R": { | ||
| 12 | + "value": { | ||
| 13 | + "/Pages": "2 0 R", | ||
| 14 | + "/Type": "/Catalog" | ||
| 15 | + } | ||
| 16 | + }, | ||
| 17 | + "obj:2 0 R": { | ||
| 18 | + "value": { | ||
| 19 | + "/Count": 1, | ||
| 20 | + "/Kids": [ | ||
| 21 | + "3 0 R" | ||
| 22 | + ], | ||
| 23 | + "/Type": "/Pages" | ||
| 24 | + } | ||
| 25 | + }, | ||
| 26 | + "obj:3 0 R": { | ||
| 27 | + "value": { | ||
| 28 | + "/Contents": "4 0 R", | ||
| 29 | + "/MediaBox": [ | ||
| 30 | + 0, | ||
| 31 | + 0, | ||
| 32 | + 612, | ||
| 33 | + 792 | ||
| 34 | + ], | ||
| 35 | + "/Parent": "2 0 R", | ||
| 36 | + "/Resources": { | ||
| 37 | + "/Font": { | ||
| 38 | + "/F1": "6 0 R" | ||
| 39 | + }, | ||
| 40 | + "/ProcSet": "5 0 R" | ||
| 41 | + }, | ||
| 42 | + "/Type": "/Page" | ||
| 43 | + } | ||
| 44 | + }, | ||
| 45 | + "obj:4 0 R": { | ||
| 46 | + "stream": { | ||
| 47 | + "data": "QlQKICAvRjEgMjQgVGYKICA3MiA3MjAgVGQKICAoUG90YXRvKSBUagpFVAo=", | ||
| 48 | + "dict": {} | ||
| 49 | + } | ||
| 50 | + }, | ||
| 51 | + "obj:5 0 R": { | ||
| 52 | + "value": [ | ||
| 53 | + "/PDF", | ||
| 54 | + "/Text" | ||
| 55 | + ] | ||
| 56 | + }, | ||
| 57 | + "obj:6 0 R": { | ||
| 58 | + "value": { | ||
| 59 | + "/BaseFont": "/Helvetica", | ||
| 60 | + "/Encoding": "/WinAnsiEncoding", | ||
| 61 | + "/Subtype": "/Type1", | ||
| 62 | + "/Type": "/Font" | ||
| 63 | + } | ||
| 64 | + }, | ||
| 65 | + "trailer": { | ||
| 66 | + "value": { | ||
| 67 | + "/Root": "1 0 R", | ||
| 68 | + "/Size": 7 | ||
| 69 | + } | ||
| 70 | + } | ||
| 71 | + } | ||
| 72 | + } | ||
| 73 | +} |
qpdf/qtest/qpdf/qjson-bad-json-version2.out
0 โ 100644
| 1 | +qpdf: qjson-bad-json-version2.json: offset 98: only JSON version 2 is supported |
qpdf/qtest/qpdf/qjson-bad-object-key.json
0 โ 100644
| 1 | +{ | ||
| 2 | + "version": 2, | ||
| 3 | + "parameters": { | ||
| 4 | + "decodelevel": "none" | ||
| 5 | + }, | ||
| 6 | + "qpdf": { | ||
| 7 | + "jsonversion": 2, | ||
| 8 | + "pdfversion": "1.3", | ||
| 9 | + "maxobjectid": 6, | ||
| 10 | + "objects": { | ||
| 11 | + "potato": { | ||
| 12 | + }, | ||
| 13 | + "obj:1 0 R": { | ||
| 14 | + "value": { | ||
| 15 | + "/Pages": "2 0 R", | ||
| 16 | + "/Type": "/Catalog" | ||
| 17 | + } | ||
| 18 | + }, | ||
| 19 | + "obj:2 0 R": { | ||
| 20 | + "value": { | ||
| 21 | + "/Count": 1, | ||
| 22 | + "/Kids": [ | ||
| 23 | + "3 0 R" | ||
| 24 | + ], | ||
| 25 | + "/Type": "/Pages" | ||
| 26 | + } | ||
| 27 | + }, | ||
| 28 | + "obj:3 0 R": { | ||
| 29 | + "value": { | ||
| 30 | + "/Contents": "4 0 R", | ||
| 31 | + "/MediaBox": [ | ||
| 32 | + 0, | ||
| 33 | + 0, | ||
| 34 | + 612, | ||
| 35 | + 792 | ||
| 36 | + ], | ||
| 37 | + "/Parent": "2 0 R", | ||
| 38 | + "/Resources": { | ||
| 39 | + "/Font": { | ||
| 40 | + "/F1": "6 0 R" | ||
| 41 | + }, | ||
| 42 | + "/ProcSet": "5 0 R" | ||
| 43 | + }, | ||
| 44 | + "/Type": "/Page" | ||
| 45 | + } | ||
| 46 | + }, | ||
| 47 | + "obj:4 0 R": { | ||
| 48 | + "stream": { | ||
| 49 | + "data": "QlQKICAvRjEgMjQgVGYKICA3MiA3MjAgVGQKICAoUG90YXRvKSBUagpFVAo=", | ||
| 50 | + "dict": {} | ||
| 51 | + } | ||
| 52 | + }, | ||
| 53 | + "obj:5 0 R": { | ||
| 54 | + "value": [ | ||
| 55 | + "/PDF", | ||
| 56 | + "/Text" | ||
| 57 | + ] | ||
| 58 | + }, | ||
| 59 | + "obj:6 0 R": { | ||
| 60 | + "value": { | ||
| 61 | + "/BaseFont": "/Helvetica", | ||
| 62 | + "/Encoding": "/WinAnsiEncoding", | ||
| 63 | + "/Subtype": "/Type1", | ||
| 64 | + "/Type": "/Font" | ||
| 65 | + } | ||
| 66 | + }, | ||
| 67 | + "trailer": { | ||
| 68 | + "value": { | ||
| 69 | + "/Root": "1 0 R", | ||
| 70 | + "/Size": 7 | ||
| 71 | + } | ||
| 72 | + } | ||
| 73 | + } | ||
| 74 | + } | ||
| 75 | +} |
qpdf/qtest/qpdf/qjson-bad-object-key.out
0 โ 100644
| 1 | +qpdf: qjson-bad-object-key.json: offset 181: object key should be "trailer" or "obj:n n R" |
qpdf/qtest/qpdf/qjson-bad-pdf-version1.json
0 โ 100644
| 1 | +{ | ||
| 2 | + "version": 2, | ||
| 3 | + "parameters": { | ||
| 4 | + "decodelevel": "none" | ||
| 5 | + }, | ||
| 6 | + "qpdf": { | ||
| 7 | + "jsonversion": 2, | ||
| 8 | + "pdfversion": "potato", | ||
| 9 | + "maxobjectid": 6, | ||
| 10 | + "objects": { | ||
| 11 | + "obj:1 0 R": { | ||
| 12 | + "value": { | ||
| 13 | + "/Pages": "2 0 R", | ||
| 14 | + "/Type": "/Catalog" | ||
| 15 | + } | ||
| 16 | + }, | ||
| 17 | + "obj:2 0 R": { | ||
| 18 | + "value": { | ||
| 19 | + "/Count": 1, | ||
| 20 | + "/Kids": [ | ||
| 21 | + "3 0 R" | ||
| 22 | + ], | ||
| 23 | + "/Type": "/Pages" | ||
| 24 | + } | ||
| 25 | + }, | ||
| 26 | + "obj:3 0 R": { | ||
| 27 | + "value": { | ||
| 28 | + "/Contents": "4 0 R", | ||
| 29 | + "/MediaBox": [ | ||
| 30 | + 0, | ||
| 31 | + 0, | ||
| 32 | + 612, | ||
| 33 | + 792 | ||
| 34 | + ], | ||
| 35 | + "/Parent": "2 0 R", | ||
| 36 | + "/Resources": { | ||
| 37 | + "/Font": { | ||
| 38 | + "/F1": "6 0 R" | ||
| 39 | + }, | ||
| 40 | + "/ProcSet": "5 0 R" | ||
| 41 | + }, | ||
| 42 | + "/Type": "/Page" | ||
| 43 | + } | ||
| 44 | + }, | ||
| 45 | + "obj:4 0 R": { | ||
| 46 | + "stream": { | ||
| 47 | + "data": "QlQKICAvRjEgMjQgVGYKICA3MiA3MjAgVGQKICAoUG90YXRvKSBUagpFVAo=", | ||
| 48 | + "dict": {} | ||
| 49 | + } | ||
| 50 | + }, | ||
| 51 | + "obj:5 0 R": { | ||
| 52 | + "value": [ | ||
| 53 | + "/PDF", | ||
| 54 | + "/Text" | ||
| 55 | + ] | ||
| 56 | + }, | ||
| 57 | + "obj:6 0 R": { | ||
| 58 | + "value": { | ||
| 59 | + "/BaseFont": "/Helvetica", | ||
| 60 | + "/Encoding": "/WinAnsiEncoding", | ||
| 61 | + "/Subtype": "/Type1", | ||
| 62 | + "/Type": "/Font" | ||
| 63 | + } | ||
| 64 | + }, | ||
| 65 | + "trailer": { | ||
| 66 | + "value": { | ||
| 67 | + "/Root": "1 0 R", | ||
| 68 | + "/Size": 7 | ||
| 69 | + } | ||
| 70 | + } | ||
| 71 | + } | ||
| 72 | + } | ||
| 73 | +} |
qpdf/qtest/qpdf/qjson-bad-pdf-version1.out
0 โ 100644
| 1 | +qpdf: qjson-bad-pdf-version1.json: offset 119: invalid PDF version (must be x.y) |
qpdf/qtest/qpdf/qjson-bad-pdf-version2.json
0 โ 100644
| 1 | +{ | ||
| 2 | + "version": 2, | ||
| 3 | + "parameters": { | ||
| 4 | + "decodelevel": "none" | ||
| 5 | + }, | ||
| 6 | + "qpdf": { | ||
| 7 | + "jsonversion": 2, | ||
| 8 | + "pdfversion": [], | ||
| 9 | + "maxobjectid": 6, | ||
| 10 | + "objects": { | ||
| 11 | + "obj:1 0 R": { | ||
| 12 | + "value": { | ||
| 13 | + "/Pages": "2 0 R", | ||
| 14 | + "/Type": "/Catalog" | ||
| 15 | + } | ||
| 16 | + }, | ||
| 17 | + "obj:2 0 R": { | ||
| 18 | + "value": { | ||
| 19 | + "/Count": 1, | ||
| 20 | + "/Kids": [ | ||
| 21 | + "3 0 R" | ||
| 22 | + ], | ||
| 23 | + "/Type": "/Pages" | ||
| 24 | + } | ||
| 25 | + }, | ||
| 26 | + "obj:3 0 R": { | ||
| 27 | + "value": { | ||
| 28 | + "/Contents": "4 0 R", | ||
| 29 | + "/MediaBox": [ | ||
| 30 | + 0, | ||
| 31 | + 0, | ||
| 32 | + 612, | ||
| 33 | + 792 | ||
| 34 | + ], | ||
| 35 | + "/Parent": "2 0 R", | ||
| 36 | + "/Resources": { | ||
| 37 | + "/Font": { | ||
| 38 | + "/F1": "6 0 R" | ||
| 39 | + }, | ||
| 40 | + "/ProcSet": "5 0 R" | ||
| 41 | + }, | ||
| 42 | + "/Type": "/Page" | ||
| 43 | + } | ||
| 44 | + }, | ||
| 45 | + "obj:4 0 R": { | ||
| 46 | + "stream": { | ||
| 47 | + "data": "QlQKICAvRjEgMjQgVGYKICA3MiA3MjAgVGQKICAoUG90YXRvKSBUagpFVAo=", | ||
| 48 | + "dict": {} | ||
| 49 | + } | ||
| 50 | + }, | ||
| 51 | + "obj:5 0 R": { | ||
| 52 | + "value": [ | ||
| 53 | + "/PDF", | ||
| 54 | + "/Text" | ||
| 55 | + ] | ||
| 56 | + }, | ||
| 57 | + "obj:6 0 R": { | ||
| 58 | + "value": { | ||
| 59 | + "/BaseFont": "/Helvetica", | ||
| 60 | + "/Encoding": "/WinAnsiEncoding", | ||
| 61 | + "/Subtype": "/Type1", | ||
| 62 | + "/Type": "/Font" | ||
| 63 | + } | ||
| 64 | + }, | ||
| 65 | + "trailer": { | ||
| 66 | + "value": { | ||
| 67 | + "/Root": "1 0 R", | ||
| 68 | + "/Size": 7 | ||
| 69 | + } | ||
| 70 | + } | ||
| 71 | + } | ||
| 72 | + } | ||
| 73 | +} |
qpdf/qtest/qpdf/qjson-bad-pdf-version2.out
0 โ 100644
| 1 | +qpdf: qjson-bad-pdf-version2.json: offset 119: invalid PDF version (must be x.y) |
qpdf/qtest/qpdf/qjson-no-json-version.json
0 โ 100644
| 1 | +{ | ||
| 2 | + "version": 2, | ||
| 3 | + "parameters": { | ||
| 4 | + "decodelevel": "none" | ||
| 5 | + }, | ||
| 6 | + "qpdf": { | ||
| 7 | + "pdfversion": "1.3", | ||
| 8 | + "maxobjectid": 6, | ||
| 9 | + "objects": { | ||
| 10 | + "obj:1 0 R": { | ||
| 11 | + "value": { | ||
| 12 | + "/Pages": "2 0 R", | ||
| 13 | + "/Type": "/Catalog" | ||
| 14 | + } | ||
| 15 | + }, | ||
| 16 | + "obj:2 0 R": { | ||
| 17 | + "value": { | ||
| 18 | + "/Count": 1, | ||
| 19 | + "/Kids": [ | ||
| 20 | + "3 0 R" | ||
| 21 | + ], | ||
| 22 | + "/Type": "/Pages" | ||
| 23 | + } | ||
| 24 | + }, | ||
| 25 | + "obj:3 0 R": { | ||
| 26 | + "value": { | ||
| 27 | + "/Contents": "4 0 R", | ||
| 28 | + "/MediaBox": [ | ||
| 29 | + 0, | ||
| 30 | + 0, | ||
| 31 | + 612, | ||
| 32 | + 792 | ||
| 33 | + ], | ||
| 34 | + "/Parent": "2 0 R", | ||
| 35 | + "/Resources": { | ||
| 36 | + "/Font": { | ||
| 37 | + "/F1": "6 0 R" | ||
| 38 | + }, | ||
| 39 | + "/ProcSet": "5 0 R" | ||
| 40 | + }, | ||
| 41 | + "/Type": "/Page" | ||
| 42 | + } | ||
| 43 | + }, | ||
| 44 | + "obj:4 0 R": { | ||
| 45 | + "stream": { | ||
| 46 | + "data": "QlQKICAvRjEgMjQgVGYKICA3MiA3MjAgVGQKICAoUG90YXRvKSBUagpFVAo=", | ||
| 47 | + "dict": {} | ||
| 48 | + } | ||
| 49 | + }, | ||
| 50 | + "obj:5 0 R": { | ||
| 51 | + "value": [ | ||
| 52 | + "/PDF", | ||
| 53 | + "/Text" | ||
| 54 | + ] | ||
| 55 | + }, | ||
| 56 | + "obj:6 0 R": { | ||
| 57 | + "value": { | ||
| 58 | + "/BaseFont": "/Helvetica", | ||
| 59 | + "/Encoding": "/WinAnsiEncoding", | ||
| 60 | + "/Subtype": "/Type1", | ||
| 61 | + "/Type": "/Font" | ||
| 62 | + } | ||
| 63 | + }, | ||
| 64 | + "trailer": { | ||
| 65 | + "value": { | ||
| 66 | + "/Root": "1 0 R", | ||
| 67 | + "/Size": 7 | ||
| 68 | + } | ||
| 69 | + } | ||
| 70 | + } | ||
| 71 | + } | ||
| 72 | +} |
qpdf/qtest/qpdf/qjson-no-json-version.out
0 โ 100644
| 1 | +qpdf: qjson-no-json-version.json: "qpdf.jsonversion" was not seen |
qpdf/qtest/qpdf/qjson-no-pdf-version.json
0 โ 100644
| 1 | +{ | ||
| 2 | + "version": 2, | ||
| 3 | + "parameters": { | ||
| 4 | + "decodelevel": "none" | ||
| 5 | + }, | ||
| 6 | + "qpdf": { | ||
| 7 | + "jsonversion": 2, | ||
| 8 | + "maxobjectid": 6, | ||
| 9 | + "objects": { | ||
| 10 | + "obj:1 0 R": { | ||
| 11 | + "value": { | ||
| 12 | + "/Pages": "2 0 R", | ||
| 13 | + "/Type": "/Catalog" | ||
| 14 | + } | ||
| 15 | + }, | ||
| 16 | + "obj:2 0 R": { | ||
| 17 | + "value": { | ||
| 18 | + "/Count": 1, | ||
| 19 | + "/Kids": [ | ||
| 20 | + "3 0 R" | ||
| 21 | + ], | ||
| 22 | + "/Type": "/Pages" | ||
| 23 | + } | ||
| 24 | + }, | ||
| 25 | + "obj:3 0 R": { | ||
| 26 | + "value": { | ||
| 27 | + "/Contents": "4 0 R", | ||
| 28 | + "/MediaBox": [ | ||
| 29 | + 0, | ||
| 30 | + 0, | ||
| 31 | + 612, | ||
| 32 | + 792 | ||
| 33 | + ], | ||
| 34 | + "/Parent": "2 0 R", | ||
| 35 | + "/Resources": { | ||
| 36 | + "/Font": { | ||
| 37 | + "/F1": "6 0 R" | ||
| 38 | + }, | ||
| 39 | + "/ProcSet": "5 0 R" | ||
| 40 | + }, | ||
| 41 | + "/Type": "/Page" | ||
| 42 | + } | ||
| 43 | + }, | ||
| 44 | + "obj:4 0 R": { | ||
| 45 | + "stream": { | ||
| 46 | + "data": "QlQKICAvRjEgMjQgVGYKICA3MiA3MjAgVGQKICAoUG90YXRvKSBUagpFVAo=", | ||
| 47 | + "dict": {} | ||
| 48 | + } | ||
| 49 | + }, | ||
| 50 | + "obj:5 0 R": { | ||
| 51 | + "value": [ | ||
| 52 | + "/PDF", | ||
| 53 | + "/Text" | ||
| 54 | + ] | ||
| 55 | + }, | ||
| 56 | + "obj:6 0 R": { | ||
| 57 | + "value": { | ||
| 58 | + "/BaseFont": "/Helvetica", | ||
| 59 | + "/Encoding": "/WinAnsiEncoding", | ||
| 60 | + "/Subtype": "/Type1", | ||
| 61 | + "/Type": "/Font" | ||
| 62 | + } | ||
| 63 | + }, | ||
| 64 | + "trailer": { | ||
| 65 | + "value": { | ||
| 66 | + "/Root": "1 0 R", | ||
| 67 | + "/Size": 7 | ||
| 68 | + } | ||
| 69 | + } | ||
| 70 | + } | ||
| 71 | + } | ||
| 72 | +} |
qpdf/qtest/qpdf/qjson-no-pdf-version.out
0 โ 100644
| 1 | +qpdf: qjson-no-pdf-version.json: "qpdf.pdfversion" was not seen |
qpdf/qtest/qpdf/qjson-no-qpdf-object.json
0 โ 100644
qpdf/qtest/qpdf/qjson-no-qpdf-object.out
0 โ 100644
| 1 | +qpdf: qjson-no-qpdf-object.json: "qpdf" object was not seen |
qpdf/qtest/qpdf/qjson-object-not-dict.json
0 โ 100644
| 1 | +{ | ||
| 2 | + "version": 2, | ||
| 3 | + "parameters": { | ||
| 4 | + "decodelevel": "none" | ||
| 5 | + }, | ||
| 6 | + "qpdf": { | ||
| 7 | + "jsonversion": 2, | ||
| 8 | + "pdfversion": "1.3", | ||
| 9 | + "maxobjectid": 6, | ||
| 10 | + "objects": { | ||
| 11 | + "obj:1 0 R": "potato", | ||
| 12 | + "obj:2 0 R": { | ||
| 13 | + "value": { | ||
| 14 | + "/Count": 1, | ||
| 15 | + "/Kids": [ | ||
| 16 | + "3 0 R" | ||
| 17 | + ], | ||
| 18 | + "/Type": "/Pages" | ||
| 19 | + } | ||
| 20 | + }, | ||
| 21 | + "obj:3 0 R": { | ||
| 22 | + "value": { | ||
| 23 | + "/Contents": "4 0 R", | ||
| 24 | + "/MediaBox": [ | ||
| 25 | + 0, | ||
| 26 | + 0, | ||
| 27 | + 612, | ||
| 28 | + 792 | ||
| 29 | + ], | ||
| 30 | + "/Parent": "2 0 R", | ||
| 31 | + "/Resources": { | ||
| 32 | + "/Font": { | ||
| 33 | + "/F1": "6 0 R" | ||
| 34 | + }, | ||
| 35 | + "/ProcSet": "5 0 R" | ||
| 36 | + }, | ||
| 37 | + "/Type": "/Page" | ||
| 38 | + } | ||
| 39 | + }, | ||
| 40 | + "obj:4 0 R": { | ||
| 41 | + "stream": { | ||
| 42 | + "data": "QlQKICAvRjEgMjQgVGYKICA3MiA3MjAgVGQKICAoUG90YXRvKSBUagpFVAo=", | ||
| 43 | + "dict": {} | ||
| 44 | + } | ||
| 45 | + }, | ||
| 46 | + "obj:5 0 R": { | ||
| 47 | + "value": [ | ||
| 48 | + "/PDF", | ||
| 49 | + "/Text" | ||
| 50 | + ] | ||
| 51 | + }, | ||
| 52 | + "obj:6 0 R": { | ||
| 53 | + "value": { | ||
| 54 | + "/BaseFont": "/Helvetica", | ||
| 55 | + "/Encoding": "/WinAnsiEncoding", | ||
| 56 | + "/Subtype": "/Type1", | ||
| 57 | + "/Type": "/Font" | ||
| 58 | + } | ||
| 59 | + }, | ||
| 60 | + "trailer": { | ||
| 61 | + "value": { | ||
| 62 | + "/Root": "1 0 R", | ||
| 63 | + "/Size": 7 | ||
| 64 | + } | ||
| 65 | + } | ||
| 66 | + } | ||
| 67 | + } | ||
| 68 | +} |
qpdf/qtest/qpdf/qjson-object-not-dict.out
0 โ 100644
| 1 | +qpdf: qjson-object-not-dict.json: offset 184: "obj:1 0 R" must be a dictionary |
qpdf/qtest/qpdf/qjson-objects-not-dict.json
0 โ 100644
qpdf/qtest/qpdf/qjson-objects-not-dict.out
0 โ 100644
| 1 | +qpdf: qjson-objects-not-dict.json: offset 77: "objects" must be a dictionary |
qpdf/qtest/qpdf/qjson-stream-dict-not-dict.json
0 โ 100644
qpdf/qtest/qpdf/qjson-stream-dict-not-dict.out
0 โ 100644
| 1 | +qpdf: qjson-stream-dict-not-dict.json: offset 137: "stream.dict" must be a dictionary |
qpdf/qtest/qpdf/qjson-stream-not-dict.json
0 โ 100644
qpdf/qtest/qpdf/qjson-stream-not-dict.out
0 โ 100644
| 1 | +qpdf: qjson-stream-not-dict.json: offset 118: "stream" must be a dictionary |
qpdf/qtest/qpdf/qjson-top-level-array.json
0 โ 100644
| 1 | +["potato"] |
qpdf/qtest/qpdf/qjson-top-level-array.out
0 โ 100644
| 1 | +qpdf: qjson-top-level-array.json: QPDF JSON must be a dictionary |
qpdf/qtest/qpdf/qjson-top-level-scalar.json
0 โ 100644
| 1 | +"potato" |
qpdf/qtest/qpdf/qjson-top-level-scalar.out
0 โ 100644
| 1 | +qpdf: qjson-top-level-scalar.json: QPDF JSON must be a dictionary |
qpdf/qtest/qpdf/qjson-trailer-not-dict.json
0 โ 100644
| 1 | +{ | ||
| 2 | + "version": 2, | ||
| 3 | + "parameters": { | ||
| 4 | + "decodelevel": "none" | ||
| 5 | + }, | ||
| 6 | + "qpdf": { | ||
| 7 | + "jsonversion": 2, | ||
| 8 | + "pdfversion": "1.3", | ||
| 9 | + "maxobjectid": 6, | ||
| 10 | + "objects": { | ||
| 11 | + "obj:1 0 R": { | ||
| 12 | + "value": { | ||
| 13 | + "/Pages": "2 0 R", | ||
| 14 | + "/Type": "/Catalog" | ||
| 15 | + } | ||
| 16 | + }, | ||
| 17 | + "obj:2 0 R": { | ||
| 18 | + "value": { | ||
| 19 | + "/Count": 1, | ||
| 20 | + "/Kids": [ | ||
| 21 | + "3 0 R" | ||
| 22 | + ], | ||
| 23 | + "/Type": "/Pages" | ||
| 24 | + } | ||
| 25 | + }, | ||
| 26 | + "obj:3 0 R": { | ||
| 27 | + "value": { | ||
| 28 | + "/Contents": "4 0 R", | ||
| 29 | + "/MediaBox": [ | ||
| 30 | + 0, | ||
| 31 | + 0, | ||
| 32 | + 612, | ||
| 33 | + 792 | ||
| 34 | + ], | ||
| 35 | + "/Parent": "2 0 R", | ||
| 36 | + "/Resources": { | ||
| 37 | + "/Font": { | ||
| 38 | + "/F1": "6 0 R" | ||
| 39 | + }, | ||
| 40 | + "/ProcSet": "5 0 R" | ||
| 41 | + }, | ||
| 42 | + "/Type": "/Page" | ||
| 43 | + } | ||
| 44 | + }, | ||
| 45 | + "obj:4 0 R": { | ||
| 46 | + "stream": { | ||
| 47 | + "data": "QlQKICAvRjEgMjQgVGYKICA3MiA3MjAgVGQKICAoUG90YXRvKSBUagpFVAo=", | ||
| 48 | + "dict": {} | ||
| 49 | + } | ||
| 50 | + }, | ||
| 51 | + "obj:5 0 R": { | ||
| 52 | + "value": [ | ||
| 53 | + "/PDF", | ||
| 54 | + "/Text" | ||
| 55 | + ] | ||
| 56 | + }, | ||
| 57 | + "obj:6 0 R": { | ||
| 58 | + "value": { | ||
| 59 | + "/BaseFont": "/Helvetica", | ||
| 60 | + "/Encoding": "/WinAnsiEncoding", | ||
| 61 | + "/Subtype": "/Type1", | ||
| 62 | + "/Type": "/Font" | ||
| 63 | + } | ||
| 64 | + }, | ||
| 65 | + "trailer": { | ||
| 66 | + "value": false, | ||
| 67 | + } | ||
| 68 | + } | ||
| 69 | + } | ||
| 70 | +} |
qpdf/qtest/qpdf/qjson-trailer-not-dict.out
0 โ 100644
| 1 | +qpdf: qjson-trailer-not-dict.json: offset 1326: "trailer.value" must be a dictionary |
qpdf/qtest/qpdf/qjson-trailer-stream.json
0 โ 100644
| 1 | +{ | ||
| 2 | + "version": 2, | ||
| 3 | + "parameters": { | ||
| 4 | + "decodelevel": "none" | ||
| 5 | + }, | ||
| 6 | + "qpdf": { | ||
| 7 | + "jsonversion": 2, | ||
| 8 | + "pdfversion": "1.3", | ||
| 9 | + "maxobjectid": 6, | ||
| 10 | + "objects": { | ||
| 11 | + "obj:1 0 R": { | ||
| 12 | + "value": { | ||
| 13 | + "/Pages": "2 0 R", | ||
| 14 | + "/Type": "/Catalog" | ||
| 15 | + } | ||
| 16 | + }, | ||
| 17 | + "obj:2 0 R": { | ||
| 18 | + "value": { | ||
| 19 | + "/Count": 1, | ||
| 20 | + "/Kids": [ | ||
| 21 | + "3 0 R" | ||
| 22 | + ], | ||
| 23 | + "/Type": "/Pages" | ||
| 24 | + } | ||
| 25 | + }, | ||
| 26 | + "obj:3 0 R": { | ||
| 27 | + "value": { | ||
| 28 | + "/Contents": "4 0 R", | ||
| 29 | + "/MediaBox": [ | ||
| 30 | + 0, | ||
| 31 | + 0, | ||
| 32 | + 612, | ||
| 33 | + 792 | ||
| 34 | + ], | ||
| 35 | + "/Parent": "2 0 R", | ||
| 36 | + "/Resources": { | ||
| 37 | + "/Font": { | ||
| 38 | + "/F1": "6 0 R" | ||
| 39 | + }, | ||
| 40 | + "/ProcSet": "5 0 R" | ||
| 41 | + }, | ||
| 42 | + "/Type": "/Page" | ||
| 43 | + } | ||
| 44 | + }, | ||
| 45 | + "obj:4 0 R": { | ||
| 46 | + "stream": { | ||
| 47 | + "data": "QlQKICAvRjEgMjQgVGYKICA3MiA3MjAgVGQKICAoUG90YXRvKSBUagpFVAo=", | ||
| 48 | + "dict": {} | ||
| 49 | + } | ||
| 50 | + }, | ||
| 51 | + "obj:5 0 R": { | ||
| 52 | + "value": [ | ||
| 53 | + "/PDF", | ||
| 54 | + "/Text" | ||
| 55 | + ] | ||
| 56 | + }, | ||
| 57 | + "obj:6 0 R": { | ||
| 58 | + "value": { | ||
| 59 | + "/BaseFont": "/Helvetica", | ||
| 60 | + "/Encoding": "/WinAnsiEncoding", | ||
| 61 | + "/Subtype": "/Type1", | ||
| 62 | + "/Type": "/Font" | ||
| 63 | + } | ||
| 64 | + }, | ||
| 65 | + "trailer": { | ||
| 66 | + "stream": {}, | ||
| 67 | + } | ||
| 68 | + } | ||
| 69 | + } | ||
| 70 | +} |
qpdf/qtest/qpdf/qjson-trailer-stream.out
0 โ 100644
| 1 | +qpdf: qjson-trailer-stream.json: offset 1327: the trailer may not be a stream |