Add additional information when listing attachments

This commit is contained in:
Jay Berkenbilt 2022-05-30 09:23:48 -04:00
parent 04fc7c4bea
commit f049a77c59
20 changed files with 1034 additions and 17 deletions

View File

@ -1,5 +1,8 @@
2022-05-30 Jay Berkenbilt <ejb@ql.org>
* Include additional information in --list-attachments --verbose
and in --json --json-key=attachments.
* Add QUtil::qpdf_time_to_iso8601 and QUtil::pdf_time_to_iso8601
for converting PDF/qpdf timestamps to ISO-8601 date format.

3
TODO
View File

@ -72,9 +72,6 @@ Remaining work:
* --encryption: show recovered user password when available
* --list-attachments: add information from --verbose. Add to a
"details" subkey.
* Consider having --check, --show-encryption, etc., just select the
right keys when in json mode. I don't think I want check on by
default, so that might be different.

View File

@ -14,4 +14,4 @@ libqpdf/qpdf/auto_job_json_decl.hh 06caa46eaf71db8a50c046f91866baa8087745a947431
libqpdf/qpdf/auto_job_json_init.hh 5f6b53e3c81d4b54ce5c4cf9c3f52d0c02f987c53bf8841c0280367bad23e335
libqpdf/qpdf/auto_job_schema.hh 9d543cd4a43eafffc2c4b8a6fee29e399c271c52cb6f7d417ae5497b3c1127dc
manual/_ext/qpdf.py 6add6321666031d55ed4aedf7c00e5662bba856dfcd66ccb526563bffefbb580
manual/cli.rst e7c35f8183d015d7fe074e38baed4c89bad827fd9c23b4cafd73d562df82ab1b
manual/cli.rst 82ead389c03bbf5e0498bd0571a11dc06544d591f4e4454c00322e3473fc556d

View File

@ -993,8 +993,16 @@ QPDFJob::doListAttachments(QPDF& pdf)
}
cout << " all data streams:" << std::endl;
for (auto i2: efoh->getEmbeddedFileStreams().ditems()) {
auto efs = QPDFEFStreamObjectHelper(i2.second);
cout << " " << i2.first << " -> "
<< i2.second.getObjGen() << std::endl;
<< efs.getObjectHandle().getObjGen() << std::endl;
cout << " creation date: " << efs.getCreationDate()
<< std::endl
<< " modification date: " << efs.getModDate()
<< std::endl
<< " mime type: " << efs.getSubtype() << std::endl
<< " checksum: "
<< QUtil::hex_encode(efs.getChecksum()) << std::endl;
}
});
}
@ -1445,6 +1453,22 @@ QPDFJob::doJSONEncrypt(Pipeline* p, bool& first, QPDF& pdf)
void
QPDFJob::doJSONAttachments(Pipeline* p, bool& first, QPDF& pdf)
{
auto to_iso8601 = [](std::string const& d) {
// Convert PDF date to iso8601 if not empty; if empty, return
// empty.
std::string iso8601;
QUtil::pdf_time_to_iso8601(d, iso8601);
return iso8601;
};
auto null_or_string = [](std::string const& s) {
if (s.empty()) {
return JSON::makeNull();
} else {
return JSON::makeString(s);
}
};
JSON j_attachments = JSON::makeDictionary();
QPDFEmbeddedFileDocumentHelper efdh(pdf);
for (auto const& iter: efdh.getEmbeddedFiles()) {
@ -1459,6 +1483,31 @@ QPDFJob::doJSONAttachments(Pipeline* p, bool& first, QPDF& pdf)
j_details.addDictionaryMember(
"preferredcontents",
JSON::makeString(fsoh->getEmbeddedFileStream().unparse()));
j_details.addDictionaryMember(
"description", null_or_string(fsoh->getDescription()));
auto j_names =
j_details.addDictionaryMember("names", JSON::makeDictionary());
for (auto const& i2: fsoh->getFilenames()) {
j_names.addDictionaryMember(i2.first, JSON::makeString(i2.second));
}
auto j_streams =
j_details.addDictionaryMember("streams", JSON::makeDictionary());
for (auto i2: fsoh->getEmbeddedFileStreams().ditems()) {
auto efs = QPDFEFStreamObjectHelper(i2.second);
auto j_stream =
j_streams.addDictionaryMember(i2.first, JSON::makeDictionary());
j_stream.addDictionaryMember(
"creationdate",
null_or_string(to_iso8601(efs.getCreationDate())));
j_stream.addDictionaryMember(
"modificationdate",
null_or_string(to_iso8601(efs.getCreationDate())));
j_stream.addDictionaryMember(
"mimetype", null_or_string(efs.getSubtype()));
j_stream.addDictionaryMember(
"checksum",
null_or_string(QUtil::hex_encode(efs.getChecksum())));
}
}
JSON::writeDictionaryItem(p, first, "attachments", j_attachments, 0);
}
@ -1640,7 +1689,19 @@ QPDFJob::json_schema(int json_version, std::set<std::string>* keys)
"<attachment-key>": {
"filespec": "object containing the file spec",
"preferredcontents": "most preferred embedded file stream",
"preferredname": "most preferred file name"
"preferredname": "most preferred file name",
"description": "description of attachment",
"names": {
"<name-key>": "file name for key"
},
"streams": {
"<stream-key>": {
"creationdate": "ISO-8601 creation date or null",
"modificationdate": "ISO-8601 modification date or null",
"mimetype": "mime type or null",
"checksum": "MD5 checksum or null"
}
}
}
})"));
}

View File

@ -3124,7 +3124,10 @@ Related Options
:qpdf:ref:`--verbose`, additional information, including preferred
file name, description, dates, and more are also displayed. The key
is usually but not always equal to the file name and is needed by
some of the other options. See also :ref:`attachments`.
some of the other options. See also :ref:`attachments`. Note that
this option displays dates in PDF timestamp syntax. When attachment
information is included in json output (see :ref:`--json`), dates
are shown in ISO-8601 format.
.. qpdf:option:: --show-attachment=key

View File

@ -96,6 +96,13 @@ For a detailed list of changes, please see the file
- See :ref:`breaking-crypto-api` for specific details, and see
:ref:`weak-crypto` for a general discussion.
- CLI Enhancements
- ``qpdf --list-attachments --verbose`` include some additional
information about attachments. Additional information about
attachments is also included in the ``attachments`` json key
with ``--json``.
- Library Enhancements
- New methods ``insertItemAndGet``, ``appendItemAndGet``,
@ -120,6 +127,9 @@ For a detailed list of changes, please see the file
- Add new ``Pipeline`` type ``Pl_String`` to append to a
``std::string``.
- Add methods to QUtil for converting PDF timestamps and QPDFTime
objects to ISO-8601 timestamps.
- Enhance JSON class to better support incrementally reading and
writing large amounts of data without having to keep everything
in memory.

View File

@ -189,7 +189,8 @@ $td->runtest("add attachments: current date",
$td->NORMALIZE_NEWLINES);
$td->runtest("list attachments",
{$td->COMMAND =>
"qpdf --password=u --list-attachments a.pdf --verbose"},
"qpdf --password=u --list-attachments a.pdf --verbose",
$td->FILTER => "perl filter-attachment-date.pl"},
{$td->FILE => "list-attachments-4.out", $td->EXIT_STATUS => 0},
$td->NORMALIZE_NEWLINES);
# The object to show here is the one in list-attachments-4.out

View File

@ -26,6 +26,7 @@ my @json_files = (
['field-types', ['--show-encryption-key']],
['image-streams', ['--decode-level=all']],
['image-streams', ['--decode-level=specialized']],
['attachment-fields', []],
['page-labels-and-outlines', ['--json-key=objects']],
['page-labels-and-outlines', ['--json-key=pages']],
['page-labels-and-outlines', ['--json-key=pagelabels']],

View File

@ -0,0 +1,190 @@
%PDF-1.3
%¿÷¢þ
%QDF-1.0
%% Original object ID: 1 0
1 0 obj
<<
/Names <<
/EmbeddedFiles 2 0 R
>>
/PageMode /UseAttachments
/Pages 3 0 R
/Type /Catalog
>>
endobj
%% Original object ID: 2 0
2 0 obj
<<
/Names [
(a.txt)
4 0 R
<feff03c0002e007400780074>
5 0 R
]
>>
endobj
%% Original object ID: 3 0
3 0 obj
<<
/Count 1
/Kids [
6 0 R
]
/Type /Pages
>>
endobj
%% Original object ID: 4 0
4 0 obj
<<
/EF <<
/F 7 0 R
/UF 7 0 R
>>
/F (a.txt)
/Type /Filespec
/UF (a.txt)
>>
endobj
%% Original object ID: 5 0
5 0 obj
<<
/Desc (Two filenames)
/EF <<
/F 9 0 R
/UF 9 0 R
>>
/F (pi.txt)
/Type /Filespec
/UF <feff03c0002e007400780074>
>>
endobj
%% Page 1
%% Original object ID: 6 0
6 0 obj
<<
/Contents 11 0 R
/MediaBox [
0
0
612
792
]
/Parent 3 0 R
/Resources <<
/Font <<
/F1 13 0 R
>>
/ProcSet 14 0 R
>>
/Type /Page
>>
endobj
%% Original object ID: 7 0
7 0 obj
<<
/Params <<
/Size 7
>>
/Type /EmbeddedFile
/Length 8 0 R
>>
stream
potato
endstream
endobj
8 0 obj
7
endobj
%% Original object ID: 8 0
9 0 obj
<<
/Params <<
/CheckSum <e561f9248d7563d15dd93457b02ebbb6>
/CreationDate (D:20220530094116-05'00')
/ModDate (D:20220530094116-05'00')
/Size 7
>>
/Subtype /text#2fplain
/Type /EmbeddedFile
/Length 10 0 R
>>
stream
potato
endstream
endobj
10 0 obj
7
endobj
%% Contents for page 1
%% Original object ID: 9 0
11 0 obj
<<
/Length 12 0 R
>>
stream
BT
/F1 24 Tf
72 720 Td
(Potato) Tj
ET
endstream
endobj
12 0 obj
44
endobj
%% Original object ID: 10 0
13 0 obj
<<
/BaseFont /Helvetica
/Encoding /WinAnsiEncoding
/Subtype /Type1
/Type /Font
>>
endobj
%% Original object ID: 11 0
14 0 obj
[
/PDF
/Text
]
endobj
xref
0 15
0000000000 65535 f
0000000052 00000 n
0000000203 00000 n
0000000330 00000 n
0000000429 00000 n
0000000564 00000 n
0000000753 00000 n
0000000975 00000 n
0000001089 00000 n
0000001134 00000 n
0000001406 00000 n
0000001475 00000 n
0000001576 00000 n
0000001624 00000 n
0000001759 00000 n
trailer <<
/Root 1 0 R
/Size 15
/ID [<3d1a89e08f9d6b3e1f787d04fceed440><4e13de38230bb10a03e49285a742c392>]
>>
startxref
1795
%%EOF

View File

@ -0,0 +1,8 @@
use warnings;
use strict;
while (<>)
{
s/D:\d{14}\S+/<date>/;
print;
}

View File

@ -0,0 +1,305 @@
{
"version": 1,
"parameters": {
"decodelevel": "generalized"
},
"pages": [
{
"contents": [
"11 0 R"
],
"images": [],
"label": null,
"object": "6 0 R",
"outlines": [],
"pageposfrom1": 1
}
],
"pagelabels": [],
"acroform": {
"fields": [],
"hasacroform": false,
"needappearances": false
},
"attachments": {
"a.txt": {
"description": null,
"filespec": "4 0 R",
"names": {
"/F": "a.txt",
"/UF": "a.txt"
},
"preferredcontents": "7 0 R",
"preferredname": "a.txt",
"streams": {
"/F": {
"checksum": null,
"creationdate": null,
"mimetype": null,
"modificationdate": null
},
"/UF": {
"checksum": null,
"creationdate": null,
"mimetype": null,
"modificationdate": null
}
}
},
"π.txt": {
"description": "Two filenames",
"filespec": "5 0 R",
"names": {
"/F": "pi.txt",
"/UF": "π.txt"
},
"preferredcontents": "9 0 R",
"preferredname": "π.txt",
"streams": {
"/F": {
"checksum": "e561f9248d7563d15dd93457b02ebbb6",
"creationdate": "2022-05-30T09:41:16-05:00",
"mimetype": "text/plain",
"modificationdate": "2022-05-30T09:41:16-05:00"
},
"/UF": {
"checksum": "e561f9248d7563d15dd93457b02ebbb6",
"creationdate": "2022-05-30T09:41:16-05:00",
"mimetype": "text/plain",
"modificationdate": "2022-05-30T09:41:16-05:00"
}
}
}
},
"encrypt": {
"capabilities": {
"accessibility": true,
"extract": true,
"moddifyannotations": true,
"modify": true,
"modifyassembly": true,
"modifyforms": true,
"modifyother": true,
"printhigh": true,
"printlow": true
},
"encrypted": false,
"ownerpasswordmatched": false,
"parameters": {
"P": 0,
"R": 0,
"V": 0,
"bits": 0,
"filemethod": "none",
"key": null,
"method": "none",
"streammethod": "none",
"stringmethod": "none"
},
"userpasswordmatched": false
},
"outlines": [],
"objects": {
"1 0 R": {
"/Names": {
"/EmbeddedFiles": "2 0 R"
},
"/PageMode": "/UseAttachments",
"/Pages": "3 0 R",
"/Type": "/Catalog"
},
"2 0 R": {
"/Names": [
"a.txt",
"4 0 R",
"π.txt",
"5 0 R"
]
},
"3 0 R": {
"/Count": 1,
"/Kids": [
"6 0 R"
],
"/Type": "/Pages"
},
"4 0 R": {
"/EF": {
"/F": "7 0 R",
"/UF": "7 0 R"
},
"/F": "a.txt",
"/Type": "/Filespec",
"/UF": "a.txt"
},
"5 0 R": {
"/Desc": "Two filenames",
"/EF": {
"/F": "9 0 R",
"/UF": "9 0 R"
},
"/F": "pi.txt",
"/Type": "/Filespec",
"/UF": "π.txt"
},
"6 0 R": {
"/Contents": "11 0 R",
"/MediaBox": [
0,
0,
612,
792
],
"/Parent": "3 0 R",
"/Resources": {
"/Font": {
"/F1": "13 0 R"
},
"/ProcSet": "14 0 R"
},
"/Type": "/Page"
},
"7 0 R": {
"/Length": "8 0 R",
"/Params": {
"/Size": 7
},
"/Type": "/EmbeddedFile"
},
"8 0 R": 7,
"9 0 R": {
"/Length": "10 0 R",
"/Params": {
"/CheckSum": "åaù$“ucÑ]Ù4W°.»¶",
"/CreationDate": "D:20220530094116-05'00'",
"/ModDate": "D:20220530094116-05'00'",
"/Size": 7
},
"/Subtype": "/text#2fplain",
"/Type": "/EmbeddedFile"
},
"10 0 R": 7,
"11 0 R": {
"/Length": "12 0 R"
},
"12 0 R": 44,
"13 0 R": {
"/BaseFont": "/Helvetica",
"/Encoding": "/WinAnsiEncoding",
"/Subtype": "/Type1",
"/Type": "/Font"
},
"14 0 R": [
"/PDF",
"/Text"
],
"trailer": {
"/ID": [
"=ˆàšk>˜x}\u0004üîÔ@",
"N\u0013Þ8#\u000b±\n\u0003䙧BÙ"
],
"/Root": "1 0 R",
"/Size": 15
}
},
"objectinfo": {
"1 0 R": {
"stream": {
"filter": null,
"is": false,
"length": null
}
},
"2 0 R": {
"stream": {
"filter": null,
"is": false,
"length": null
}
},
"3 0 R": {
"stream": {
"filter": null,
"is": false,
"length": null
}
},
"4 0 R": {
"stream": {
"filter": null,
"is": false,
"length": null
}
},
"5 0 R": {
"stream": {
"filter": null,
"is": false,
"length": null
}
},
"6 0 R": {
"stream": {
"filter": null,
"is": false,
"length": null
}
},
"7 0 R": {
"stream": {
"filter": null,
"is": true,
"length": 7
}
},
"8 0 R": {
"stream": {
"filter": null,
"is": false,
"length": null
}
},
"9 0 R": {
"stream": {
"filter": null,
"is": true,
"length": 7
}
},
"10 0 R": {
"stream": {
"filter": null,
"is": false,
"length": null
}
},
"11 0 R": {
"stream": {
"filter": null,
"is": true,
"length": 44
}
},
"12 0 R": {
"stream": {
"filter": null,
"is": false,
"length": null
}
},
"13 0 R": {
"stream": {
"filter": null,
"is": false,
"length": null
}
},
"14 0 R": {
"stream": {
"filter": null,
"is": false,
"length": null
}
}
}
}

View File

@ -0,0 +1,241 @@
{
"version": 2,
"parameters": {
"decodelevel": "generalized"
},
"pages": [
{
"contents": [
"11 0 R"
],
"images": [],
"label": null,
"object": "6 0 R",
"outlines": [],
"pageposfrom1": 1
}
],
"pagelabels": [],
"acroform": {
"fields": [],
"hasacroform": false,
"needappearances": false
},
"attachments": {
"a.txt": {
"description": null,
"filespec": "4 0 R",
"names": {
"/F": "a.txt",
"/UF": "a.txt"
},
"preferredcontents": "7 0 R",
"preferredname": "a.txt",
"streams": {
"/F": {
"checksum": null,
"creationdate": null,
"mimetype": null,
"modificationdate": null
},
"/UF": {
"checksum": null,
"creationdate": null,
"mimetype": null,
"modificationdate": null
}
}
},
"π.txt": {
"description": "Two filenames",
"filespec": "5 0 R",
"names": {
"/F": "pi.txt",
"/UF": "π.txt"
},
"preferredcontents": "9 0 R",
"preferredname": "π.txt",
"streams": {
"/F": {
"checksum": "e561f9248d7563d15dd93457b02ebbb6",
"creationdate": "2022-05-30T09:41:16-05:00",
"mimetype": "text/plain",
"modificationdate": "2022-05-30T09:41:16-05:00"
},
"/UF": {
"checksum": "e561f9248d7563d15dd93457b02ebbb6",
"creationdate": "2022-05-30T09:41:16-05:00",
"mimetype": "text/plain",
"modificationdate": "2022-05-30T09:41:16-05:00"
}
}
}
},
"encrypt": {
"capabilities": {
"accessibility": true,
"extract": true,
"modify": true,
"modifyannotations": true,
"modifyassembly": true,
"modifyforms": true,
"modifyother": true,
"printhigh": true,
"printlow": true
},
"encrypted": false,
"ownerpasswordmatched": false,
"parameters": {
"P": 0,
"R": 0,
"V": 0,
"bits": 0,
"filemethod": "none",
"key": null,
"method": "none",
"streammethod": "none",
"stringmethod": "none"
},
"userpasswordmatched": false
},
"outlines": [],
"objects": {
"obj:1 0 R": {
"value": {
"/Names": {
"/EmbeddedFiles": "2 0 R"
},
"/PageMode": "/UseAttachments",
"/Pages": "3 0 R",
"/Type": "/Catalog"
}
},
"obj:2 0 R": {
"value": {
"/Names": [
"u:a.txt",
"4 0 R",
"u:π.txt",
"5 0 R"
]
}
},
"obj:3 0 R": {
"value": {
"/Count": 1,
"/Kids": [
"6 0 R"
],
"/Type": "/Pages"
}
},
"obj:4 0 R": {
"value": {
"/EF": {
"/F": "7 0 R",
"/UF": "7 0 R"
},
"/F": "u:a.txt",
"/Type": "/Filespec",
"/UF": "u:a.txt"
}
},
"obj:5 0 R": {
"value": {
"/Desc": "u:Two filenames",
"/EF": {
"/F": "9 0 R",
"/UF": "9 0 R"
},
"/F": "u:pi.txt",
"/Type": "/Filespec",
"/UF": "u:π.txt"
}
},
"obj:6 0 R": {
"value": {
"/Contents": "11 0 R",
"/MediaBox": [
0,
0,
612,
792
],
"/Parent": "3 0 R",
"/Resources": {
"/Font": {
"/F1": "13 0 R"
},
"/ProcSet": "14 0 R"
},
"/Type": "/Page"
}
},
"obj:7 0 R": {
"stream": {
"dict": {
"/Length": "8 0 R",
"/Params": {
"/Size": 7
},
"/Type": "/EmbeddedFile"
}
}
},
"obj:8 0 R": {
"value": 7
},
"obj:9 0 R": {
"stream": {
"dict": {
"/Length": "10 0 R",
"/Params": {
"/CheckSum": "b:e561f9248d7563d15dd93457b02ebbb6",
"/CreationDate": "u:D:20220530094116-05'00'",
"/ModDate": "u:D:20220530094116-05'00'",
"/Size": 7
},
"/Subtype": "/text/plain",
"/Type": "/EmbeddedFile"
}
}
},
"obj:10 0 R": {
"value": 7
},
"obj:11 0 R": {
"stream": {
"dict": {
"/Length": "12 0 R"
}
}
},
"obj:12 0 R": {
"value": 44
},
"obj:13 0 R": {
"value": {
"/BaseFont": "/Helvetica",
"/Encoding": "/WinAnsiEncoding",
"/Subtype": "/Type1",
"/Type": "/Font"
}
},
"obj:14 0 R": {
"value": [
"/PDF",
"/Text"
]
},
"trailer": {
"value": {
"/ID": [
"b:3d1a89e08f9d6b3e1f787d04fceed440",
"b:4e13de38230bb10a03e49285a742c392"
],
"/Root": "1 0 R",
"/Size": 15
}
}
}
}

View File

@ -5,7 +5,15 @@ auto-1 -> 8,0
/UF -> auto-1
all data streams:
/F -> 8,0
creation date: D:20210210091359-05'00'
modification date: D:20210210141359Z
mime type: text/plain
checksum: a857d18d3fc23ad412122ef040733331
/UF -> 8,0
creation date: D:20210210091359-05'00'
modification date: D:20210210141359Z
mime type: text/plain
checksum: a857d18d3fc23ad412122ef040733331
auto-3 -> 10,0
description: two words
preferred name: auto-Three.txt
@ -14,7 +22,15 @@ auto-3 -> 10,0
/UF -> auto-Three.txt
all data streams:
/F -> 10,0
creation date: D:20210210091359-05'00'
modification date: D:20210210141359Z
mime type:
checksum: d6c7ac7cf295ae133fea186cfd068dab
/UF -> 10,0
creation date: D:20210210091359-05'00'
modification date: D:20210210141359Z
mime type:
checksum: d6c7ac7cf295ae133fea186cfd068dab
auto-Two -> 12,0
preferred name: auto-2
all names:
@ -22,4 +38,12 @@ auto-Two -> 12,0
/UF -> auto-2
all data streams:
/F -> 12,0
creation date: D:20210210091359-05'00'
modification date: D:20210210141359Z
mime type:
checksum: 9f991a5669c47a94f9350f53e3953e57
/UF -> 12,0
creation date: D:20210210091359-05'00'
modification date: D:20210210141359Z
mime type:
checksum: 9f991a5669c47a94f9350f53e3953e57

View File

@ -5,7 +5,15 @@
/UF -> auto-1
all data streams:
/F -> 11,0
creation date: D:20210210091359-05'00'
modification date: D:20210210141359Z
mime type: text/plain
checksum: a857d18d3fc23ad412122ef040733331
/UF -> 11,0
creation date: D:20210210091359-05'00'
modification date: D:20210210141359Z
mime type: text/plain
checksum: a857d18d3fc23ad412122ef040733331
1-auto-3 -> 13,0
description: two words
preferred name: auto-Three.txt
@ -14,7 +22,15 @@
/UF -> auto-Three.txt
all data streams:
/F -> 13,0
creation date: D:20210210091359-05'00'
modification date: D:20210210141359Z
mime type:
checksum: d6c7ac7cf295ae133fea186cfd068dab
/UF -> 13,0
creation date: D:20210210091359-05'00'
modification date: D:20210210141359Z
mime type:
checksum: d6c7ac7cf295ae133fea186cfd068dab
1-auto-Two -> 15,0
preferred name: auto-2
all names:
@ -22,7 +38,15 @@
/UF -> auto-2
all data streams:
/F -> 15,0
creation date: D:20210210091359-05'00'
modification date: D:20210210141359Z
mime type:
checksum: 9f991a5669c47a94f9350f53e3953e57
/UF -> 15,0
creation date: D:20210210091359-05'00'
modification date: D:20210210141359Z
mime type:
checksum: 9f991a5669c47a94f9350f53e3953e57
auto-1 -> 17,0
preferred name: auto-1
all names:
@ -30,7 +54,15 @@ auto-1 -> 17,0
/UF -> auto-1
all data streams:
/F -> 17,0
creation date: D:20210210091359-05'00'
modification date: D:20210210141359Z
mime type: text/plain
checksum: a857d18d3fc23ad412122ef040733331
/UF -> 17,0
creation date: D:20210210091359-05'00'
modification date: D:20210210141359Z
mime type: text/plain
checksum: a857d18d3fc23ad412122ef040733331
auto-3 -> 19,0
description: two words
preferred name: auto-Three.txt
@ -39,7 +71,15 @@ auto-3 -> 19,0
/UF -> auto-Three.txt
all data streams:
/F -> 19,0
creation date: D:20210210091359-05'00'
modification date: D:20210210141359Z
mime type:
checksum: d6c7ac7cf295ae133fea186cfd068dab
/UF -> 19,0
creation date: D:20210210091359-05'00'
modification date: D:20210210141359Z
mime type:
checksum: d6c7ac7cf295ae133fea186cfd068dab
auto-Two -> 21,0
preferred name: auto-2
all names:
@ -47,4 +87,12 @@ auto-Two -> 21,0
/UF -> auto-2
all data streams:
/F -> 21,0
creation date: D:20210210091359-05'00'
modification date: D:20210210141359Z
mime type:
checksum: 9f991a5669c47a94f9350f53e3953e57
/UF -> 21,0
creation date: D:20210210091359-05'00'
modification date: D:20210210141359Z
mime type:
checksum: 9f991a5669c47a94f9350f53e3953e57

View File

@ -5,7 +5,15 @@ auto-1 -> 8,0
/UF -> auto-2
all data streams:
/F -> 8,0
creation date: D:20210210091359-05'00'
modification date: D:20210210141359Z
mime type:
checksum: 9f991a5669c47a94f9350f53e3953e57
/UF -> 8,0
creation date: D:20210210091359-05'00'
modification date: D:20210210141359Z
mime type:
checksum: 9f991a5669c47a94f9350f53e3953e57
auto-3 -> 10,0
description: two words
preferred name: auto-Three.txt
@ -14,7 +22,15 @@ auto-3 -> 10,0
/UF -> auto-Three.txt
all data streams:
/F -> 10,0
creation date: D:20210210091359-05'00'
modification date: D:20210210141359Z
mime type:
checksum: d6c7ac7cf295ae133fea186cfd068dab
/UF -> 10,0
creation date: D:20210210091359-05'00'
modification date: D:20210210141359Z
mime type:
checksum: d6c7ac7cf295ae133fea186cfd068dab
auto-Two -> 12,0
preferred name: auto-2
all names:
@ -22,4 +38,12 @@ auto-Two -> 12,0
/UF -> auto-2
all data streams:
/F -> 12,0
creation date: D:20210210091359-05'00'
modification date: D:20210210141359Z
mime type:
checksum: 9f991a5669c47a94f9350f53e3953e57
/UF -> 12,0
creation date: D:20210210091359-05'00'
modification date: D:20210210141359Z
mime type:
checksum: 9f991a5669c47a94f9350f53e3953e57

View File

@ -5,4 +5,12 @@ auto-1 -> 6,0
/UF -> auto-1
all data streams:
/F -> 6,0
creation date: <date>
modification date: <date>
mime type:
checksum: a857d18d3fc23ad412122ef040733331
/UF -> 6,0
creation date: <date>
modification date: <date>
mime type:
checksum: a857d18d3fc23ad412122ef040733331

View File

@ -5,19 +5,76 @@
},
"attachments": {
"att1": {
"description": "some text",
"filespec": "4 0 R",
"names": {
"/F": "att1.txt",
"/UF": "att1.txt"
},
"preferredcontents": "8 0 R",
"preferredname": "att1.txt"
"preferredname": "att1.txt",
"streams": {
"/F": {
"checksum": "2e10f186a4cdf5be438747f4bdc2d4d4",
"creationdate": "2021-02-07T19:11:21-05:00",
"mimetype": "text/plain",
"modificationdate": "2021-02-07T19:11:21-05:00"
},
"/UF": {
"checksum": "2e10f186a4cdf5be438747f4bdc2d4d4",
"creationdate": "2021-02-07T19:11:21-05:00",
"mimetype": "text/plain",
"modificationdate": "2021-02-07T19:11:21-05:00"
}
}
},
"att2": {
"description": null,
"filespec": "5 0 R",
"names": {
"/F": "att2.txt",
"/UF": "att2.txt"
},
"preferredcontents": "10 0 R",
"preferredname": "att2.txt"
"preferredname": "att2.txt",
"streams": {
"/F": {
"checksum": "2fce9c8228e360ba9b04a1bd1bf63d6b",
"creationdate": null,
"mimetype": "text/plain",
"modificationdate": null
},
"/UF": {
"checksum": "2fce9c8228e360ba9b04a1bd1bf63d6b",
"creationdate": null,
"mimetype": "text/plain",
"modificationdate": null
}
}
},
"att3": {
"description": null,
"filespec": "6 0 R",
"names": {
"/F": "att3.txt",
"/UF": "π.txt"
},
"preferredcontents": "12 0 R",
"preferredname": "π.txt"
"preferredname": "π.txt",
"streams": {
"/F": {
"checksum": "2236c155b1d62b7f00285bba081d4336",
"creationdate": null,
"mimetype": "text/plain",
"modificationdate": null
},
"/UF": {
"checksum": "2236c155b1d62b7f00285bba081d4336",
"creationdate": null,
"mimetype": "text/plain",
"modificationdate": null
}
}
}
}
}

View File

@ -6,7 +6,15 @@ att1 -> 8,0
/UF -> att1.txt
all data streams:
/F -> 8,0
creation date: D:20210207191121-05'00'
modification date: D:20210208001122Z
mime type: text/plain
checksum: 2e10f186a4cdf5be438747f4bdc2d4d4
/UF -> 8,0
creation date: D:20210207191121-05'00'
modification date: D:20210208001122Z
mime type: text/plain
checksum: 2e10f186a4cdf5be438747f4bdc2d4d4
att2 -> 10,0
preferred name: att2.txt
all names:
@ -14,7 +22,15 @@ att2 -> 10,0
/UF -> att2.txt
all data streams:
/F -> 10,0
creation date:
modification date:
mime type: text/plain
checksum: 2fce9c8228e360ba9b04a1bd1bf63d6b
/UF -> 10,0
creation date:
modification date:
mime type: text/plain
checksum: 2fce9c8228e360ba9b04a1bd1bf63d6b
att3 -> 12,0
preferred name: π.txt
all names:
@ -22,4 +38,12 @@ att3 -> 12,0
/UF -> π.txt
all data streams:
/F -> 12,0
creation date:
modification date:
mime type: text/plain
checksum: 2236c155b1d62b7f00285bba081d4336
/UF -> 12,0
creation date:
modification date:
mime type: text/plain
checksum: 2236c155b1d62b7f00285bba081d4336

View File

@ -5,4 +5,12 @@ potato.png -> 6,0
/UF -> π.png
all data streams:
/F -> 6,0
creation date: D:20220215153939-05'00'
modification date: D:20220215153939-05'00'
mime type:
checksum: c55e70c0c72d7eaf01230124fe5ff2d9
/UF -> 6,0
creation date: D:20220215153939-05'00'
modification date: D:20220215153939-05'00'
mime type:
checksum: c55e70c0c72d7eaf01230124fe5ff2d9

View File

@ -218,7 +218,7 @@ if (defined $tc_log)
print_xml(">\n");
print_junit("<?xml version=\"1.0\"?>\n" .
"<testsuites>\n");
my @invalid_test_suites = ();
my @failed_test_suites = ();
foreach my $test (@tests)
{
print_and_log("\nRunning $test\n");
@ -228,7 +228,7 @@ foreach my $test (@tests)
if (scalar(@results) != 5)
{
print_and_log("test driver $test returned invalid results\n");
push(@invalid_test_suites, $test);
push(@failed_test_suites, $test);
}
else
{
@ -263,6 +263,10 @@ foreach my $test (@tests)
my $passed = (($extra == 0) && ($missing == 0) &&
($fails == 0) && ($xpasses == 0));
if (! $passed)
{
push(@failed_test_suites, $test);
}
print_xml(" <testsummary\n" .
" overall-outcome=\"" .($passed ? 'pass' : 'fail') . "\"\n".
@ -284,7 +288,7 @@ tc_do_final_checks();
my $okay = ((($totpasses + $totxfails) == $tottests) &&
($errors == 0) && ($totmissing == 0) && ($totextra == 0) &&
($coverage_okay) && (scalar(@invalid_test_suites) == 0));
($coverage_okay) && (scalar(@failed_test_suites) == 0));
print "\n";
print_and_pad("Overall test suite");
@ -301,10 +305,10 @@ else
}
my $summary = "\nTESTS COMPLETE. Summary:\n\n";
if (@invalid_test_suites)
if (@failed_test_suites)
{
$summary .= "INVALID TEST SUITES:\n";
foreach my $t (@invalid_test_suites)
$summary .= "FAILED TEST SUITES:\n";
foreach my $t (@failed_test_suites)
{
$summary .= " $t\n";
}