mirror of
https://github.com/qpdf/qpdf.git
synced 2024-09-23 10:39:16 +00:00
4ee393d1fa
By combining --linearize with --compress-streams=n, we ensure that no new compressed data will appear in linearized output, which makes the output independent of zlib's output. There are other tests to ensure that linearization works correctly with compression. This commit involves changing some test outputs and test code as well just updating test suites.
1420 lines
50 KiB
C
1420 lines
50 KiB
C
#include <qpdf/assert_test.h>
|
|
|
|
#include <qpdf/qpdf-c.h>
|
|
#include <errno.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
static char* whoami = 0;
|
|
static qpdf_data qpdf = 0;
|
|
|
|
static FILE*
|
|
safe_fopen(char const* filename, char const* mode)
|
|
{
|
|
// This function is basically a "C" port of QUtil::safe_fopen.
|
|
FILE* f = 0;
|
|
#ifdef _MSC_VER
|
|
errno_t err = fopen_s(&f, filename, mode);
|
|
if (err != 0) {
|
|
char buf[94];
|
|
strerror_s(buf, sizeof(buf), errno);
|
|
fprintf(stderr, "%s: unable to open %s: %s\n", whoami, filename, buf);
|
|
exit(2);
|
|
}
|
|
#else
|
|
f = fopen(filename, mode);
|
|
if (f == NULL) {
|
|
fprintf(stderr, "%s: unable to open %s: %s\n", whoami, filename, strerror(errno));
|
|
exit(2);
|
|
}
|
|
#endif
|
|
return f;
|
|
}
|
|
|
|
static void
|
|
print_error(char const* label, qpdf_data q, qpdf_error e)
|
|
{
|
|
printf("%s: %s\n", label, qpdf_get_error_full_text(q, e));
|
|
printf(" code: %d\n", qpdf_get_error_code(q, e));
|
|
printf(" file: %s\n", qpdf_get_error_filename(q, e));
|
|
printf(" pos: %lld\n", qpdf_get_error_file_position(q, e));
|
|
printf(" text: %s\n", qpdf_get_error_message_detail(q, e));
|
|
}
|
|
|
|
static void
|
|
report_errors()
|
|
{
|
|
qpdf_error e = 0;
|
|
while (qpdf_more_warnings(qpdf)) {
|
|
e = qpdf_next_warning(qpdf);
|
|
print_error("warning", qpdf, e);
|
|
}
|
|
if (qpdf_has_error(qpdf)) {
|
|
e = qpdf_get_error(qpdf);
|
|
assert(qpdf_has_error(qpdf) == QPDF_FALSE);
|
|
print_error("error", qpdf, e);
|
|
} else {
|
|
e = qpdf_get_error(qpdf);
|
|
assert(e == 0);
|
|
assert(qpdf_get_error_code(qpdf, e) == qpdf_e_success);
|
|
// Call these to ensure that they can be called on a null
|
|
// error pointer.
|
|
(void)qpdf_get_error_full_text(qpdf, e);
|
|
(void)qpdf_get_error_filename(qpdf, e);
|
|
(void)qpdf_get_error_file_position(qpdf, e);
|
|
(void)qpdf_get_error_message_detail(qpdf, e);
|
|
}
|
|
}
|
|
|
|
static void
|
|
handle_oh_error(qpdf_data q, char const* label)
|
|
{
|
|
if (qpdf_has_error(q)) {
|
|
print_error(label, q, qpdf_get_error(q));
|
|
}
|
|
}
|
|
|
|
static void
|
|
read_file_into_memory(char const* filename, char** buf, unsigned long* size)
|
|
{
|
|
char* buf_p = 0;
|
|
FILE* f = NULL;
|
|
size_t bytes_read = 0;
|
|
size_t len = 0;
|
|
|
|
f = safe_fopen(filename, "rb");
|
|
fseek(f, 0, SEEK_END);
|
|
*size = (unsigned long)ftell(f);
|
|
fseek(f, 0, SEEK_SET);
|
|
*buf = malloc(*size);
|
|
if (*buf == NULL) {
|
|
fprintf(stderr, "%s: unable to allocate %lu bytes\n", whoami, *size);
|
|
exit(2);
|
|
}
|
|
buf_p = *buf;
|
|
bytes_read = 0;
|
|
len = 0;
|
|
while ((len = fread(buf_p + bytes_read, 1, *size - bytes_read, f)) > 0) {
|
|
bytes_read += len;
|
|
}
|
|
if (bytes_read != *size) {
|
|
if (ferror(f)) {
|
|
fprintf(stderr, "%s: failure reading file %s into memory:", whoami, filename);
|
|
} else {
|
|
fprintf(stderr, "%s: premature EOF reading file %s:", whoami, filename);
|
|
}
|
|
fprintf(stderr, " read %lu, wanted %lu\n", (unsigned long)bytes_read, (unsigned long)*size);
|
|
exit(2);
|
|
}
|
|
fclose(f);
|
|
}
|
|
|
|
static void
|
|
count_progress(int percent, void* data)
|
|
{
|
|
++(*(int*)data);
|
|
}
|
|
|
|
static int
|
|
write_to_file(char const* data, size_t size, void* udata)
|
|
{
|
|
FILE* f = (FILE*)udata;
|
|
return fwrite(data, 1, size, f) != size;
|
|
}
|
|
|
|
static int
|
|
custom_log(char const* data, size_t size, void* udata)
|
|
{
|
|
fprintf(stderr, "|custom|");
|
|
fwrite(data, 1, size, stderr);
|
|
fflush(stderr);
|
|
return 0;
|
|
}
|
|
|
|
static void
|
|
test01(char const* infile, char const* password, char const* outfile, char const* xarg)
|
|
{
|
|
qpdf_read(qpdf, infile, password);
|
|
printf("version: %s\n", qpdf_get_pdf_version(qpdf));
|
|
if (qpdf_get_pdf_extension_level(qpdf) > 0) {
|
|
printf("extension level: %d\n", qpdf_get_pdf_extension_level(qpdf));
|
|
}
|
|
printf("linearized: %d\n", qpdf_is_linearized(qpdf));
|
|
printf("encrypted: %d\n", qpdf_is_encrypted(qpdf));
|
|
if (qpdf_is_encrypted(qpdf)) {
|
|
printf("user password: %s\n", qpdf_get_user_password(qpdf));
|
|
printf("extract for accessibility: %d\n", qpdf_allow_accessibility(qpdf));
|
|
printf("extract for any purpose: %d\n", qpdf_allow_extract_all(qpdf));
|
|
printf("print low resolution: %d\n", qpdf_allow_print_low_res(qpdf));
|
|
printf("print high resolution: %d\n", qpdf_allow_print_high_res(qpdf));
|
|
printf("modify document assembly: %d\n", qpdf_allow_modify_assembly(qpdf));
|
|
printf("modify forms: %d\n", qpdf_allow_modify_form(qpdf));
|
|
printf("modify annotations: %d\n", qpdf_allow_modify_annotation(qpdf));
|
|
printf("modify other: %d\n", qpdf_allow_modify_other(qpdf));
|
|
printf("modify anything: %d\n", qpdf_allow_modify_all(qpdf));
|
|
}
|
|
report_errors();
|
|
}
|
|
|
|
static void
|
|
test02(char const* infile, char const* password, char const* outfile, char const* xarg)
|
|
{
|
|
qpdf_set_suppress_warnings(qpdf, QPDF_TRUE);
|
|
if (((qpdf_read(qpdf, infile, password) & QPDF_ERRORS) == 0) &&
|
|
((qpdf_init_write(qpdf, outfile) & QPDF_ERRORS) == 0)) {
|
|
qpdf_set_static_ID(qpdf, QPDF_TRUE);
|
|
qpdf_write(qpdf);
|
|
}
|
|
report_errors();
|
|
}
|
|
|
|
static void
|
|
test03(char const* infile, char const* password, char const* outfile, char const* xarg)
|
|
{
|
|
qpdf_read(qpdf, infile, password);
|
|
qpdf_init_write(qpdf, outfile);
|
|
qpdf_set_static_ID(qpdf, QPDF_TRUE);
|
|
qpdf_set_content_normalization(qpdf, QPDF_TRUE);
|
|
qpdf_write(qpdf);
|
|
report_errors();
|
|
}
|
|
|
|
static void
|
|
test04(char const* infile, char const* password, char const* outfile, char const* xarg)
|
|
{
|
|
qpdf_set_ignore_xref_streams(qpdf, QPDF_TRUE);
|
|
qpdf_read(qpdf, infile, password);
|
|
qpdf_init_write(qpdf, outfile);
|
|
qpdf_set_static_ID(qpdf, QPDF_TRUE);
|
|
qpdf_write(qpdf);
|
|
report_errors();
|
|
}
|
|
|
|
static void
|
|
test05(char const* infile, char const* password, char const* outfile, char const* xarg)
|
|
{
|
|
int count = 0;
|
|
qpdf_read(qpdf, infile, password);
|
|
qpdf_init_write(qpdf, outfile);
|
|
qpdf_register_progress_reporter(qpdf, count_progress, (void*)&count);
|
|
qpdf_set_static_ID(qpdf, QPDF_TRUE);
|
|
qpdf_set_linearization(qpdf, QPDF_TRUE);
|
|
qpdf_set_compress_streams(qpdf, QPDF_FALSE); // Don't depend on zlib
|
|
qpdf_write(qpdf);
|
|
/* make sure progress reporter was called */
|
|
assert(count > 0);
|
|
report_errors();
|
|
}
|
|
|
|
static void
|
|
test06(char const* infile, char const* password, char const* outfile, char const* xarg)
|
|
{
|
|
char* buf = NULL;
|
|
unsigned long size = 0;
|
|
read_file_into_memory(infile, &buf, &size);
|
|
qpdf_read_memory(qpdf, infile, buf, size, password);
|
|
qpdf_init_write(qpdf, outfile);
|
|
qpdf_set_static_ID(qpdf, QPDF_TRUE);
|
|
qpdf_set_object_stream_mode(qpdf, qpdf_o_generate);
|
|
qpdf_write(qpdf);
|
|
report_errors();
|
|
free(buf);
|
|
}
|
|
|
|
static void
|
|
test07(char const* infile, char const* password, char const* outfile, char const* xarg)
|
|
{
|
|
qpdf_read(qpdf, infile, password);
|
|
qpdf_init_write(qpdf, outfile);
|
|
qpdf_set_static_ID(qpdf, QPDF_TRUE);
|
|
qpdf_set_qdf_mode(qpdf, QPDF_TRUE);
|
|
qpdf_write(qpdf);
|
|
report_errors();
|
|
}
|
|
|
|
static void
|
|
test08(char const* infile, char const* password, char const* outfile, char const* xarg)
|
|
{
|
|
qpdf_read(qpdf, infile, password);
|
|
qpdf_init_write(qpdf, outfile);
|
|
qpdf_set_static_ID(qpdf, QPDF_TRUE);
|
|
qpdf_set_qdf_mode(qpdf, QPDF_TRUE);
|
|
qpdf_set_suppress_original_object_IDs(qpdf, QPDF_TRUE);
|
|
qpdf_write(qpdf);
|
|
report_errors();
|
|
}
|
|
|
|
static void
|
|
test09(char const* infile, char const* password, char const* outfile, char const* xarg)
|
|
{
|
|
qpdf_read(qpdf, infile, password);
|
|
qpdf_init_write(qpdf, outfile);
|
|
qpdf_set_static_ID(qpdf, QPDF_TRUE);
|
|
qpdf_set_stream_data_mode(qpdf, qpdf_s_uncompress);
|
|
qpdf_write(qpdf);
|
|
report_errors();
|
|
}
|
|
|
|
static void
|
|
test10(char const* infile, char const* password, char const* outfile, char const* xarg)
|
|
{
|
|
qpdf_set_attempt_recovery(qpdf, QPDF_FALSE);
|
|
qpdf_read(qpdf, infile, password);
|
|
report_errors();
|
|
}
|
|
|
|
static void
|
|
test11(char const* infile, char const* password, char const* outfile, char const* xarg)
|
|
{
|
|
qpdf_read(qpdf, infile, password);
|
|
qpdf_init_write(qpdf, outfile);
|
|
qpdf_set_static_ID(qpdf, QPDF_TRUE);
|
|
qpdf_set_r2_encryption_parameters_insecure(
|
|
qpdf, "user1", "owner1", QPDF_FALSE, QPDF_TRUE, QPDF_TRUE, QPDF_TRUE);
|
|
qpdf_write(qpdf);
|
|
report_errors();
|
|
}
|
|
|
|
static void
|
|
test12(char const* infile, char const* password, char const* outfile, char const* xarg)
|
|
{
|
|
qpdf_read(qpdf, infile, password);
|
|
qpdf_init_write(qpdf, outfile);
|
|
qpdf_set_static_ID(qpdf, QPDF_TRUE);
|
|
qpdf_set_r3_encryption_parameters_insecure(
|
|
qpdf,
|
|
"user2",
|
|
"owner2",
|
|
QPDF_TRUE,
|
|
QPDF_TRUE,
|
|
QPDF_TRUE,
|
|
QPDF_TRUE,
|
|
QPDF_TRUE,
|
|
QPDF_TRUE,
|
|
qpdf_r3p_low);
|
|
qpdf_write(qpdf);
|
|
report_errors();
|
|
}
|
|
|
|
static void
|
|
test13(char const* infile, char const* password, char const* outfile, char const* xarg)
|
|
{
|
|
qpdf_read(qpdf, infile, password);
|
|
printf("user password: %s\n", qpdf_get_user_password(qpdf));
|
|
qpdf_init_write(qpdf, outfile);
|
|
qpdf_set_static_ID(qpdf, QPDF_TRUE);
|
|
qpdf_set_preserve_encryption(qpdf, QPDF_FALSE);
|
|
qpdf_write(qpdf);
|
|
report_errors();
|
|
}
|
|
|
|
static void
|
|
test14(char const* infile, char const* password, char const* outfile, char const* xarg)
|
|
{
|
|
qpdf_read(qpdf, infile, password);
|
|
qpdf_init_write(qpdf, outfile);
|
|
qpdf_set_static_ID(qpdf, QPDF_TRUE);
|
|
qpdf_set_minimum_pdf_version_and_extension(qpdf, "1.7", 8);
|
|
qpdf_write(qpdf);
|
|
qpdf_init_write(qpdf, xarg);
|
|
qpdf_set_static_ID(qpdf, QPDF_TRUE);
|
|
qpdf_force_pdf_version(qpdf, "1.4");
|
|
qpdf_write(qpdf);
|
|
report_errors();
|
|
}
|
|
|
|
static void
|
|
test15(char const* infile, char const* password, char const* outfile, char const* xarg)
|
|
{
|
|
qpdf_read(qpdf, infile, password);
|
|
qpdf_init_write(qpdf, outfile);
|
|
qpdf_set_static_ID(qpdf, QPDF_TRUE);
|
|
qpdf_set_static_aes_IV(qpdf, QPDF_TRUE);
|
|
qpdf_set_r4_encryption_parameters_insecure(
|
|
qpdf,
|
|
"user2",
|
|
"owner2",
|
|
QPDF_TRUE,
|
|
QPDF_TRUE,
|
|
QPDF_TRUE,
|
|
QPDF_TRUE,
|
|
QPDF_TRUE,
|
|
QPDF_TRUE,
|
|
qpdf_r3p_low,
|
|
QPDF_TRUE,
|
|
QPDF_TRUE);
|
|
qpdf_write(qpdf);
|
|
report_errors();
|
|
}
|
|
|
|
static void
|
|
print_info(char const* key)
|
|
{
|
|
char const* value = qpdf_get_info_key(qpdf, key);
|
|
printf("Info key %s: %s\n", key, (value ? value : "(null)"));
|
|
}
|
|
|
|
static void
|
|
test16(char const* infile, char const* password, char const* outfile, char const* xarg)
|
|
{
|
|
unsigned long buflen = 0L;
|
|
unsigned char const* buf = 0;
|
|
FILE* f = 0;
|
|
|
|
qpdf_read(qpdf, infile, password);
|
|
print_info("/Author");
|
|
print_info("/Producer");
|
|
print_info("/Creator");
|
|
qpdf_set_info_key(qpdf, "/Author", "Mr. Potato Head");
|
|
qpdf_set_info_key(qpdf, "/Producer", "QPDF library");
|
|
qpdf_set_info_key(qpdf, "/Creator", 0);
|
|
print_info("/Author");
|
|
print_info("/Producer");
|
|
print_info("/Creator");
|
|
qpdf_init_write_memory(qpdf);
|
|
qpdf_set_static_ID(qpdf, QPDF_TRUE);
|
|
qpdf_set_static_aes_IV(qpdf, QPDF_TRUE);
|
|
qpdf_set_stream_data_mode(qpdf, qpdf_s_uncompress);
|
|
qpdf_write(qpdf);
|
|
f = safe_fopen(outfile, "wb");
|
|
buflen = (unsigned long)(qpdf_get_buffer_length(qpdf));
|
|
buf = qpdf_get_buffer(qpdf);
|
|
fwrite(buf, 1, buflen, f);
|
|
fclose(f);
|
|
report_errors();
|
|
}
|
|
|
|
static void
|
|
test17(char const* infile, char const* password, char const* outfile, char const* xarg)
|
|
{
|
|
qpdf_read(qpdf, infile, password);
|
|
qpdf_init_write(qpdf, outfile);
|
|
qpdf_set_static_ID(qpdf, QPDF_TRUE);
|
|
qpdf_set_static_aes_IV(qpdf, QPDF_TRUE);
|
|
qpdf_set_r5_encryption_parameters2(
|
|
qpdf,
|
|
"user3",
|
|
"owner3",
|
|
QPDF_TRUE,
|
|
QPDF_TRUE,
|
|
QPDF_TRUE,
|
|
QPDF_TRUE,
|
|
QPDF_TRUE,
|
|
QPDF_TRUE,
|
|
qpdf_r3p_low,
|
|
QPDF_TRUE);
|
|
qpdf_write(qpdf);
|
|
report_errors();
|
|
}
|
|
|
|
static void
|
|
test18(char const* infile, char const* password, char const* outfile, char const* xarg)
|
|
{
|
|
qpdf_read(qpdf, infile, password);
|
|
qpdf_init_write(qpdf, outfile);
|
|
qpdf_set_static_ID(qpdf, QPDF_TRUE);
|
|
qpdf_set_static_aes_IV(qpdf, QPDF_TRUE);
|
|
qpdf_set_r6_encryption_parameters2(
|
|
qpdf,
|
|
"user4",
|
|
"owner4",
|
|
QPDF_TRUE,
|
|
QPDF_TRUE,
|
|
QPDF_TRUE,
|
|
QPDF_TRUE,
|
|
QPDF_TRUE,
|
|
QPDF_TRUE,
|
|
qpdf_r3p_low,
|
|
QPDF_TRUE);
|
|
qpdf_write(qpdf);
|
|
report_errors();
|
|
}
|
|
|
|
static void
|
|
test19(char const* infile, char const* password, char const* outfile, char const* xarg)
|
|
{
|
|
qpdf_read(qpdf, infile, password);
|
|
qpdf_init_write(qpdf, outfile);
|
|
qpdf_set_deterministic_ID(qpdf, QPDF_TRUE);
|
|
qpdf_write(qpdf);
|
|
report_errors();
|
|
}
|
|
|
|
static void
|
|
test20(char const* infile, char const* password, char const* outfile, char const* xarg)
|
|
{
|
|
qpdf_read(qpdf, infile, password);
|
|
qpdf_init_write(qpdf, outfile);
|
|
qpdf_set_static_ID(qpdf, QPDF_TRUE);
|
|
qpdf_set_static_aes_IV(qpdf, QPDF_TRUE);
|
|
qpdf_set_compress_streams(qpdf, QPDF_FALSE);
|
|
qpdf_set_decode_level(qpdf, qpdf_dl_specialized);
|
|
qpdf_write(qpdf);
|
|
report_errors();
|
|
}
|
|
|
|
static void
|
|
test21(char const* infile, char const* password, char const* outfile, char const* xarg)
|
|
{
|
|
qpdf_read(qpdf, infile, password);
|
|
qpdf_init_write(qpdf, outfile);
|
|
qpdf_set_static_ID(qpdf, QPDF_TRUE);
|
|
qpdf_set_static_aes_IV(qpdf, QPDF_TRUE);
|
|
qpdf_set_preserve_unreferenced_objects(qpdf, QPDF_TRUE);
|
|
qpdf_write(qpdf);
|
|
report_errors();
|
|
}
|
|
|
|
static void
|
|
test22(char const* infile, char const* password, char const* outfile, char const* xarg)
|
|
{
|
|
qpdf_read(qpdf, infile, password);
|
|
qpdf_init_write(qpdf, outfile);
|
|
qpdf_set_static_ID(qpdf, QPDF_TRUE);
|
|
qpdf_set_static_aes_IV(qpdf, QPDF_TRUE);
|
|
qpdf_set_compress_streams(qpdf, QPDF_FALSE);
|
|
qpdf_set_newline_before_endstream(qpdf, QPDF_TRUE);
|
|
qpdf_write(qpdf);
|
|
report_errors();
|
|
}
|
|
|
|
static void
|
|
test23(char const* infile, char const* password, char const* outfile, char const* xarg)
|
|
{
|
|
/* Test check and also exercise custom logger */
|
|
qpdflogger_handle l1 = qpdf_get_logger(qpdf);
|
|
qpdflogger_handle l2 = qpdflogger_default_logger();
|
|
assert(qpdflogger_equal(l1, l2));
|
|
qpdflogger_cleanup(&l1);
|
|
qpdflogger_cleanup(&l2);
|
|
qpdflogger_handle l = qpdflogger_create();
|
|
qpdflogger_set_warn(l, qpdf_log_dest_custom, custom_log, NULL);
|
|
qpdf_set_logger(qpdf, l);
|
|
qpdflogger_handle l3 = qpdf_get_logger(qpdf);
|
|
assert(qpdflogger_equal(l, l3));
|
|
qpdflogger_cleanup(&l);
|
|
qpdflogger_cleanup(&l3);
|
|
|
|
QPDF_ERROR_CODE status = 0;
|
|
qpdf_read(qpdf, infile, password);
|
|
status = qpdf_check_pdf(qpdf);
|
|
printf("status: %d\n", status);
|
|
report_errors();
|
|
}
|
|
|
|
static void
|
|
test24(char const* infile, char const* password, char const* outfile, char const* xarg)
|
|
{
|
|
/* This test case is designed for minimal.pdf. Pull objects out of
|
|
* minimal.pdf to make sure all our accessors work as expected.
|
|
*/
|
|
|
|
qpdf_read(qpdf, infile, password);
|
|
qpdf_oh trailer = qpdf_get_trailer(qpdf);
|
|
/* The library never returns 0 */
|
|
assert(trailer == 1);
|
|
|
|
/* Get root two different ways */
|
|
qpdf_oh root = qpdf_get_root(qpdf);
|
|
assert(qpdf_oh_get_generation(qpdf, root) == 0);
|
|
qpdf_oh root_from_trailer = qpdf_oh_get_key(qpdf, trailer, "/Root");
|
|
assert(qpdf_oh_get_object_id(qpdf, root) == qpdf_oh_get_object_id(qpdf, root_from_trailer));
|
|
|
|
/* Go to the first page and look at all the keys */
|
|
qpdf_oh pages = qpdf_oh_get_key(qpdf, root, "/Pages");
|
|
assert(qpdf_oh_is_dictionary(qpdf, pages));
|
|
assert(qpdf_oh_get_type_code(qpdf, pages) == ot_dictionary);
|
|
assert(strcmp(qpdf_oh_get_type_name(qpdf, pages), "dictionary") == 0);
|
|
assert(qpdf_oh_is_initialized(qpdf, pages));
|
|
qpdf_oh kids = qpdf_oh_get_key(qpdf, pages, "/Kids");
|
|
assert(qpdf_oh_is_array(qpdf, kids));
|
|
assert(qpdf_oh_get_type_code(qpdf, kids) == ot_array);
|
|
assert(strcmp(qpdf_oh_get_type_name(qpdf, kids), "array") == 0);
|
|
assert(qpdf_oh_get_array_n_items(qpdf, kids) == 1);
|
|
qpdf_oh page1 = qpdf_oh_get_array_item(qpdf, kids, 0);
|
|
qpdf_oh_begin_dict_key_iter(qpdf, page1);
|
|
while (qpdf_oh_dict_more_keys(qpdf)) {
|
|
printf("page dictionary key: %s\n", qpdf_oh_dict_next_key(qpdf));
|
|
}
|
|
|
|
/* Inspect the first page */
|
|
qpdf_oh type = qpdf_oh_get_key(qpdf, page1, "/Type");
|
|
assert(qpdf_oh_is_name(qpdf, type));
|
|
assert(qpdf_oh_get_type_code(qpdf, type) == ot_name);
|
|
assert(strcmp(qpdf_oh_get_type_name(qpdf, type), "name") == 0);
|
|
assert(strcmp(qpdf_oh_get_name(qpdf, type), "/Page") == 0);
|
|
qpdf_oh parent = qpdf_oh_get_key(qpdf, page1, "/Parent");
|
|
assert(qpdf_oh_is_indirect(qpdf, parent));
|
|
qpdf_oh mediabox = qpdf_oh_get_key(qpdf, page1, "/MediaBox");
|
|
assert(!qpdf_oh_is_scalar(qpdf, mediabox));
|
|
assert(qpdf_oh_is_array(qpdf, mediabox));
|
|
assert(qpdf_oh_get_array_n_items(qpdf, mediabox) == 4);
|
|
for (int i = 0; i < 4; ++i) {
|
|
qpdf_oh item = qpdf_oh_get_array_item(qpdf, mediabox, i);
|
|
printf(
|
|
"item %d: %d %.2f\n",
|
|
i,
|
|
qpdf_oh_get_int_value_as_int(qpdf, item),
|
|
qpdf_oh_get_numeric_value(qpdf, item));
|
|
}
|
|
|
|
/* Exercise different ways of looking at integers */
|
|
qpdf_oh i2 = qpdf_oh_get_array_item(qpdf, mediabox, 2);
|
|
assert(qpdf_oh_get_int_value_as_int(qpdf, i2) == 612);
|
|
assert(qpdf_oh_get_int_value(qpdf, i2) == 612ll);
|
|
assert(qpdf_oh_get_uint_value_as_uint(qpdf, i2) == 612u);
|
|
assert(qpdf_oh_get_uint_value(qpdf, i2) == 612ull);
|
|
/* Exercise accessors of other object types */
|
|
assert(!qpdf_oh_is_operator(qpdf, i2));
|
|
assert(!qpdf_oh_is_inline_image(qpdf, i2));
|
|
/* Chain calls. */
|
|
qpdf_oh encoding = qpdf_oh_get_key(
|
|
qpdf,
|
|
qpdf_oh_get_key(
|
|
qpdf,
|
|
qpdf_oh_get_key(qpdf, qpdf_oh_get_key(qpdf, page1, "/Resources"), "/Font"),
|
|
"/F1"),
|
|
"/Encoding");
|
|
assert(strcmp(qpdf_oh_get_name(qpdf, encoding), "/WinAnsiEncoding") == 0);
|
|
|
|
qpdf_oh res = qpdf_oh_get_key_if_dict(qpdf, page1, "/Resources");
|
|
assert(qpdf_oh_has_key(qpdf, res, "/Font"));
|
|
/* check no warning when called with null */
|
|
while (qpdf_more_warnings(qpdf)) {
|
|
qpdf_next_warning(qpdf);
|
|
}
|
|
res = qpdf_oh_get_key_if_dict(qpdf, qpdf_oh_get_key_if_dict(qpdf, page1, "/Missing"), "/Font");
|
|
assert(!qpdf_more_warnings(qpdf));
|
|
|
|
/* Look at page contents to exercise stream functions */
|
|
qpdf_oh contents = qpdf_oh_get_key(qpdf, page1, "/Contents");
|
|
assert(qpdf_oh_is_stream(qpdf, contents));
|
|
assert(qpdf_oh_get_type_code(qpdf, contents) == ot_stream);
|
|
assert(strcmp(qpdf_oh_get_type_name(qpdf, contents), "stream") == 0);
|
|
qpdf_oh contents_dict = qpdf_oh_get_dict(qpdf, contents);
|
|
assert(!qpdf_oh_is_scalar(qpdf, contents));
|
|
assert(!qpdf_oh_is_scalar(qpdf, contents_dict));
|
|
qpdf_oh contents_length = qpdf_oh_get_key(qpdf, contents_dict, "/Length");
|
|
assert(qpdf_oh_is_integer(qpdf, contents_length));
|
|
assert(qpdf_oh_get_type_code(qpdf, contents_length) == ot_integer);
|
|
assert(strcmp(qpdf_oh_get_type_name(qpdf, contents_length), "integer") == 0);
|
|
assert(qpdf_oh_is_scalar(qpdf, contents_length));
|
|
assert(qpdf_oh_is_number(qpdf, contents_length));
|
|
qpdf_oh contents_array = qpdf_oh_wrap_in_array(qpdf, contents);
|
|
assert(qpdf_oh_get_array_n_items(qpdf, contents_array) == 1);
|
|
assert(
|
|
qpdf_oh_get_object_id(qpdf, qpdf_oh_get_array_item(qpdf, contents_array, 0)) ==
|
|
qpdf_oh_get_object_id(qpdf, contents));
|
|
/* Wrap in array for a non-trivial case */
|
|
qpdf_oh wrapped_contents_array = qpdf_oh_wrap_in_array(qpdf, contents_array);
|
|
assert(qpdf_oh_get_array_n_items(qpdf, wrapped_contents_array) == 1);
|
|
assert(
|
|
qpdf_oh_get_object_id(qpdf, qpdf_oh_get_array_item(qpdf, wrapped_contents_array, 0)) ==
|
|
qpdf_oh_get_object_id(qpdf, contents));
|
|
|
|
/* Exercise functions that work with indirect objects */
|
|
qpdf_oh resources = qpdf_oh_get_key(qpdf, page1, "/Resources");
|
|
qpdf_oh procset = qpdf_oh_get_key(qpdf, resources, "/ProcSet");
|
|
assert(strcmp(qpdf_oh_unparse(qpdf, procset), "5 0 R") == 0);
|
|
assert(strcmp(qpdf_oh_unparse_resolved(qpdf, procset), "[ /PDF /Text ]") == 0);
|
|
qpdf_oh_make_direct(qpdf, procset);
|
|
assert(strcmp(qpdf_oh_unparse(qpdf, procset), "[ /PDF /Text ]") == 0);
|
|
/* The replaced /ProcSet can be seen to be a direct object in the
|
|
* expected output PDF.
|
|
*/
|
|
qpdf_oh_replace_key(qpdf, resources, "/ProcSet", procset);
|
|
|
|
/* Release and access to exercise handling of object handle errors
|
|
* and to show that write still works after releasing. This test
|
|
* uses the default oh error handler, so messages get written to
|
|
* stderr. The warning about using the default error handler only
|
|
* appears once.
|
|
*/
|
|
qpdf_oh_release(qpdf, page1);
|
|
contents = qpdf_oh_get_key(qpdf, page1, "/Contents");
|
|
assert(qpdf_oh_is_null(qpdf, contents));
|
|
assert(qpdf_oh_get_type_code(qpdf, contents) == ot_null);
|
|
assert(strcmp(qpdf_oh_get_type_name(qpdf, contents), "null") == 0);
|
|
assert(qpdf_oh_is_array(qpdf, mediabox));
|
|
qpdf_oh_release_all(qpdf);
|
|
assert(!qpdf_oh_is_null(qpdf, mediabox));
|
|
assert(!qpdf_oh_is_array(qpdf, mediabox));
|
|
/* Make sure something is assigned when we exit so we check that
|
|
* it gets properly freed.
|
|
*/
|
|
qpdf_get_root(qpdf);
|
|
|
|
qpdf_init_write(qpdf, outfile);
|
|
qpdf_set_static_ID(qpdf, QPDF_TRUE);
|
|
qpdf_set_qdf_mode(qpdf, QPDF_TRUE);
|
|
qpdf_set_suppress_original_object_IDs(qpdf, QPDF_TRUE);
|
|
qpdf_write(qpdf);
|
|
report_errors();
|
|
}
|
|
|
|
static void
|
|
test25(char const* infile, char const* password, char const* outfile, char const* xarg)
|
|
{
|
|
/* This test case is designed for minimal.pdf. */
|
|
qpdf_read(qpdf, infile, password);
|
|
qpdf_oh root = qpdf_get_root(qpdf);
|
|
|
|
/* Parse objects from a string */
|
|
qpdf_oh parsed =
|
|
qpdf_oh_parse(qpdf, "[ 1 2.0 (3\xf7) << /Four [/Five] >> null true false /Six]");
|
|
qpdf_oh p_int = qpdf_oh_get_array_item(qpdf, parsed, 0);
|
|
qpdf_oh p_real = qpdf_oh_get_array_item(qpdf, parsed, 1);
|
|
qpdf_oh p_string = qpdf_oh_get_array_item(qpdf, parsed, 2);
|
|
qpdf_oh p_dict = qpdf_oh_get_array_item(qpdf, parsed, 3);
|
|
qpdf_oh p_null = qpdf_oh_get_array_item(qpdf, parsed, 4);
|
|
qpdf_oh p_bool = qpdf_oh_get_array_item(qpdf, parsed, 5);
|
|
qpdf_oh p_bool_f = qpdf_oh_get_array_item(qpdf, parsed, 6);
|
|
qpdf_oh p_name = qpdf_oh_get_array_item(qpdf, parsed, 7);
|
|
assert(qpdf_oh_is_integer(qpdf, p_int) && qpdf_oh_get_int_value_as_int(qpdf, p_int) == 1);
|
|
long long l = 0;
|
|
assert(qpdf_oh_get_value_as_longlong(qpdf, p_bool, &l) == QPDF_FALSE);
|
|
assert((qpdf_oh_get_value_as_longlong(qpdf, p_int, &l) == QPDF_TRUE) && (l == 1));
|
|
int i = 0;
|
|
assert(qpdf_oh_get_value_as_int(qpdf, p_bool, &i) == QPDF_FALSE);
|
|
assert((qpdf_oh_get_value_as_int(qpdf, p_int, &i) == QPDF_TRUE) && (i == 1));
|
|
unsigned long long ul = 0u;
|
|
assert(qpdf_oh_get_value_as_ulonglong(qpdf, p_bool, &ul) == QPDF_FALSE);
|
|
assert((qpdf_oh_get_value_as_ulonglong(qpdf, p_int, &ul) == QPDF_TRUE) && (ul == 1u));
|
|
unsigned int u = 0u;
|
|
assert(qpdf_oh_get_value_as_uint(qpdf, p_bool, &u) == QPDF_FALSE);
|
|
assert((qpdf_oh_get_value_as_uint(qpdf, p_int, &u) == QPDF_TRUE) && (u == 1u));
|
|
double d = 0.0;
|
|
assert(qpdf_oh_get_value_as_number(qpdf, p_bool, &d) == QPDF_FALSE);
|
|
assert(
|
|
(qpdf_oh_get_value_as_number(qpdf, p_int, &d) == QPDF_TRUE) && ((d - 1.0) < 1e-6) &&
|
|
((d - 1.0) > -1e-6));
|
|
assert(qpdf_oh_get_type_code(qpdf, p_int) == ot_integer);
|
|
assert(strcmp(qpdf_oh_get_type_name(qpdf, p_int), "integer") == 0);
|
|
assert(
|
|
qpdf_oh_is_real(qpdf, p_real) &&
|
|
(strcmp(qpdf_oh_get_real_value(qpdf, p_real), "2.0") == 0) &&
|
|
qpdf_oh_get_numeric_value(qpdf, p_real) == 2.0);
|
|
const char* r = "";
|
|
size_t length = 0;
|
|
assert(
|
|
(qpdf_oh_get_value_as_real(qpdf, p_name, &r, &length) == QPDF_FALSE) &&
|
|
(strcmp(r, "") == 0) && (length == 0));
|
|
assert(
|
|
(qpdf_oh_get_value_as_real(qpdf, p_real, &r, &length) == QPDF_TRUE) &&
|
|
(strcmp(r, "2.0") == 0) && (length == 3));
|
|
assert(qpdf_oh_get_type_code(qpdf, p_real) == ot_real);
|
|
assert(strcmp(qpdf_oh_get_type_name(qpdf, p_real), "real") == 0);
|
|
assert(
|
|
qpdf_oh_is_string(qpdf, p_string) &&
|
|
(strcmp(qpdf_oh_get_string_value(qpdf, p_string), "3\xf7") == 0) &&
|
|
(strcmp(qpdf_oh_get_utf8_value(qpdf, p_string), "3\xc3\xb7") == 0) &&
|
|
(strcmp(qpdf_oh_unparse_binary(qpdf, p_string), "<33f7>") == 0));
|
|
const char* str = "";
|
|
length = 0;
|
|
assert(
|
|
(qpdf_oh_get_value_as_string(qpdf, p_name, &str, &length) == QPDF_FALSE) &&
|
|
(strcmp(str, "") == 0) && (length == 0));
|
|
assert(
|
|
(qpdf_oh_get_value_as_string(qpdf, p_string, &str, &length) == QPDF_TRUE) &&
|
|
(strcmp(str, "3\xf7") == 0) && (length == 2));
|
|
const char* utf8 = "";
|
|
length = 0;
|
|
assert(
|
|
(qpdf_oh_get_value_as_utf8(qpdf, p_name, &utf8, &length) == QPDF_FALSE) &&
|
|
(strcmp(utf8, "") == 0) && (length == 0));
|
|
assert(
|
|
(qpdf_oh_get_value_as_utf8(qpdf, p_string, &utf8, &length) == QPDF_TRUE) &&
|
|
(strcmp(utf8, "3\xc3\xb7") == 0) && (length == 3));
|
|
assert(qpdf_oh_get_type_code(qpdf, p_string) == ot_string);
|
|
assert(!qpdf_oh_is_name_and_equals(qpdf, p_string, "3\xf7"));
|
|
assert(strcmp(qpdf_oh_get_type_name(qpdf, p_string), "string") == 0);
|
|
assert(qpdf_oh_is_dictionary(qpdf, p_dict));
|
|
qpdf_oh p_five = qpdf_oh_get_key(qpdf, p_dict, "/Four");
|
|
assert(qpdf_oh_is_or_has_name(qpdf, p_five, "/Five"));
|
|
assert(!qpdf_oh_is_name_and_equals(qpdf, p_five, "/Five"));
|
|
assert(qpdf_oh_is_or_has_name(qpdf, qpdf_oh_get_array_item(qpdf, p_five, 0), "/Five"));
|
|
assert(qpdf_oh_is_name_and_equals(qpdf, qpdf_oh_get_array_item(qpdf, p_five, 0), "/Five"));
|
|
assert(qpdf_oh_is_null(qpdf, p_null));
|
|
assert(qpdf_oh_get_type_code(qpdf, p_null) == ot_null);
|
|
assert(strcmp(qpdf_oh_get_type_name(qpdf, p_null), "null") == 0);
|
|
assert(qpdf_oh_is_bool(qpdf, p_bool) && (qpdf_oh_get_bool_value(qpdf, p_bool) == QPDF_TRUE));
|
|
QPDF_BOOL b = QPDF_FALSE;
|
|
assert((qpdf_oh_get_value_as_bool(qpdf, p_int, &b) == QPDF_FALSE) && b == QPDF_FALSE);
|
|
assert((qpdf_oh_get_value_as_bool(qpdf, p_bool, &b) == QPDF_TRUE) && b == QPDF_TRUE);
|
|
assert((qpdf_oh_get_value_as_bool(qpdf, p_bool_f, &b) == QPDF_TRUE) && b == QPDF_FALSE);
|
|
assert(qpdf_oh_get_type_code(qpdf, p_bool) == ot_boolean);
|
|
assert(strcmp(qpdf_oh_get_type_name(qpdf, p_bool), "boolean") == 0);
|
|
const char* n = "";
|
|
length = 0;
|
|
assert(
|
|
(qpdf_oh_get_value_as_name(qpdf, p_string, &n, &length) == QPDF_FALSE) &&
|
|
(strcmp(n, "") == 0) && (length == 0));
|
|
assert(
|
|
(qpdf_oh_get_value_as_name(qpdf, p_name, &n, &length) == QPDF_TRUE) &&
|
|
(strcmp(n, "/Six") == 0) && (length == 4));
|
|
qpdf_oh_erase_item(qpdf, parsed, 4);
|
|
qpdf_oh_insert_item(
|
|
qpdf,
|
|
parsed,
|
|
2,
|
|
qpdf_oh_parse(qpdf, "<</A 1 /B 2 /C 3 /D 4 /Type /Test /Subtype /Marvin>>"));
|
|
qpdf_oh new_dict = qpdf_oh_get_array_item(qpdf, parsed, 2);
|
|
assert(qpdf_oh_has_key(qpdf, new_dict, "/A"));
|
|
assert(qpdf_oh_has_key(qpdf, new_dict, "/D"));
|
|
assert(qpdf_oh_is_dictionary_of_type(qpdf, new_dict, "/Test", ""));
|
|
assert(qpdf_oh_is_dictionary_of_type(qpdf, new_dict, "/Test", 0));
|
|
assert(qpdf_oh_is_dictionary_of_type(qpdf, new_dict, "/Test", "/Marvin"));
|
|
assert(!qpdf_oh_is_dictionary_of_type(qpdf, new_dict, "/Test2", ""));
|
|
assert(!qpdf_oh_is_dictionary_of_type(qpdf, new_dict, "/Test", "/M"));
|
|
assert(qpdf_oh_is_dictionary_of_type(qpdf, new_dict, "", ""));
|
|
qpdf_oh new_array = qpdf_oh_new_array(qpdf);
|
|
qpdf_oh_replace_or_remove_key(qpdf, new_dict, "/A", qpdf_oh_new_null(qpdf));
|
|
qpdf_oh_replace_or_remove_key(qpdf, new_dict, "/B", new_array);
|
|
qpdf_oh_replace_key(qpdf, new_dict, "/C", qpdf_oh_new_dictionary(qpdf));
|
|
qpdf_oh_remove_key(qpdf, new_dict, "/D");
|
|
assert(!qpdf_oh_has_key(qpdf, new_dict, "/A"));
|
|
assert(!qpdf_oh_has_key(qpdf, new_dict, "/D"));
|
|
qpdf_oh_append_item(qpdf, new_array, qpdf_oh_new_string(qpdf, "potato"));
|
|
qpdf_oh_append_item(qpdf, new_array, qpdf_oh_new_unicode_string(qpdf, "qww\xc3\xb7\xcf\x80"));
|
|
qpdf_oh_append_item(
|
|
qpdf, new_array, qpdf_oh_new_binary_unicode_string(qpdf, "qw\x00w\xc3\xb7\xcf\x80", 8));
|
|
qpdf_oh_append_item(qpdf, new_array, qpdf_oh_new_null(qpdf)); /* 2 */
|
|
qpdf_oh_append_item(qpdf, new_array, qpdf_oh_new_null(qpdf)); /* 3 */
|
|
qpdf_oh_set_array_item(qpdf, new_array, 3, qpdf_oh_new_name(qpdf, "/Quack"));
|
|
qpdf_oh_append_item(qpdf, new_array, qpdf_oh_new_real_from_double(qpdf, 4.123, 2));
|
|
qpdf_oh_append_item(qpdf, new_array, qpdf_oh_new_real_from_string(qpdf, "5.0"));
|
|
qpdf_oh_append_item(qpdf, new_array, qpdf_oh_new_integer(qpdf, 6));
|
|
qpdf_oh_append_item(qpdf, new_array, qpdf_oh_new_bool(qpdf, QPDF_TRUE));
|
|
qpdf_oh_replace_key(qpdf, root, "/QTest", new_dict);
|
|
|
|
qpdf_init_write(qpdf, outfile);
|
|
qpdf_set_static_ID(qpdf, QPDF_TRUE);
|
|
qpdf_set_qdf_mode(qpdf, QPDF_TRUE);
|
|
qpdf_set_suppress_original_object_IDs(qpdf, QPDF_TRUE);
|
|
qpdf_write(qpdf);
|
|
report_errors();
|
|
}
|
|
static void
|
|
test26(char const* infile, char const* password, char const* outfile, char const* xarg)
|
|
{
|
|
/* Make sure we detect uninitialized objects */
|
|
qpdf_data qpdf2 = qpdf_init();
|
|
qpdf_oh trailer = qpdf_get_trailer(qpdf2);
|
|
assert(!qpdf_oh_is_initialized(qpdf2, trailer));
|
|
assert(qpdf_oh_get_type_code(qpdf, trailer) == ot_uninitialized);
|
|
qpdf_cleanup(&qpdf2);
|
|
}
|
|
|
|
static void
|
|
test27(char const* infile, char const* password, char const* outfile, char const* xarg)
|
|
{
|
|
/* Exercise a string with a null. Since the regular methods return
|
|
* char*, we can't see past the null character without looking
|
|
* explicitly at the length.
|
|
*/
|
|
qpdf_oh p_string_with_null = qpdf_oh_parse(qpdf, "<6f6e650074776f>");
|
|
assert(qpdf_oh_is_string(qpdf, p_string_with_null));
|
|
assert(strcmp(qpdf_oh_get_string_value(qpdf, p_string_with_null), "one") == 0);
|
|
assert(qpdf_get_last_string_length(qpdf) == 7);
|
|
/* memcmp adds a character to verify the trailing null */
|
|
assert(memcmp(qpdf_oh_get_string_value(qpdf, p_string_with_null), "one\000two", 8) == 0);
|
|
size_t length = 0;
|
|
p_string_with_null = qpdf_oh_new_binary_string(qpdf, "potato\000salad", 12);
|
|
/* memcmp adds a character to verify the trailing null */
|
|
assert(
|
|
memcmp(
|
|
qpdf_oh_get_binary_string_value(qpdf, p_string_with_null, &length),
|
|
"potato\000salad",
|
|
13) == 0);
|
|
assert(qpdf_get_last_string_length(qpdf) == 12);
|
|
assert(length == 12);
|
|
/* repeat for UTF8 string */
|
|
qpdf_oh p_utf8_string_with_null = qpdf_oh_parse(qpdf, "<feff007100770000007700f703c0>");
|
|
assert(qpdf_oh_is_string(qpdf, p_utf8_string_with_null));
|
|
assert(
|
|
strcmp(qpdf_oh_get_utf8_value(qpdf, p_utf8_string_with_null), "qw\x00w\xc3\xb7\xcf\x80") ==
|
|
0);
|
|
assert(qpdf_get_last_string_length(qpdf) == 8);
|
|
/* memcmp adds a character to verify the trailing null */
|
|
assert(
|
|
memcmp(
|
|
qpdf_oh_get_utf8_value(qpdf, p_utf8_string_with_null), "qw\x00w\xc3\xb7\xcf\x80", 8) ==
|
|
0);
|
|
p_utf8_string_with_null = qpdf_oh_new_binary_unicode_string(qpdf, "qw\x00w\xc3\xb7\xcf\x80", 8);
|
|
/* memcmp adds a character to verify the trailing null */
|
|
assert(
|
|
memcmp(
|
|
qpdf_oh_get_binary_utf8_value(qpdf, p_utf8_string_with_null, &length),
|
|
"qw\x00w\xc3\xb7\xcf\x80",
|
|
9) == 0);
|
|
assert(qpdf_get_last_string_length(qpdf) == 8);
|
|
assert(length == 8);
|
|
}
|
|
|
|
static void
|
|
test28(char const* infile, char const* password, char const* outfile, char const* xarg)
|
|
{
|
|
/* This test case is designed for minimal.pdf. */
|
|
|
|
/* Look at the media box. The media box is in array. Trivially
|
|
* wrap it and also clone it and make sure we get different
|
|
* handles with the same contents.
|
|
*/
|
|
qpdf_read(qpdf, infile, password);
|
|
qpdf_oh root = qpdf_get_root(qpdf);
|
|
qpdf_oh pages = qpdf_oh_get_key(qpdf, root, "/Pages");
|
|
qpdf_oh kids = qpdf_oh_get_key(qpdf, pages, "/Kids");
|
|
qpdf_oh page1 = qpdf_oh_get_array_item(qpdf, kids, 0);
|
|
qpdf_oh mediabox = qpdf_oh_get_key(qpdf, page1, "/MediaBox");
|
|
qpdf_oh wrapped_mediabox = qpdf_oh_wrap_in_array(qpdf, mediabox);
|
|
qpdf_oh cloned_mediabox = qpdf_oh_new_object(qpdf, mediabox);
|
|
assert(wrapped_mediabox != mediabox);
|
|
assert(cloned_mediabox != mediabox);
|
|
assert(qpdf_oh_get_array_n_items(qpdf, wrapped_mediabox) == 4);
|
|
for (int i = 0; i < 4; ++i) {
|
|
qpdf_oh item = qpdf_oh_get_array_item(qpdf, mediabox, i);
|
|
qpdf_oh item2 = qpdf_oh_get_array_item(qpdf, wrapped_mediabox, i);
|
|
qpdf_oh item3 = qpdf_oh_get_array_item(qpdf, cloned_mediabox, i);
|
|
assert(
|
|
qpdf_oh_get_int_value_as_int(qpdf, item) ==
|
|
(i == 0 ? 0
|
|
: i == 1 ? 0
|
|
: i == 2 ? 612
|
|
: i == 3 ? 792
|
|
: -1));
|
|
assert(
|
|
qpdf_oh_get_int_value_as_int(qpdf, item) == qpdf_oh_get_int_value_as_int(qpdf, item2));
|
|
assert(
|
|
qpdf_oh_get_int_value_as_int(qpdf, item) == qpdf_oh_get_int_value_as_int(qpdf, item3));
|
|
qpdf_oh_release(qpdf, item);
|
|
}
|
|
}
|
|
|
|
static void
|
|
test29(char const* infile, char const* password, char const* outfile, char const* xarg)
|
|
{
|
|
/* Trap exceptions thrown by object accessors. Type mismatches are
|
|
* errors rather than warnings when they don't have an owning QPDF
|
|
* object.
|
|
*/
|
|
qpdf_silence_errors(qpdf);
|
|
|
|
/* get_root fails when we have no trailer */
|
|
qpdf_oh root = qpdf_get_root(qpdf);
|
|
handle_oh_error(qpdf, "get root");
|
|
assert(root != 0);
|
|
assert(!qpdf_oh_is_initialized(qpdf, root));
|
|
|
|
assert(!qpdf_oh_is_initialized(qpdf, qpdf_oh_parse(qpdf, "[oops")));
|
|
handle_oh_error(qpdf, "bad parse");
|
|
report_errors();
|
|
|
|
assert(qpdf_oh_get_int_value_as_int(qpdf, qpdf_oh_new_string(qpdf, "x")) == 0);
|
|
handle_oh_error(qpdf, "type mismatch (int operation on string)");
|
|
qpdf_oh int_oh = qpdf_oh_new_integer(qpdf, 12);
|
|
assert(strlen(qpdf_oh_get_string_value(qpdf, int_oh)) == 0);
|
|
handle_oh_error(qpdf, "type mismatch (string operation on int)");
|
|
|
|
// This doesn't test every possible error flow, but it tests each
|
|
// way of handling errors in the library code.
|
|
assert(qpdf_oh_get_array_n_items(qpdf, int_oh) == 0);
|
|
handle_oh_error(qpdf, "array type mismatch - n_items");
|
|
assert(qpdf_oh_is_null(qpdf, qpdf_oh_get_array_item(qpdf, int_oh, 3)));
|
|
handle_oh_error(qpdf, "array type mismatch - item");
|
|
qpdf_oh_append_item(qpdf, int_oh, qpdf_oh_new_null(qpdf));
|
|
handle_oh_error(qpdf, "append to non-array");
|
|
qpdf_oh array = qpdf_oh_new_array(qpdf);
|
|
assert(qpdf_oh_is_null(qpdf, qpdf_oh_get_array_item(qpdf, array, 3)));
|
|
handle_oh_error(qpdf, "array bounds");
|
|
|
|
qpdf_oh_begin_dict_key_iter(qpdf, int_oh);
|
|
assert(qpdf_oh_dict_more_keys(qpdf) == QPDF_FALSE);
|
|
handle_oh_error(qpdf, "dictionary iter type mismatch");
|
|
assert(qpdf_oh_is_null(qpdf, qpdf_oh_get_key(qpdf, int_oh, "potato")));
|
|
handle_oh_error(qpdf, "dictionary type mismatch");
|
|
assert(qpdf_oh_has_key(qpdf, int_oh, "potato") == QPDF_FALSE);
|
|
handle_oh_error(qpdf, "dictionary type mismatch");
|
|
|
|
report_errors();
|
|
}
|
|
|
|
static void
|
|
test30(char const* infile, char const* password, char const* outfile, char const* xarg)
|
|
{
|
|
assert(qpdf_read(qpdf, infile, password) & QPDF_ERRORS);
|
|
/* Fail to handle error */
|
|
}
|
|
|
|
static void
|
|
test31(char const* infile, char const* password, char const* outfile, char const* xarg)
|
|
{
|
|
/* Make sure type warnings have a specific error code. This test
|
|
* case is designed for minimal.pdf.
|
|
*/
|
|
qpdf_read(qpdf, infile, password);
|
|
qpdf_oh trailer = qpdf_get_trailer(qpdf);
|
|
assert(qpdf_oh_get_int_value(qpdf, trailer) == 0LL);
|
|
assert(!qpdf_has_error(qpdf));
|
|
assert(qpdf_more_warnings(qpdf));
|
|
qpdf_error e = qpdf_next_warning(qpdf);
|
|
assert(qpdf_get_error_code(qpdf, e) == qpdf_e_object);
|
|
report_errors();
|
|
}
|
|
|
|
static void
|
|
test32(char const* infile, char const* password, char const* outfile, char const* xarg)
|
|
{
|
|
/* This test case is designed for minimal.pdf. */
|
|
assert(qpdf_read(qpdf, infile, password) == 0);
|
|
qpdf_oh page = qpdf_get_object_by_id(qpdf, 3, 0);
|
|
assert(qpdf_oh_is_dictionary(qpdf, page));
|
|
assert(qpdf_oh_has_key(qpdf, page, "/MediaBox"));
|
|
report_errors();
|
|
}
|
|
|
|
static void
|
|
test33(char const* infile, char const* password, char const* outfile, char const* xarg)
|
|
{
|
|
/* This test case is designed for minimal.pdf. */
|
|
|
|
/* Convert a direct object to an indirect object and replace it. */
|
|
assert(qpdf_read(qpdf, infile, password) == 0);
|
|
qpdf_oh root = qpdf_get_root(qpdf);
|
|
qpdf_oh pages = qpdf_oh_get_key(qpdf, root, "/Pages");
|
|
qpdf_oh kids = qpdf_oh_get_key(qpdf, pages, "/Kids");
|
|
qpdf_oh page1 = qpdf_oh_get_array_item(qpdf, kids, 0);
|
|
qpdf_oh mediabox = qpdf_oh_get_key(qpdf, page1, "/MediaBox");
|
|
assert(!qpdf_oh_is_indirect(qpdf, mediabox));
|
|
qpdf_oh i_mediabox = qpdf_make_indirect_object(qpdf, mediabox);
|
|
assert(qpdf_oh_is_indirect(qpdf, i_mediabox));
|
|
qpdf_oh_replace_key(qpdf, page1, "/MediaBox", i_mediabox);
|
|
|
|
/* Replace a different indirect object */
|
|
qpdf_oh resources = qpdf_oh_get_key(qpdf, page1, "/Resources");
|
|
qpdf_oh procset = qpdf_oh_get_key(qpdf, resources, "/ProcSet");
|
|
assert(qpdf_oh_is_indirect(qpdf, procset));
|
|
qpdf_replace_object(
|
|
qpdf,
|
|
qpdf_oh_get_object_id(qpdf, procset),
|
|
qpdf_oh_get_generation(qpdf, procset),
|
|
qpdf_oh_parse(qpdf, "[/PDF]"));
|
|
|
|
qpdf_init_write(qpdf, outfile);
|
|
qpdf_set_static_ID(qpdf, QPDF_TRUE);
|
|
qpdf_set_qdf_mode(qpdf, QPDF_TRUE);
|
|
qpdf_set_suppress_original_object_IDs(qpdf, QPDF_TRUE);
|
|
qpdf_write(qpdf);
|
|
report_errors();
|
|
}
|
|
|
|
static void
|
|
test34(char const* infile, char const* password, char const* outfile, char const* xarg)
|
|
{
|
|
/* This test expects 11-pages.pdf as file1 and minimal.pdf as xarg. */
|
|
|
|
/* Non-error cases for page API */
|
|
|
|
qpdf_data qpdf2 = qpdf_init();
|
|
assert(qpdf_read(qpdf, infile, password) == 0);
|
|
assert(qpdf_read(qpdf2, xarg, "") == 0);
|
|
assert(qpdf_get_num_pages(qpdf) == 11);
|
|
assert(qpdf_get_num_pages(qpdf2) == 1);
|
|
|
|
/* At this time, there is no C API for accessing stream data, so
|
|
* we hard-code object IDs from a known input file.
|
|
*/
|
|
assert(qpdf_oh_get_object_id(qpdf, qpdf_get_page_n(qpdf, 0)) == 4);
|
|
assert(qpdf_oh_get_object_id(qpdf, qpdf_get_page_n(qpdf, 10)) == 14);
|
|
qpdf_oh page3 = qpdf_get_page_n(qpdf, 3);
|
|
assert(qpdf_find_page_by_oh(qpdf, page3) == 3);
|
|
assert(qpdf_find_page_by_id(qpdf, qpdf_oh_get_object_id(qpdf, page3), 0) == 3);
|
|
|
|
/* Add other page to the end */
|
|
qpdf_oh opage0 = qpdf_get_page_n(qpdf2, 0);
|
|
assert(qpdf_add_page(qpdf, qpdf2, opage0, QPDF_FALSE) == 0);
|
|
/* Add other page before page 3 */
|
|
assert(qpdf_add_page_at(qpdf, qpdf2, opage0, QPDF_TRUE, page3) == 0);
|
|
/* Remove page 3 */
|
|
assert(qpdf_remove_page(qpdf, page3) == 0);
|
|
/* At page 3 back at the beginning */
|
|
assert(qpdf_add_page(qpdf, qpdf, page3, QPDF_TRUE) == 0);
|
|
|
|
qpdf_init_write(qpdf, outfile);
|
|
qpdf_set_static_ID(qpdf, QPDF_TRUE);
|
|
qpdf_set_qdf_mode(qpdf, QPDF_TRUE);
|
|
qpdf_set_suppress_original_object_IDs(qpdf, QPDF_TRUE);
|
|
qpdf_write(qpdf);
|
|
report_errors();
|
|
qpdf_cleanup(&qpdf2);
|
|
}
|
|
|
|
static void
|
|
test35(char const* infile, char const* password, char const* outfile, char const* xarg)
|
|
{
|
|
/* This test uses 11-pages.pdf */
|
|
|
|
assert(qpdf_get_num_pages(qpdf) == -1);
|
|
assert(qpdf_has_error(qpdf));
|
|
qpdf_error e = qpdf_get_error(qpdf);
|
|
assert(qpdf_get_error_code(qpdf, e) != QPDF_SUCCESS);
|
|
assert(!qpdf_has_error(qpdf));
|
|
|
|
assert(qpdf_read(qpdf, infile, password) == 0);
|
|
|
|
qpdf_oh range = qpdf_get_page_n(qpdf, 11);
|
|
assert(!qpdf_oh_is_initialized(qpdf, range));
|
|
assert(qpdf_has_error(qpdf));
|
|
e = qpdf_get_error(qpdf);
|
|
assert(qpdf_get_error_code(qpdf, e) != QPDF_SUCCESS);
|
|
assert(!qpdf_has_error(qpdf));
|
|
|
|
assert(qpdf_find_page_by_id(qpdf, 100, 0) == -1);
|
|
assert(qpdf_has_error(qpdf));
|
|
e = qpdf_get_error(qpdf);
|
|
assert(qpdf_get_error_code(qpdf, e) != QPDF_SUCCESS);
|
|
assert(!qpdf_has_error(qpdf));
|
|
|
|
assert(qpdf_find_page_by_oh(qpdf, qpdf_get_root(qpdf)) == -1);
|
|
assert(qpdf_more_warnings(qpdf));
|
|
e = qpdf_next_warning(qpdf);
|
|
assert(qpdf_get_error_code(qpdf, e) != QPDF_SUCCESS);
|
|
assert(qpdf_has_error(qpdf));
|
|
e = qpdf_get_error(qpdf);
|
|
assert(qpdf_get_error_code(qpdf, e) != QPDF_SUCCESS);
|
|
assert(!qpdf_has_error(qpdf));
|
|
|
|
assert(qpdf_find_page_by_id(qpdf, 100, 0) == -1);
|
|
assert(qpdf_has_error(qpdf));
|
|
e = qpdf_get_error(qpdf);
|
|
assert(qpdf_get_error_code(qpdf, e) != QPDF_SUCCESS);
|
|
assert(!qpdf_has_error(qpdf));
|
|
|
|
assert(qpdf_add_page(qpdf, qpdf, 1000, QPDF_FALSE) != 0);
|
|
|
|
report_errors();
|
|
}
|
|
|
|
static void
|
|
test36(char const* infile, char const* password, char const* outfile, char const* xarg)
|
|
{
|
|
/* This test uses inherited-rotate.pdf */
|
|
|
|
assert(qpdf_read(qpdf, infile, password) == 0);
|
|
|
|
/* Non-trivially push inherited attributes */
|
|
qpdf_oh page0 = qpdf_get_object_by_id(qpdf, 3, 0);
|
|
assert(qpdf_oh_is_dictionary(qpdf, page0));
|
|
qpdf_oh r = qpdf_oh_get_key(qpdf, page0, "/Rotate");
|
|
assert(qpdf_oh_get_int_value(qpdf, r) == 90);
|
|
qpdf_oh_remove_key(qpdf, page0, "/Rotate");
|
|
assert(!qpdf_oh_has_key(qpdf, page0, "/Rotate"));
|
|
|
|
assert(qpdf_push_inherited_attributes_to_page(qpdf) == 0);
|
|
r = qpdf_oh_get_key(qpdf, page0, "/Rotate");
|
|
assert(qpdf_oh_get_int_value(qpdf, r) == 270);
|
|
|
|
assert(qpdf_add_page(qpdf, qpdf, page0, QPDF_TRUE) == 0);
|
|
}
|
|
|
|
static void
|
|
test37(char const* infile, char const* password, char const* outfile, char const* xarg)
|
|
{
|
|
/* This test uses 11-pages.pdf */
|
|
|
|
/* Manually manipulate pages tree */
|
|
assert(qpdf_read(qpdf, infile, password) == 0);
|
|
assert(qpdf_get_num_pages(qpdf) == 11);
|
|
qpdf_oh pages = qpdf_get_object_by_id(qpdf, 3, 0);
|
|
qpdf_oh kids = qpdf_oh_get_key(qpdf, pages, "/Kids");
|
|
assert(qpdf_oh_get_array_n_items(qpdf, kids) == 11);
|
|
qpdf_oh_erase_item(qpdf, kids, 0);
|
|
assert(qpdf_get_num_pages(qpdf) == 11);
|
|
assert(qpdf_update_all_pages_cache(qpdf) == 0);
|
|
assert(qpdf_get_num_pages(qpdf) == 10);
|
|
}
|
|
|
|
static void
|
|
test38(char const* infile, char const* password, char const* outfile, char const* xarg)
|
|
{
|
|
/* This test expects 11-pages.pdf. */
|
|
|
|
/* Read stream data */
|
|
|
|
assert(qpdf_read(qpdf, infile, password) == 0);
|
|
qpdf_oh stream = qpdf_get_object_by_id(qpdf, 17, 0);
|
|
qpdf_oh dict = qpdf_oh_get_dict(qpdf, stream);
|
|
assert(qpdf_oh_get_int_value_as_int(qpdf, qpdf_oh_get_key(qpdf, dict, "/Length")) == 53);
|
|
/* Get raw data */
|
|
unsigned char* buf = 0;
|
|
size_t len = 0;
|
|
assert(qpdf_oh_get_stream_data(qpdf, stream, qpdf_dl_none, 0, &buf, &len) == 0);
|
|
assert(len == 53);
|
|
assert(((int)buf[0] == 'x') && ((int)buf[1] == 0234));
|
|
free(buf);
|
|
|
|
/* Test whether filterable */
|
|
QPDF_BOOL filtered = QPDF_FALSE;
|
|
assert(qpdf_oh_get_stream_data(qpdf, stream, qpdf_dl_all, &filtered, 0, 0) == 0);
|
|
assert(filtered == QPDF_TRUE);
|
|
|
|
/* Get filtered data */
|
|
assert(qpdf_oh_get_stream_data(qpdf, stream, qpdf_dl_all, 0, &buf, &len) == 0);
|
|
assert(len == 47);
|
|
assert(memcmp((char const*)buf, "BT /F1 15 Tf 72 720 Td (Original page 2) Tj ET\n", len) == 0);
|
|
|
|
/* Get page data */
|
|
qpdf_oh page2 = qpdf_get_page_n(qpdf, 1); /* 0-based index */
|
|
unsigned char* buf2 = 0;
|
|
assert(qpdf_oh_get_page_content_data(qpdf, page2, &buf2, &len) == 0);
|
|
assert(len == 47);
|
|
assert(memcmp(buf, buf2, len) == 0);
|
|
free(buf);
|
|
free(buf2);
|
|
|
|
/* errors */
|
|
printf("page content on broken page\n");
|
|
qpdf_oh_replace_key(qpdf, page2, "/Contents", qpdf_oh_new_integer(qpdf, 3));
|
|
buf = 0;
|
|
qpdf_oh_get_page_content_data(qpdf, page2, &buf, &len);
|
|
assert(buf == 0);
|
|
report_errors();
|
|
printf("stream data for non stream\n");
|
|
qpdf_oh root = qpdf_get_root(qpdf);
|
|
assert(qpdf_oh_get_stream_data(qpdf, root, qpdf_dl_all, 0, 0, 0) != 0);
|
|
report_errors();
|
|
}
|
|
|
|
static void
|
|
test39(char const* infile, char const* password, char const* outfile, char const* xarg)
|
|
{
|
|
/* This test expects 11-pages.pdf as file1 and minimal.pdf as xarg. */
|
|
|
|
/* Foreign object */
|
|
|
|
qpdf_data qpdf2 = qpdf_init();
|
|
assert(qpdf_read(qpdf, infile, password) == 0);
|
|
assert(qpdf_read(qpdf2, xarg, "") == 0);
|
|
|
|
qpdf_oh resources = qpdf_get_object_by_id(qpdf2, 3, 0);
|
|
qpdf_oh copy = qpdf_oh_copy_foreign_object(qpdf, qpdf2, resources);
|
|
qpdf_oh root = qpdf_get_root(qpdf);
|
|
qpdf_oh_replace_key(qpdf, root, "/Copy", copy);
|
|
|
|
qpdf_init_write(qpdf, outfile);
|
|
qpdf_set_static_ID(qpdf, QPDF_TRUE);
|
|
qpdf_set_qdf_mode(qpdf, QPDF_TRUE);
|
|
qpdf_set_suppress_original_object_IDs(qpdf, QPDF_TRUE);
|
|
qpdf_write(qpdf);
|
|
report_errors();
|
|
qpdf_cleanup(&qpdf2);
|
|
}
|
|
|
|
static void
|
|
test40(char const* infile, char const* password, char const* outfile, char const* xarg)
|
|
{
|
|
/* This test expects minimal.pdf. */
|
|
|
|
/* New stream */
|
|
|
|
assert(qpdf_read(qpdf, infile, password) == 0);
|
|
qpdf_oh stream = qpdf_oh_new_stream(qpdf);
|
|
qpdf_oh_replace_stream_data(
|
|
qpdf,
|
|
stream,
|
|
(unsigned char*)"12345\000abcde",
|
|
11, /* embedded null */
|
|
qpdf_oh_new_null(qpdf),
|
|
qpdf_oh_new_null(qpdf));
|
|
qpdf_oh root = qpdf_get_root(qpdf);
|
|
qpdf_oh_replace_key(qpdf, root, "/Potato", stream);
|
|
|
|
qpdf_init_write(qpdf, outfile);
|
|
qpdf_set_static_ID(qpdf, QPDF_TRUE);
|
|
qpdf_set_qdf_mode(qpdf, QPDF_TRUE);
|
|
qpdf_set_suppress_original_object_IDs(qpdf, QPDF_TRUE);
|
|
qpdf_write(qpdf);
|
|
report_errors();
|
|
}
|
|
|
|
static void
|
|
test41(char const* infile, char const* password, char const* outfile, char const* xarg)
|
|
{
|
|
/* Empty PDF -- infile is ignored */
|
|
assert(qpdf_empty_pdf(qpdf) == 0);
|
|
qpdf_init_write(qpdf, outfile);
|
|
qpdf_set_static_ID(qpdf, QPDF_TRUE);
|
|
qpdf_write(qpdf);
|
|
report_errors();
|
|
}
|
|
|
|
static void
|
|
test42(char const* infile, char const* password, char const* outfile, char const* xarg)
|
|
{
|
|
assert(qpdf_create_from_json_file(qpdf, infile) == QPDF_SUCCESS);
|
|
qpdf_init_write(qpdf, outfile);
|
|
qpdf_set_static_ID(qpdf, QPDF_TRUE);
|
|
qpdf_write(qpdf);
|
|
report_errors();
|
|
}
|
|
|
|
static void
|
|
test43(char const* infile, char const* password, char const* outfile, char const* xarg)
|
|
{
|
|
char* buf = NULL;
|
|
unsigned long size = 0;
|
|
read_file_into_memory(infile, &buf, &size);
|
|
assert(qpdf_create_from_json_data(qpdf, buf, size) == QPDF_SUCCESS);
|
|
qpdf_init_write(qpdf, outfile);
|
|
qpdf_set_static_ID(qpdf, QPDF_TRUE);
|
|
qpdf_write(qpdf);
|
|
report_errors();
|
|
free(buf);
|
|
}
|
|
|
|
static void
|
|
test44(char const* infile, char const* password, char const* outfile, char const* xarg)
|
|
{
|
|
assert(qpdf_read(qpdf, infile, password) == 0);
|
|
assert(qpdf_update_from_json_file(qpdf, xarg) == QPDF_SUCCESS);
|
|
qpdf_init_write(qpdf, outfile);
|
|
qpdf_set_static_ID(qpdf, QPDF_TRUE);
|
|
qpdf_write(qpdf);
|
|
report_errors();
|
|
}
|
|
|
|
static void
|
|
test45(char const* infile, char const* password, char const* outfile, char const* xarg)
|
|
{
|
|
char* buf = NULL;
|
|
unsigned long size = 0;
|
|
read_file_into_memory(xarg, &buf, &size);
|
|
assert(qpdf_read(qpdf, infile, password) == 0);
|
|
assert(qpdf_update_from_json_data(qpdf, buf, size) == QPDF_SUCCESS);
|
|
qpdf_init_write(qpdf, outfile);
|
|
qpdf_set_static_ID(qpdf, QPDF_TRUE);
|
|
qpdf_write(qpdf);
|
|
report_errors();
|
|
free(buf);
|
|
}
|
|
|
|
static void
|
|
test46(char const* infile, char const* password, char const* outfile, char const* xarg)
|
|
{
|
|
FILE* f = safe_fopen(outfile, "wb");
|
|
assert(qpdf_read(qpdf, infile, password) == 0);
|
|
qpdf_write_json(qpdf, 2, write_to_file, f, qpdf_dl_none, qpdf_sj_inline, "", NULL);
|
|
fclose(f);
|
|
report_errors();
|
|
}
|
|
|
|
static void
|
|
test47(char const* infile, char const* password, char const* outfile, char const* xarg)
|
|
{
|
|
FILE* f = safe_fopen(outfile, "wb");
|
|
assert(qpdf_read(qpdf, infile, password) == 0);
|
|
char const* wanted_objects[] = {"obj:4 0 R", "trailer", NULL};
|
|
qpdf_write_json(
|
|
qpdf, 2, write_to_file, f, qpdf_dl_specialized, qpdf_sj_file, xarg, wanted_objects);
|
|
fclose(f);
|
|
report_errors();
|
|
}
|
|
|
|
int
|
|
main(int argc, char* argv[])
|
|
{
|
|
char* p = 0;
|
|
int n = 0;
|
|
char const* infile = 0;
|
|
char const* password = 0;
|
|
char const* outfile = 0;
|
|
char const* xarg = 0;
|
|
void (*fn)(char const*, char const*, char const*, char const*) = 0;
|
|
|
|
if ((p = strrchr(argv[0], '/')) != NULL) {
|
|
whoami = p + 1;
|
|
} else if ((p = strrchr(argv[0], '\\')) != NULL) {
|
|
whoami = p + 1;
|
|
} else {
|
|
whoami = argv[0];
|
|
}
|
|
if ((argc == 2) && (strcmp(argv[1], "--version") == 0)) {
|
|
printf("qpdf-ctest version %s\n", qpdf_get_qpdf_version());
|
|
return 0;
|
|
}
|
|
|
|
if (argc < 5) {
|
|
fprintf(stderr, "usage: %s n infile password outfile\n", whoami);
|
|
exit(2);
|
|
}
|
|
|
|
n = atoi(argv[1]);
|
|
infile = argv[2];
|
|
password = argv[3];
|
|
outfile = argv[4];
|
|
xarg = (argc > 5 ? argv[5] : 0);
|
|
|
|
fn =
|
|
((n == 1) ? test01
|
|
: (n == 2) ? test02
|
|
: (n == 3) ? test03
|
|
: (n == 4) ? test04
|
|
: (n == 5) ? test05
|
|
: (n == 6) ? test06
|
|
: (n == 7) ? test07
|
|
: (n == 8) ? test08
|
|
: (n == 9) ? test09
|
|
: (n == 10) ? test10
|
|
: (n == 11) ? test11
|
|
: (n == 12) ? test12
|
|
: (n == 13) ? test13
|
|
: (n == 14) ? test14
|
|
: (n == 15) ? test15
|
|
: (n == 16) ? test16
|
|
: (n == 17) ? test17
|
|
: (n == 18) ? test18
|
|
: (n == 19) ? test19
|
|
: (n == 20) ? test20
|
|
: (n == 21) ? test21
|
|
: (n == 22) ? test22
|
|
: (n == 23) ? test23
|
|
: (n == 24) ? test24
|
|
: (n == 25) ? test25
|
|
: (n == 26) ? test26
|
|
: (n == 27) ? test27
|
|
: (n == 28) ? test28
|
|
: (n == 29) ? test29
|
|
: (n == 30) ? test30
|
|
: (n == 31) ? test31
|
|
: (n == 32) ? test32
|
|
: (n == 33) ? test33
|
|
: (n == 34) ? test34
|
|
: (n == 35) ? test35
|
|
: (n == 36) ? test36
|
|
: (n == 37) ? test37
|
|
: (n == 38) ? test38
|
|
: (n == 39) ? test39
|
|
: (n == 40) ? test40
|
|
: (n == 41) ? test41
|
|
: (n == 42) ? test42
|
|
: (n == 43) ? test43
|
|
: (n == 44) ? test44
|
|
: (n == 45) ? test45
|
|
: (n == 46) ? test46
|
|
: (n == 47) ? test47
|
|
: 0);
|
|
|
|
if (fn == 0) {
|
|
fprintf(stderr, "%s: invalid test number %d\n", whoami, n);
|
|
exit(2);
|
|
}
|
|
|
|
qpdf = qpdf_init();
|
|
fn(infile, password, outfile, xarg);
|
|
qpdf_cleanup(&qpdf);
|
|
assert(qpdf == 0);
|
|
printf("C test %d done\n", n);
|
|
|
|
return 0;
|
|
}
|