Use JSON::parse to initialize schema for json mode

This commit is contained in:
Jay Berkenbilt 2022-01-19 11:21:48 -05:00
parent 37105710ee
commit 2e58541493
1 changed files with 126 additions and 272 deletions

View File

@ -1462,10 +1462,9 @@ QPDFJob::json_schema(std::set<std::string>* keys)
"version", JSON::makeString( "version", JSON::makeString(
"JSON format serial number; increased for non-compatible changes")); "JSON format serial number; increased for non-compatible changes"));
JSON j_params = schema.addDictionaryMember( JSON j_params = schema.addDictionaryMember(
"parameters", JSON::makeDictionary()); "parameters", JSON::parse(R"({
j_params.addDictionaryMember( "decodelevel": "decode level used to determine stream filterability"
"decodelevel", JSON::makeString( })"));
"decode level used to determine stream filterability"));
bool all_keys = ((keys == 0) || keys->empty()); bool all_keys = ((keys == 0) || keys->empty());
@ -1482,297 +1481,152 @@ QPDFJob::json_schema(std::set<std::string>* keys)
if (all_keys || keys->count("objectinfo")) if (all_keys || keys->count("objectinfo"))
{ {
JSON objectinfo = schema.addDictionaryMember( JSON objectinfo = schema.addDictionaryMember(
"objectinfo", JSON::makeDictionary()); "objectinfo", JSON::parse(R"({
JSON details = objectinfo.addDictionaryMember( "<object-id>": {
"<object-id>", JSON::makeDictionary()); "stream": {
JSON stream = details.addDictionaryMember( "filter": "if stream, its filters, otherwise null",
"stream", JSON::makeDictionary()); "is": "whether the object is a stream",
stream.addDictionaryMember( "length": "if stream, its length, otherwise null"
"is", }
JSON::makeString("whether the object is a stream")); }
stream.addDictionaryMember( })"));
"length",
JSON::makeString("if stream, its length, otherwise null"));
stream.addDictionaryMember(
"filter",
JSON::makeString("if stream, its filters, otherwise null"));
} }
if (all_keys || keys->count("pages")) if (all_keys || keys->count("pages"))
{ {
JSON page = schema.addDictionaryMember("pages", JSON::makeArray()). JSON page = schema.addDictionaryMember("pages", JSON::parse(R"([
addArrayElement(JSON::makeDictionary()); {
page.addDictionaryMember( "contents": [
"object", "reference to each content stream"
JSON::makeString("reference to original page object")); ],
JSON image = page.addDictionaryMember("images", JSON::makeArray()). "images": [
addArrayElement(JSON::makeDictionary()); {
image.addDictionaryMember( "bitspercomponent": "bits per component",
"name", "colorspace": "color space",
JSON::makeString("name of image in XObject table")); "decodeparms": [
image.addDictionaryMember( "decode parameters for image data"
"object", ],
JSON::makeString("reference to image stream")); "filter": [
image.addDictionaryMember( "filters applied to image data"
"width", ],
JSON::makeString("image width")); "filterable": "whether image data can be decoded using the decode level qpdf was invoked with",
image.addDictionaryMember( "height": "image height",
"height", "name": "name of image in XObject table",
JSON::makeString("image height")); "object": "reference to image stream",
image.addDictionaryMember( "width": "image width"
"colorspace", }
JSON::makeString("color space")); ],
image.addDictionaryMember( "label": "page label dictionary, or null if none",
"bitspercomponent", "object": "reference to original page object",
JSON::makeString("bits per component")); "outlines": [
image.addDictionaryMember("filter", JSON::makeArray()). {
addArrayElement( "dest": "outline destination dictionary",
JSON::makeString("filters applied to image data")); "object": "reference to outline that targets this page",
image.addDictionaryMember("decodeparms", JSON::makeArray()). "title": "outline title"
addArrayElement( }
JSON::makeString("decode parameters for image data")); ],
image.addDictionaryMember( "pageposfrom1": "position of page in document numbering from 1"
"filterable", }
JSON::makeString("whether image data can be decoded" ])"));
" using the decode level qpdf was invoked with"));
page.addDictionaryMember("contents", JSON::makeArray()).
addArrayElement(
JSON::makeString("reference to each content stream"));
page.addDictionaryMember(
"label",
JSON::makeString("page label dictionary, or null if none"));
JSON outline = page.addDictionaryMember("outlines", JSON::makeArray()).
addArrayElement(JSON::makeDictionary());
outline.addDictionaryMember(
"object",
JSON::makeString("reference to outline that targets this page"));
outline.addDictionaryMember(
"title",
JSON::makeString("outline title"));
outline.addDictionaryMember(
"dest",
JSON::makeString("outline destination dictionary"));
page.addDictionaryMember(
"pageposfrom1",
JSON::makeString("position of page in document numbering from 1"));
} }
if (all_keys || keys->count("pagelabels")) if (all_keys || keys->count("pagelabels"))
{ {
JSON labels = schema.addDictionaryMember( JSON labels = schema.addDictionaryMember(
"pagelabels", JSON::makeArray()). "pagelabels", JSON::parse(R"([
addArrayElement(JSON::makeDictionary()); {
labels.addDictionaryMember( "index": "starting page position starting from zero",
"index", "label": "page label dictionary"
JSON::makeString("starting page position starting from zero")); }
labels.addDictionaryMember( ])"));
"label",
JSON::makeString("page label dictionary"));
} }
if (all_keys || keys->count("outlines")) if (all_keys || keys->count("outlines"))
{ {
JSON outlines = schema.addDictionaryMember( JSON outlines = schema.addDictionaryMember(
"outlines", JSON::makeArray()). "outlines", JSON::parse(R"([
addArrayElement(JSON::makeDictionary()); {
outlines.addDictionaryMember( "dest": "outline destination dictionary",
"object", "destpageposfrom1": "position of destination page in document numbered from 1; null if not known",
JSON::makeString("reference to this outline")); "kids": "array of descendent outlines",
outlines.addDictionaryMember( "object": "reference to this outline",
"title", "open": "whether the outline is displayed expanded",
JSON::makeString("outline title")); "title": "outline title"
outlines.addDictionaryMember( }
"dest", ])"));
JSON::makeString("outline destination dictionary"));
outlines.addDictionaryMember(
"kids",
JSON::makeString("array of descendent outlines"));
outlines.addDictionaryMember(
"open",
JSON::makeString("whether the outline is displayed expanded"));
outlines.addDictionaryMember(
"destpageposfrom1",
JSON::makeString("position of destination page in document"
" numbered from 1; null if not known"));
} }
if (all_keys || keys->count("acroform")) if (all_keys || keys->count("acroform"))
{ {
JSON acroform = schema.addDictionaryMember( JSON acroform = schema.addDictionaryMember(
"acroform", JSON::makeDictionary()); "acroform", JSON::parse(R"({
acroform.addDictionaryMember( "fields": [
"hasacroform", {
JSON::makeString("whether the document has interactive forms")); "alternativename": "alternative name of field -- this is the one usually shown to users",
acroform.addDictionaryMember( "annotation": {
"needappearances", "annotationflags": "annotation flags from /F -- see pdf_annotation_flag_e in qpdf/Constants.h",
JSON::makeString("whether the form fields' appearance" "appearancestate": "appearance state -- can be used to determine value for checkboxes and radio buttons",
" streams need to be regenerated")); "object": "reference to the annotation object"
JSON fields = acroform.addDictionaryMember( },
"fields", JSON::makeArray()). "choices": "for choices fields, the list of choices presented to the user",
addArrayElement(JSON::makeDictionary()); "defaultvalue": "default value of field",
fields.addDictionaryMember( "fieldflags": "form field flags from /Ff -- see pdf_form_field_flag_e in qpdf/Constants.h",
"object", "fieldtype": "field type",
JSON::makeString("reference to this form field")); "fullname": "full name of field",
fields.addDictionaryMember( "ischeckbox": "whether field is a checkbox",
"parent", "ischoice": "whether field is a list, combo, or dropdown",
JSON::makeString("reference to this field's parent")); "isradiobutton": "whether field is a radio button -- buttons in a single group share a parent",
fields.addDictionaryMember( "istext": "whether field is a text field",
"pageposfrom1", "mappingname": "mapping name of field",
JSON::makeString("position of containing page numbered from 1")); "object": "reference to this form field",
fields.addDictionaryMember( "pageposfrom1": "position of containing page numbered from 1",
"fieldtype", "parent": "reference to this field's parent",
JSON::makeString("field type")); "partialname": "partial name of field",
fields.addDictionaryMember( "quadding": "field quadding -- number indicating left, center, or right",
"fieldflags", "value": "value of field"
JSON::makeString( }
"form field flags from /Ff --" ],
" see pdf_form_field_flag_e in qpdf/Constants.h")); "hasacroform": "whether the document has interactive forms",
fields.addDictionaryMember( "needappearances": "whether the form fields' appearance streams need to be regenerated"
"fullname", })"));
JSON::makeString("full name of field"));
fields.addDictionaryMember(
"partialname",
JSON::makeString("partial name of field"));
fields.addDictionaryMember(
"alternativename",
JSON::makeString(
"alternative name of field --"
" this is the one usually shown to users"));
fields.addDictionaryMember(
"mappingname",
JSON::makeString("mapping name of field"));
fields.addDictionaryMember(
"value",
JSON::makeString("value of field"));
fields.addDictionaryMember(
"defaultvalue",
JSON::makeString("default value of field"));
fields.addDictionaryMember(
"quadding",
JSON::makeString(
"field quadding --"
" number indicating left, center, or right"));
fields.addDictionaryMember(
"ischeckbox",
JSON::makeString("whether field is a checkbox"));
fields.addDictionaryMember(
"isradiobutton",
JSON::makeString("whether field is a radio button --"
" buttons in a single group share a parent"));
fields.addDictionaryMember(
"ischoice",
JSON::makeString("whether field is a list, combo, or dropdown"));
fields.addDictionaryMember(
"istext",
JSON::makeString("whether field is a text field"));
JSON j_choices = fields.addDictionaryMember(
"choices",
JSON::makeString("for choices fields, the list of"
" choices presented to the user"));
JSON annotation = fields.addDictionaryMember(
"annotation", JSON::makeDictionary());
annotation.addDictionaryMember(
"object",
JSON::makeString("reference to the annotation object"));
annotation.addDictionaryMember(
"appearancestate",
JSON::makeString("appearance state --"
" can be used to determine value for"
" checkboxes and radio buttons"));
annotation.addDictionaryMember(
"annotationflags",
JSON::makeString(
"annotation flags from /F --"
" see pdf_annotation_flag_e in qpdf/Constants.h"));
} }
if (all_keys || keys->count("encrypt")) if (all_keys || keys->count("encrypt"))
{ {
JSON encrypt = schema.addDictionaryMember( JSON encrypt = schema.addDictionaryMember(
"encrypt", JSON::makeDictionary()); "encrypt", JSON::parse(R"({
encrypt.addDictionaryMember( "capabilities": {
"encrypted", "accessibility": "allow extraction for accessibility?",
JSON::makeString("whether the document is encrypted")); "extract": "allow extraction?",
encrypt.addDictionaryMember( "moddifyannotations": "allow modifying annotations?",
"userpasswordmatched", "modify": "allow all modifications?",
JSON::makeString("whether supplied password matched user password;" "modifyassembly": "allow modifying document assembly?",
" always false for non-encrypted files")); "modifyforms": "allow modifying forms?",
encrypt.addDictionaryMember( "modifyother": "allow other modifications?",
"ownerpasswordmatched", "printhigh": "allow high resolution printing?",
JSON::makeString("whether supplied password matched owner password;" "printlow": "allow low resolution printing?"
" always false for non-encrypted files")); },
JSON capabilities = encrypt.addDictionaryMember( "encrypted": "whether the document is encrypted",
"capabilities", JSON::makeDictionary()); "ownerpasswordmatched": "whether supplied password matched owner password; always false for non-encrypted files",
capabilities.addDictionaryMember( "parameters": {
"accessibility", "P": "P value from Encrypt dictionary",
JSON::makeString("allow extraction for accessibility?")); "R": "R value from Encrypt dictionary",
capabilities.addDictionaryMember( "V": "V value from Encrypt dictionary",
"extract", "bits": "encryption key bit length",
JSON::makeString("allow extraction?")); "filemethod": "encryption method for attachments",
capabilities.addDictionaryMember( "key": "encryption key; will be null unless --show-encryption-key was specified",
"printlow", "method": "overall encryption method: none, mixed, RC4, AESv2, AESv3",
JSON::makeString("allow low resolution printing?")); "streammethod": "encryption method for streams",
capabilities.addDictionaryMember( "stringmethod": "encryption method for string"
"printhigh", },
JSON::makeString("allow high resolution printing?")); "userpasswordmatched": "whether supplied password matched user password; always false for non-encrypted files"
capabilities.addDictionaryMember( })"));
"modifyassembly",
JSON::makeString("allow modifying document assembly?"));
capabilities.addDictionaryMember(
"modifyforms",
JSON::makeString("allow modifying forms?"));
capabilities.addDictionaryMember(
"moddifyannotations",
JSON::makeString("allow modifying annotations?"));
capabilities.addDictionaryMember(
"modifyother",
JSON::makeString("allow other modifications?"));
capabilities.addDictionaryMember(
"modify",
JSON::makeString("allow all modifications?"));
JSON parameters = encrypt.addDictionaryMember(
"parameters", JSON::makeDictionary());
parameters.addDictionaryMember(
"R",
JSON::makeString("R value from Encrypt dictionary"));
parameters.addDictionaryMember(
"V",
JSON::makeString("V value from Encrypt dictionary"));
parameters.addDictionaryMember(
"P",
JSON::makeString("P value from Encrypt dictionary"));
parameters.addDictionaryMember(
"bits",
JSON::makeString("encryption key bit length"));
parameters.addDictionaryMember(
"key",
JSON::makeString("encryption key; will be null"
" unless --show-encryption-key was specified"));
parameters.addDictionaryMember(
"method",
JSON::makeString("overall encryption method:"
" none, mixed, RC4, AESv2, AESv3"));
parameters.addDictionaryMember(
"streammethod",
JSON::makeString("encryption method for streams"));
parameters.addDictionaryMember(
"stringmethod",
JSON::makeString("encryption method for string"));
parameters.addDictionaryMember(
"filemethod",
JSON::makeString("encryption method for attachments"));
} }
if (all_keys || keys->count("attachments")) if (all_keys || keys->count("attachments"))
{ {
JSON attachments = schema.addDictionaryMember( JSON attachments = schema.addDictionaryMember(
"attachments", JSON::makeDictionary()); "attachments", JSON::parse(R"({
JSON details = attachments.addDictionaryMember( "<attachment-key>": {
"<attachment-key>", JSON::makeDictionary()); "filespec": "object containing the file spec",
details.addDictionaryMember( "preferredcontents": "most preferred embedded file stream",
"filespec", "preferredname": "most preferred file name"
JSON::makeString("object containing the file spec")); }
details.addDictionaryMember( })"));
"preferredname",
JSON::makeString("most preferred file name"));
details.addDictionaryMember(
"preferredcontents",
JSON::makeString("most preferred embedded file stream"));
} }
return schema; return schema;
} }