Add C API for checking PDF files

This commit is contained in:
Jay Berkenbilt 2018-02-17 11:51:10 -05:00
parent b72a38bf5f
commit 2780a1871d
10 changed files with 236 additions and 0 deletions

View File

@ -1,5 +1,9 @@
2018-02-17 Jay Berkenbilt <ejb@ql.org>
* Add qpdf_check_pdf to the "C" API. This method just attempts to
read the entire file and produce no output, making possible to
assess whether the file has any errors that qpdf can detect.
* Major enhancements to handling of type errors within the qpdf
library. This fix is intended to eliminate those annoying cases
where qpdf would exit with a message like "operation for

View File

@ -180,6 +180,14 @@ extern "C" {
QPDF_DLL
void qpdf_set_suppress_warnings(qpdf_data qpdf, QPDF_BOOL value);
/* CHECK FUNCTIONS */
/* Attempt to read the entire PDF file to see if there are any
* errors qpdf can detect.
*/
QPDF_DLL
QPDF_ERROR_CODE qpdf_check_pdf(qpdf_data qpdf);
/* READ FUNCTIONS */
/* READ PARAMETER FUNCTIONS -- must be called before qpdf_read */

View File

@ -4,6 +4,7 @@
#include <qpdf/QPDFWriter.hh>
#include <qpdf/QTC.hh>
#include <qpdf/QPDFExc.hh>
#include <qpdf/Pl_Discard.hh>
#include <list>
#include <string>
@ -82,6 +83,15 @@ static void call_write(qpdf_data qpdf)
qpdf->qpdf_writer->write();
}
static void call_check(qpdf_data qpdf)
{
QPDFWriter w(*qpdf->qpdf);
Pl_Discard discard;
w.setOutputPipeline(&discard);
w.setDecodeLevel(qpdf_dl_all);
w.write();
}
static QPDF_ERROR_CODE trap_errors(qpdf_data qpdf, void (*fn)(qpdf_data))
{
QPDF_ERROR_CODE status = QPDF_SUCCESS;
@ -236,6 +246,13 @@ char const* qpdf_get_error_message_detail(qpdf_data qpdf, qpdf_error e)
return e->exc->getMessageDetail().c_str();
}
QPDF_ERROR_CODE qpdf_check_pdf(qpdf_data qpdf)
{
QPDF_ERROR_CODE status = trap_errors(qpdf, &call_check);
QTC::TC("qpdf", "qpdf-c called qpdf_check_pdf");
return status;
}
void qpdf_set_suppress_warnings(qpdf_data qpdf, QPDF_BOOL value)
{
QTC::TC("qpdf", "qpdf-c called qpdf_set_suppress_warnings");

View File

@ -484,6 +484,18 @@ static void test22(char const* infile,
report_errors();
}
static void test23(char const* infile,
char const* password,
char const* outfile,
char const* outfile2)
{
QPDF_ERROR_CODE status = 0;
qpdf_read(qpdf, infile, password);
status = qpdf_check_pdf(qpdf);
printf("status: %d\n", status);
report_errors();
}
int main(int argc, char* argv[])
{
char* p = 0;
@ -546,6 +558,7 @@ int main(int argc, char* argv[])
(n == 20) ? test20 :
(n == 21) ? test21 :
(n == 22) ? test22 :
(n == 23) ? test23 :
0);
if (fn == 0)

View File

@ -333,3 +333,4 @@ QPDFObjectHandle dictionary ignoring removeKey 0
QPDFObjectHandle dictionary ignoring removereplace 0
QPDFObjectHandle numeric non-numeric 0
QPDFObjectHandle erase array bounds 0
qpdf-c called qpdf_check_pdf 0

View File

@ -2493,6 +2493,21 @@ foreach my $d (@enc_key)
$td->NORMALIZE_NEWLINES);
}
show_ntests();
# ----------
$td->notify("--- Check from C API ---");
my @c_check_types = qw(warn clear);
$n_tests += scalar(@c_check_types);
foreach my $i (@c_check_types)
{
$td->runtest("C check $i",
{$td->COMMAND => "qpdf-ctest 23 c-check-$i-in.pdf '' -"},
{$td->FILE => "c-check-$i.out",
$td->EXIT_STATUS => 0},
$td->NORMALIZE_NEWLINES);
}
show_ntests();
# ----------
$td->notify("--- Content Preservation Tests ---");

View File

@ -0,0 +1,79 @@
%PDF-1.3
1 0 obj
<<
/Type /Catalog
/Pages 2 0 R
>>
endobj
2 0 obj
<<
/Type /Pages
/Kids [
3 0 R
]
/Count 1
>>
endobj
3 0 obj
<<
/Type /Page
/Parent 2 0 R
/MediaBox [0 0 612 792]
/Contents 4 0 R
/Resources <<
/ProcSet 5 0 R
/Font <<
/F1 6 0 R
>>
>>
>>
endobj
4 0 obj
<<
/Length 44
>>
stream
BT
/F1 24 Tf
72 720 Td
(Potato) Tj
ET
endstream
endobj
5 0 obj
[
/PDF
/Text
]
endobj
6 0 obj
<<
/Type /Font
/Subtype /Type1
/Name /F1
/BaseFont /Helvetica
/Encoding /WinAnsiEncoding
>>
endobj
xref
0 7
0000000000 65535 f
0000000009 00000 n
0000000063 00000 n
0000000135 00000 n
0000000307 00000 n
0000000403 00000 n
0000000438 00000 n
trailer <<
/Size 7
/Root 1 0 R
>>
startxref
556
%%EOF

View File

@ -0,0 +1 @@
status: 0

View File

@ -0,0 +1,79 @@
%PDF-1.3
1 0 obj
<<
/Type /Catalog
/Pages 2 0 R
>>
endobj
2 0 obj
<<
/Type /Pages
/Kids [
3 0 R
]
/Count 1
>>
endobj
3 0 obj
<<
/Type /Page
/Parent 2 0 R
/MediaBox [0 0 612 792]
/Contents 4 0 R
/Resources <<
/ProcSet 5 0 R
/Font <<
/F1 6 0 R
>>
>>
>>
endobj
4 0 obj
<<
/Length 44
>>
stream
BT
/F1 24 Tf
72 720 Td
(Potato) Tj
ET
endstream
endobj
5 0 obj
[
/PDF
/Text
]
endobj
6 0 obj
<<
/Type /Font
/Subtype /Type1
/Name /F1
/BaseFont /Helvetica
/Encoding /WinAnsiEncoding
>>
endobj
xref
0 7
0000000000 65535 f
0000000009 00000 n
0000000063 00000 n
0000000135 00000 n
0000000307 00000 n
0000000403 00000 n
0000000438 00000 n
trailer <<
/Size 7
/Root 1 0 R
>>
startxref
1556
%%EOF

View File

@ -0,0 +1,19 @@
WARNING: c-check-warn-in.pdf: file is damaged
WARNING: c-check-warn-in.pdf (offset 1556): xref not found
WARNING: c-check-warn-in.pdf: Attempting to reconstruct cross-reference table
status: 1
warning: c-check-warn-in.pdf: file is damaged
code: 5
file: c-check-warn-in.pdf
pos : 0
text: file is damaged
warning: c-check-warn-in.pdf (offset 1556): xref not found
code: 5
file: c-check-warn-in.pdf
pos : 1556
text: xref not found
warning: c-check-warn-in.pdf: Attempting to reconstruct cross-reference table
code: 5
file: c-check-warn-in.pdf
pos : 0
text: Attempting to reconstruct cross-reference table