#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // must set qpdf->filename and qpdf->password static void call_read(qpdf_data qpdf) { qpdf->qpdf->processFile(qpdf->filename, qpdf->password); } // must set qpdf->filename, qpdf->buffer, qpdf->size, and qpdf->password static void call_read_memory(qpdf_data qpdf) { qpdf->qpdf->processMemoryFile( qpdf->filename, qpdf->buffer, QIntC::to_size(qpdf->size), qpdf->password); } // must set qpdf->filename static void call_init_write(qpdf_data qpdf) { qpdf->qpdf_writer = std::make_shared(*(qpdf->qpdf), qpdf->filename); } static void call_init_write_memory(qpdf_data qpdf) { qpdf->qpdf_writer = std::make_shared(*(qpdf->qpdf)); qpdf->qpdf_writer->setOutputMemory(); } 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, std::function fn) { QPDF_ERROR_CODE status = QPDF_SUCCESS; try { fn(qpdf); } catch (QPDFExc& e) { qpdf->error = std::make_shared(e); status |= QPDF_ERRORS; } catch (std::runtime_error& e) { qpdf->error = std::make_shared(qpdf_e_system, "", "", 0, e.what()); status |= QPDF_ERRORS; } catch (std::exception& e) { qpdf->error = std::make_shared(qpdf_e_internal, "", "", 0, e.what()); status |= QPDF_ERRORS; } if (qpdf_more_warnings(qpdf)) { status |= QPDF_WARNINGS; } return status; } char const* qpdf_get_qpdf_version() { QTC::TC("qpdf", "qpdf-c called qpdf_get_qpdf_version"); // The API guarantees that this is a static value. return QPDF::QPDFVersion().c_str(); } qpdf_data qpdf_init() { QTC::TC("qpdf", "qpdf-c called qpdf_init"); auto qpdf = new _qpdf_data(); qpdf->qpdf = QPDF::create(); return qpdf; } void qpdf_cleanup(qpdf_data* qpdf) { QTC::TC("qpdf", "qpdf-c called qpdf_cleanup"); qpdf_oh_release_all(*qpdf); if ((*qpdf)->error.get()) { QTC::TC("qpdf", "qpdf-c cleanup warned about unhandled error"); *QPDFLogger::defaultLogger()->getWarn() << "WARNING: application did not handle error: " << (*qpdf)->error->what() << "\n"; } delete *qpdf; *qpdf = nullptr; } size_t qpdf_get_last_string_length(qpdf_data qpdf) { return qpdf->tmp_string.length(); } QPDF_BOOL qpdf_more_warnings(qpdf_data qpdf) { QTC::TC("qpdf", "qpdf-c called qpdf_more_warnings"); if (qpdf->warnings.empty()) { std::vector w = qpdf->qpdf->getWarnings(); if (!w.empty()) { qpdf->warnings.assign(w.begin(), w.end()); } } if (qpdf->warnings.empty()) { return QPDF_FALSE; } else { return QPDF_TRUE; } } QPDF_BOOL qpdf_has_error(qpdf_data qpdf) { QTC::TC("qpdf", "qpdf-c called qpdf_has_error"); return (qpdf->error.get() ? QPDF_TRUE : QPDF_FALSE); } qpdf_error qpdf_get_error(qpdf_data qpdf) { if (qpdf->error.get()) { qpdf->tmp_error.exc = qpdf->error; qpdf->error = nullptr; QTC::TC("qpdf", "qpdf-c qpdf_get_error returned error"); return &qpdf->tmp_error; } else { return nullptr; } } qpdf_error qpdf_next_warning(qpdf_data qpdf) { if (qpdf_more_warnings(qpdf)) { qpdf->tmp_error.exc = std::make_shared(qpdf->warnings.front()); qpdf->warnings.pop_front(); QTC::TC("qpdf", "qpdf-c qpdf_next_warning returned warning"); return &qpdf->tmp_error; } else { return nullptr; } } char const* qpdf_get_error_full_text(qpdf_data qpdf, qpdf_error e) { if (e == nullptr) { return ""; } return e->exc->what(); } enum qpdf_error_code_e qpdf_get_error_code(qpdf_data qpdf, qpdf_error e) { if (e == nullptr) { return qpdf_e_success; } return e->exc->getErrorCode(); } char const* qpdf_get_error_filename(qpdf_data qpdf, qpdf_error e) { if (e == nullptr) { return ""; } return e->exc->getFilename().c_str(); } unsigned long long qpdf_get_error_file_position(qpdf_data qpdf, qpdf_error e) { if (e == nullptr) { return 0; } return QIntC::to_ulonglong(e->exc->getFilePosition()); } char const* qpdf_get_error_message_detail(qpdf_data qpdf, qpdf_error e) { if (e == nullptr) { return ""; } 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_logger(qpdf_data qpdf, qpdflogger_handle logger) { qpdf->qpdf->setLogger(logger->l); } qpdflogger_handle qpdf_get_logger(qpdf_data qpdf) { return new _qpdflogger_handle(qpdf->qpdf->getLogger()); } void qpdf_set_suppress_warnings(qpdf_data qpdf, QPDF_BOOL value) { QTC::TC("qpdf", "qpdf-c called qpdf_set_suppress_warnings"); qpdf->qpdf->setSuppressWarnings(value != QPDF_FALSE); } void qpdf_set_ignore_xref_streams(qpdf_data qpdf, QPDF_BOOL value) { QTC::TC("qpdf", "qpdf-c called qpdf_set_ignore_xref_streams"); qpdf->qpdf->setIgnoreXRefStreams(value != QPDF_FALSE); } void qpdf_set_attempt_recovery(qpdf_data qpdf, QPDF_BOOL value) { QTC::TC("qpdf", "qpdf-c called qpdf_set_attempt_recovery"); qpdf->qpdf->setAttemptRecovery(value != QPDF_FALSE); } QPDF_ERROR_CODE qpdf_read(qpdf_data qpdf, char const* filename, char const* password) { QPDF_ERROR_CODE status = QPDF_SUCCESS; qpdf->filename = filename; qpdf->password = password; status = trap_errors(qpdf, &call_read); // We no longer have a good way to exercise a file with both warnings and errors because qpdf is // getting much better at recovering. QTC::TC( "qpdf", "qpdf-c called qpdf_read", (status == 0) ? 0 : (status & QPDF_WARNINGS) ? 1 : (status & QPDF_ERRORS) ? 2 : -1); return status; } QPDF_ERROR_CODE qpdf_read_memory( qpdf_data qpdf, char const* description, char const* buffer, unsigned long long size, char const* password) { QPDF_ERROR_CODE status = QPDF_SUCCESS; qpdf->filename = description; qpdf->buffer = buffer; qpdf->size = size; qpdf->password = password; status = trap_errors(qpdf, &call_read_memory); QTC::TC("qpdf", "qpdf-c called qpdf_read_memory", status); return status; } QPDF_ERROR_CODE qpdf_empty_pdf(qpdf_data qpdf) { qpdf->filename = "empty PDF"; qpdf->qpdf->emptyPDF(); QTC::TC("qpdf", "qpdf-c called qpdf_empty_pdf"); return QPDF_SUCCESS; } char const* qpdf_get_pdf_version(qpdf_data qpdf) { QTC::TC("qpdf", "qpdf-c called qpdf_get_pdf_version"); qpdf->tmp_string = qpdf->qpdf->getPDFVersion(); return qpdf->tmp_string.c_str(); } int qpdf_get_pdf_extension_level(qpdf_data qpdf) { QTC::TC("qpdf", "qpdf-c called qpdf_get_pdf_extension_level"); return qpdf->qpdf->getExtensionLevel(); } char const* qpdf_get_user_password(qpdf_data qpdf) { QTC::TC("qpdf", "qpdf-c called qpdf_get_user_password"); qpdf->tmp_string = qpdf->qpdf->getTrimmedUserPassword(); return qpdf->tmp_string.c_str(); } char const* qpdf_get_info_key(qpdf_data qpdf, char const* key) { char const* result = nullptr; QPDFObjectHandle trailer = qpdf->qpdf->getTrailer(); if (trailer.hasKey("/Info")) { QPDFObjectHandle info = trailer.getKey("/Info"); if (info.hasKey(key)) { QPDFObjectHandle value = info.getKey(key); if (value.isString()) { qpdf->tmp_string = value.getStringValue(); result = qpdf->tmp_string.c_str(); } } } QTC::TC("qpdf", "qpdf-c get_info_key", (result == nullptr ? 0 : 1)); return result; } void qpdf_set_info_key(qpdf_data qpdf, char const* key, char const* value) { if ((key == nullptr) || (std::strlen(key) == 0) || (key[0] != '/')) { return; } QPDFObjectHandle value_object; if (value) { QTC::TC("qpdf", "qpdf-c set_info_key to value"); value_object = QPDFObjectHandle::newString(value); } else { QTC::TC("qpdf", "qpdf-c set_info_key to null"); value_object = QPDFObjectHandle::newNull(); } QPDFObjectHandle trailer = qpdf->qpdf->getTrailer(); if (!trailer.hasKey("/Info")) { QTC::TC("qpdf", "qpdf-c add info to trailer"); trailer.replaceKey( "/Info", qpdf->qpdf->makeIndirectObject(QPDFObjectHandle::newDictionary())); } else { QTC::TC("qpdf", "qpdf-c set-info-key use existing info"); } QPDFObjectHandle info = trailer.getKey("/Info"); info.replaceKey(key, value_object); } QPDF_BOOL qpdf_is_linearized(qpdf_data qpdf) { QTC::TC("qpdf", "qpdf-c called qpdf_is_linearized"); return (qpdf->qpdf->isLinearized() ? QPDF_TRUE : QPDF_FALSE); } QPDF_BOOL qpdf_is_encrypted(qpdf_data qpdf) { QTC::TC("qpdf", "qpdf-c called qpdf_is_encrypted"); return (qpdf->qpdf->isEncrypted() ? QPDF_TRUE : QPDF_FALSE); } QPDF_BOOL qpdf_allow_accessibility(qpdf_data qpdf) { QTC::TC("qpdf", "qpdf-c called qpdf_allow_accessibility"); return (qpdf->qpdf->allowAccessibility() ? QPDF_TRUE : QPDF_FALSE); } QPDF_BOOL qpdf_allow_extract_all(qpdf_data qpdf) { QTC::TC("qpdf", "qpdf-c called qpdf_allow_extract_all"); return (qpdf->qpdf->allowExtractAll() ? QPDF_TRUE : QPDF_FALSE); } QPDF_BOOL qpdf_allow_print_low_res(qpdf_data qpdf) { QTC::TC("qpdf", "qpdf-c called qpdf_allow_print_low_res"); return (qpdf->qpdf->allowPrintLowRes() ? QPDF_TRUE : QPDF_FALSE); } QPDF_BOOL qpdf_allow_print_high_res(qpdf_data qpdf) { QTC::TC("qpdf", "qpdf-c called qpdf_allow_print_high_res"); return (qpdf->qpdf->allowPrintHighRes() ? QPDF_TRUE : QPDF_FALSE); } QPDF_BOOL qpdf_allow_modify_assembly(qpdf_data qpdf) { QTC::TC("qpdf", "qpdf-c called qpdf_allow_modify_assembly"); return (qpdf->qpdf->allowModifyAssembly() ? QPDF_TRUE : QPDF_FALSE); } QPDF_BOOL qpdf_allow_modify_form(qpdf_data qpdf) { QTC::TC("qpdf", "qpdf-c called qpdf_allow_modify_form"); return (qpdf->qpdf->allowModifyForm() ? QPDF_TRUE : QPDF_FALSE); } QPDF_BOOL qpdf_allow_modify_annotation(qpdf_data qpdf) { QTC::TC("qpdf", "qpdf-c called qpdf_allow_modify_annotation"); return (qpdf->qpdf->allowModifyAnnotation() ? QPDF_TRUE : QPDF_FALSE); } QPDF_BOOL qpdf_allow_modify_other(qpdf_data qpdf) { QTC::TC("qpdf", "qpdf-c called qpdf_allow_modify_other"); return (qpdf->qpdf->allowModifyOther() ? QPDF_TRUE : QPDF_FALSE); } QPDF_BOOL qpdf_allow_modify_all(qpdf_data qpdf) { QTC::TC("qpdf", "qpdf-c called qpdf_allow_modify_all"); return (qpdf->qpdf->allowModifyAll() ? QPDF_TRUE : QPDF_FALSE); } static void qpdf_init_write_internal(qpdf_data qpdf) { if (qpdf->qpdf_writer.get()) { QTC::TC("qpdf", "qpdf-c called qpdf_init_write multiple times"); qpdf->qpdf_writer = nullptr; if (qpdf->output_buffer.get()) { qpdf->output_buffer = nullptr; qpdf->write_memory = false; qpdf->filename = nullptr; } } } QPDF_ERROR_CODE qpdf_init_write(qpdf_data qpdf, char const* filename) { qpdf_init_write_internal(qpdf); qpdf->filename = filename; QPDF_ERROR_CODE status = trap_errors(qpdf, &call_init_write); QTC::TC("qpdf", "qpdf-c called qpdf_init_write", status); return status; } QPDF_ERROR_CODE qpdf_init_write_memory(qpdf_data qpdf) { qpdf_init_write_internal(qpdf); QPDF_ERROR_CODE status = trap_errors(qpdf, &call_init_write_memory); QTC::TC("qpdf", "qpdf-c called qpdf_init_write_memory"); qpdf->write_memory = true; return status; } static void qpdf_get_buffer_internal(qpdf_data qpdf) { if (qpdf->write_memory && (qpdf->output_buffer == nullptr)) { qpdf->output_buffer = qpdf->qpdf_writer->getBufferSharedPointer(); } } size_t qpdf_get_buffer_length(qpdf_data qpdf) { qpdf_get_buffer_internal(qpdf); size_t result = 0; if (qpdf->output_buffer.get()) { result = qpdf->output_buffer->getSize(); } return result; } unsigned char const* qpdf_get_buffer(qpdf_data qpdf) { unsigned char const* result = nullptr; qpdf_get_buffer_internal(qpdf); if (qpdf->output_buffer.get()) { result = qpdf->output_buffer->getBuffer(); } return result; } void qpdf_set_object_stream_mode(qpdf_data qpdf, qpdf_object_stream_e mode) { QTC::TC("qpdf", "qpdf-c called qpdf_set_object_stream_mode"); qpdf->qpdf_writer->setObjectStreamMode(mode); } void qpdf_set_compress_streams(qpdf_data qpdf, QPDF_BOOL value) { QTC::TC("qpdf", "qpdf-c called qpdf_set_compress_streams"); qpdf->qpdf_writer->setCompressStreams(value != QPDF_FALSE); } void qpdf_set_decode_level(qpdf_data qpdf, qpdf_stream_decode_level_e level) { QTC::TC("qpdf", "qpdf-c called qpdf_set_decode_level"); qpdf->qpdf_writer->setDecodeLevel(level); } void qpdf_set_preserve_unreferenced_objects(qpdf_data qpdf, QPDF_BOOL value) { QTC::TC("qpdf", "qpdf-c called qpdf_set_preserve_unreferenced_objects"); qpdf->qpdf_writer->setPreserveUnreferencedObjects(value != QPDF_FALSE); } void qpdf_set_newline_before_endstream(qpdf_data qpdf, QPDF_BOOL value) { QTC::TC("qpdf", "qpdf-c called qpdf_set_newline_before_endstream"); qpdf->qpdf_writer->setNewlineBeforeEndstream(value != QPDF_FALSE); } void qpdf_set_stream_data_mode(qpdf_data qpdf, qpdf_stream_data_e mode) { QTC::TC("qpdf", "qpdf-c called qpdf_set_stream_data_mode"); qpdf->qpdf_writer->setStreamDataMode(mode); } void qpdf_set_content_normalization(qpdf_data qpdf, QPDF_BOOL value) { QTC::TC("qpdf", "qpdf-c called qpdf_set_content_normalization"); qpdf->qpdf_writer->setContentNormalization(value != QPDF_FALSE); } void qpdf_set_qdf_mode(qpdf_data qpdf, QPDF_BOOL value) { QTC::TC("qpdf", "qpdf-c called qpdf_set_qdf_mode"); qpdf->qpdf_writer->setQDFMode(value != QPDF_FALSE); } void qpdf_set_deterministic_ID(qpdf_data qpdf, QPDF_BOOL value) { QTC::TC("qpdf", "qpdf-c called qpdf_set_deterministic_ID"); qpdf->qpdf_writer->setDeterministicID(value != QPDF_FALSE); } void qpdf_set_static_ID(qpdf_data qpdf, QPDF_BOOL value) { QTC::TC("qpdf", "qpdf-c called qpdf_set_static_ID"); qpdf->qpdf_writer->setStaticID(value != QPDF_FALSE); } void qpdf_set_static_aes_IV(qpdf_data qpdf, QPDF_BOOL value) { QTC::TC("qpdf", "qpdf-c called qpdf_set_static_aes_IV"); qpdf->qpdf_writer->setStaticAesIV(value != QPDF_FALSE); } void qpdf_set_suppress_original_object_IDs(qpdf_data qpdf, QPDF_BOOL value) { QTC::TC("qpdf", "qpdf-c called qpdf_set_suppress_original_object_IDs"); qpdf->qpdf_writer->setSuppressOriginalObjectIDs(value != QPDF_FALSE); } void qpdf_set_preserve_encryption(qpdf_data qpdf, QPDF_BOOL value) { QTC::TC("qpdf", "qpdf-c called qpdf_set_preserve_encryption"); qpdf->qpdf_writer->setPreserveEncryption(value != QPDF_FALSE); } void qpdf_set_r2_encryption_parameters_insecure( qpdf_data qpdf, char const* user_password, char const* owner_password, QPDF_BOOL allow_print, QPDF_BOOL allow_modify, QPDF_BOOL allow_extract, QPDF_BOOL allow_annotate) { QTC::TC("qpdf", "qpdf-c called qpdf_set_r2_encryption_parameters_insecure"); qpdf->qpdf_writer->setR2EncryptionParametersInsecure( user_password, owner_password, allow_print != QPDF_FALSE, allow_modify != QPDF_FALSE, allow_extract != QPDF_FALSE, allow_annotate != QPDF_FALSE); } void qpdf_set_r3_encryption_parameters_insecure( qpdf_data qpdf, char const* user_password, char const* owner_password, QPDF_BOOL allow_accessibility, QPDF_BOOL allow_extract, QPDF_BOOL allow_assemble, QPDF_BOOL allow_annotate_and_form, QPDF_BOOL allow_form_filling, QPDF_BOOL allow_modify_other, enum qpdf_r3_print_e print) { QTC::TC("qpdf", "qpdf-c called qpdf_set_r3_encryption_parameters_insecure"); qpdf->qpdf_writer->setR3EncryptionParametersInsecure( user_password, owner_password, allow_accessibility != QPDF_FALSE, allow_extract != QPDF_FALSE, allow_assemble != QPDF_FALSE, allow_annotate_and_form != QPDF_FALSE, allow_form_filling != QPDF_FALSE, allow_modify_other != QPDF_FALSE, print); } void qpdf_set_r4_encryption_parameters_insecure( qpdf_data qpdf, char const* user_password, char const* owner_password, QPDF_BOOL allow_accessibility, QPDF_BOOL allow_extract, QPDF_BOOL allow_assemble, QPDF_BOOL allow_annotate_and_form, QPDF_BOOL allow_form_filling, QPDF_BOOL allow_modify_other, enum qpdf_r3_print_e print, QPDF_BOOL encrypt_metadata, QPDF_BOOL use_aes) { QTC::TC("qpdf", "qpdf-c called qpdf_set_r4_encryption_parameters_insecure"); qpdf->qpdf_writer->setR4EncryptionParametersInsecure( user_password, owner_password, allow_accessibility != QPDF_FALSE, allow_extract != QPDF_FALSE, allow_assemble != QPDF_FALSE, allow_annotate_and_form != QPDF_FALSE, allow_form_filling != QPDF_FALSE, allow_modify_other != QPDF_FALSE, print, encrypt_metadata != QPDF_FALSE, use_aes != QPDF_FALSE); } void qpdf_set_r5_encryption_parameters2( qpdf_data qpdf, char const* user_password, char const* owner_password, QPDF_BOOL allow_accessibility, QPDF_BOOL allow_extract, QPDF_BOOL allow_assemble, QPDF_BOOL allow_annotate_and_form, QPDF_BOOL allow_form_filling, QPDF_BOOL allow_modify_other, enum qpdf_r3_print_e print, QPDF_BOOL encrypt_metadata) { QTC::TC("qpdf", "qpdf-c called qpdf_set_r5_encryption_parameters"); qpdf->qpdf_writer->setR5EncryptionParameters( user_password, owner_password, allow_accessibility != QPDF_FALSE, allow_extract != QPDF_FALSE, allow_assemble != QPDF_FALSE, allow_annotate_and_form != QPDF_FALSE, allow_form_filling != QPDF_FALSE, allow_modify_other != QPDF_FALSE, print, encrypt_metadata != QPDF_FALSE); } void qpdf_set_r6_encryption_parameters2( qpdf_data qpdf, char const* user_password, char const* owner_password, QPDF_BOOL allow_accessibility, QPDF_BOOL allow_extract, QPDF_BOOL allow_assemble, QPDF_BOOL allow_annotate_and_form, QPDF_BOOL allow_form_filling, QPDF_BOOL allow_modify_other, enum qpdf_r3_print_e print, QPDF_BOOL encrypt_metadata) { QTC::TC("qpdf", "qpdf-c called qpdf_set_r6_encryption_parameters"); qpdf->qpdf_writer->setR6EncryptionParameters( user_password, owner_password, allow_accessibility != QPDF_FALSE, allow_extract != QPDF_FALSE, allow_assemble != QPDF_FALSE, allow_annotate_and_form != QPDF_FALSE, allow_form_filling != QPDF_FALSE, allow_modify_other != QPDF_FALSE, print, encrypt_metadata != QPDF_FALSE); } void qpdf_set_linearization(qpdf_data qpdf, QPDF_BOOL value) { QTC::TC("qpdf", "qpdf-c called qpdf_set_linearization"); qpdf->qpdf_writer->setLinearization(value != QPDF_FALSE); } void qpdf_set_minimum_pdf_version(qpdf_data qpdf, char const* version) { qpdf_set_minimum_pdf_version_and_extension(qpdf, version, 0); } void qpdf_set_minimum_pdf_version_and_extension(qpdf_data qpdf, char const* version, int extension_level) { QTC::TC("qpdf", "qpdf-c called qpdf_set_minimum_pdf_version"); qpdf->qpdf_writer->setMinimumPDFVersion(version, extension_level); } void qpdf_force_pdf_version(qpdf_data qpdf, char const* version) { qpdf_force_pdf_version_and_extension(qpdf, version, 0); } void qpdf_force_pdf_version_and_extension(qpdf_data qpdf, char const* version, int extension_level) { QTC::TC("qpdf", "qpdf-c called qpdf_force_pdf_version"); qpdf->qpdf_writer->forcePDFVersion(version, extension_level); } void qpdf_register_progress_reporter( qpdf_data qpdf, void (*report_progress)(int percent, void* data), void* data) { QTC::TC("qpdf", "qpdf-c registered progress reporter"); qpdf->qpdf_writer->registerProgressReporter( std::shared_ptr(new QPDFWriter::FunctionProgressReporter( std::bind(report_progress, std::placeholders::_1, data)))); } QPDF_ERROR_CODE qpdf_write(qpdf_data qpdf) { QPDF_ERROR_CODE status = QPDF_SUCCESS; status = trap_errors(qpdf, &call_write); QTC::TC("qpdf", "qpdf-c called qpdf_write", (status == 0) ? 0 : 1); return status; } void qpdf_silence_errors(qpdf_data qpdf) { QTC::TC("qpdf", "qpdf-c silence oh errors"); qpdf->silence_errors = true; } template static RET trap_oh_errors(qpdf_data qpdf, std::function fallback, std::function fn) { // Note: fallback is a function so we don't have to evaluate it unless needed. This is important // because sometimes the fallback creates an object. RET ret; QPDF_ERROR_CODE status = trap_errors(qpdf, [&ret, fn](qpdf_data q) { ret = fn(q); }); if (status & QPDF_ERRORS) { if (!qpdf->silence_errors) { QTC::TC("qpdf", "qpdf-c warn about oh error", qpdf->oh_error_occurred ? 0 : 1); if (!qpdf->oh_error_occurred) { qpdf->warnings.emplace_back( qpdf_e_internal, qpdf->qpdf->getFilename(), "", 0, "C API function caught an exception that it isn't returning; please point the " "application developer to ERROR HANDLING in qpdf-c.h"); qpdf->oh_error_occurred = true; } *QPDFLogger::defaultLogger()->getError() << qpdf->error->what() << "\n"; } return fallback(); } return ret; } static qpdf_oh new_object(qpdf_data qpdf, QPDFObjectHandle const& qoh) { qpdf_oh oh = ++qpdf->next_oh; // never return 0 qpdf->oh_cache[oh] = std::make_shared(qoh); return oh; } qpdf_oh qpdf_oh_new_object(qpdf_data qpdf, qpdf_oh oh) { QTC::TC("qpdf", "qpdf-c called qpdf_new_object"); return new_object(qpdf, *(qpdf->oh_cache[oh])); } void qpdf_oh_release(qpdf_data qpdf, qpdf_oh oh) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_release"); qpdf->oh_cache.erase(oh); } void qpdf_oh_release_all(qpdf_data qpdf) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_release_all"); qpdf->oh_cache.clear(); } template static std::function return_T(T const& r) { return [&r]() { return r; }; } static QPDF_BOOL return_false() { return QPDF_FALSE; } static std::function return_uninitialized(qpdf_data qpdf) { return [qpdf]() { return qpdf_oh_new_uninitialized(qpdf); }; } static std::function return_null(qpdf_data qpdf) { return [qpdf]() { return qpdf_oh_new_null(qpdf); }; } qpdf_oh qpdf_get_trailer(qpdf_data qpdf) { QTC::TC("qpdf", "qpdf-c called qpdf_get_trailer"); return trap_oh_errors(qpdf, return_uninitialized(qpdf), [](qpdf_data q) { return new_object(q, q->qpdf->getTrailer()); }); } qpdf_oh qpdf_get_root(qpdf_data qpdf) { QTC::TC("qpdf", "qpdf-c called qpdf_get_root"); return trap_oh_errors(qpdf, return_uninitialized(qpdf), [](qpdf_data q) { return new_object(q, q->qpdf->getRoot()); }); } qpdf_oh qpdf_get_object_by_id(qpdf_data qpdf, int objid, int generation) { QTC::TC("qpdf", "qpdf-c called qpdf_get_object_by_id"); return new_object(qpdf, qpdf->qpdf->getObject(objid, generation)); } template static RET do_with_oh( qpdf_data qpdf, qpdf_oh oh, std::function fallback, std::function fn) { return trap_oh_errors(qpdf, fallback, [fn, oh](qpdf_data q) { auto i = q->oh_cache.find(oh); bool result = ((i != q->oh_cache.end()) && (i->second).get()); if (!result) { QTC::TC("qpdf", "qpdf-c invalid object handle"); throw QPDFExc( qpdf_e_internal, q->qpdf->getFilename(), std::string("C API object handle ") + std::to_string(oh), 0, "attempted access to unknown object handle"); } return fn(*(q->oh_cache[oh])); }); } static void do_with_oh_void(qpdf_data qpdf, qpdf_oh oh, std::function fn) { do_with_oh(qpdf, oh, return_T(false), [fn](QPDFObjectHandle& o) { fn(o); return true; // unused }); } void qpdf_replace_object(qpdf_data qpdf, int objid, int generation, qpdf_oh oh) { do_with_oh_void(qpdf, oh, [qpdf, objid, generation](QPDFObjectHandle& o) { QTC::TC("qpdf", "qpdf-c called qpdf_replace_object"); qpdf->qpdf->replaceObject(objid, generation, o); }); } QPDF_BOOL qpdf_oh_is_initialized(qpdf_data qpdf, qpdf_oh oh) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_is_initialized"); return do_with_oh( qpdf, oh, return_false, [](QPDFObjectHandle& o) { return static_cast(o); }); } QPDF_BOOL qpdf_oh_is_bool(qpdf_data qpdf, qpdf_oh oh) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_is_bool"); return do_with_oh( qpdf, oh, return_false, [](QPDFObjectHandle& o) { return o.isBool(); }); } QPDF_BOOL qpdf_oh_is_null(qpdf_data qpdf, qpdf_oh oh) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_is_null"); return do_with_oh( qpdf, oh, return_false, [](QPDFObjectHandle& o) { return o.isNull(); }); } QPDF_BOOL qpdf_oh_is_integer(qpdf_data qpdf, qpdf_oh oh) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_is_integer"); return do_with_oh( qpdf, oh, return_false, [](QPDFObjectHandle& o) { return o.isInteger(); }); } QPDF_BOOL qpdf_oh_is_real(qpdf_data qpdf, qpdf_oh oh) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_is_real"); return do_with_oh( qpdf, oh, return_false, [](QPDFObjectHandle& o) { return o.isReal(); }); } QPDF_BOOL qpdf_oh_is_name(qpdf_data qpdf, qpdf_oh oh) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_is_name"); return do_with_oh( qpdf, oh, return_false, [](QPDFObjectHandle& o) { return o.isName(); }); } QPDF_BOOL qpdf_oh_is_string(qpdf_data qpdf, qpdf_oh oh) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_is_string"); return do_with_oh( qpdf, oh, return_false, [](QPDFObjectHandle& o) { return o.isString(); }); } QPDF_BOOL qpdf_oh_is_operator(qpdf_data qpdf, qpdf_oh oh) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_is_operator"); return do_with_oh( qpdf, oh, return_false, [](QPDFObjectHandle& o) { return o.isOperator(); }); } QPDF_BOOL qpdf_oh_is_inline_image(qpdf_data qpdf, qpdf_oh oh) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_is_inline_image"); return do_with_oh( qpdf, oh, return_false, [](QPDFObjectHandle& o) { return o.isInlineImage(); }); } QPDF_BOOL qpdf_oh_is_array(qpdf_data qpdf, qpdf_oh oh) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_is_array"); return do_with_oh( qpdf, oh, return_false, [](QPDFObjectHandle& o) { return o.isArray(); }); } QPDF_BOOL qpdf_oh_is_dictionary(qpdf_data qpdf, qpdf_oh oh) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_is_dictionary"); return do_with_oh( qpdf, oh, return_false, [](QPDFObjectHandle& o) { return o.isDictionary(); }); } QPDF_BOOL qpdf_oh_is_stream(qpdf_data qpdf, qpdf_oh oh) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_is_stream"); return do_with_oh( qpdf, oh, return_false, [](QPDFObjectHandle& o) { return o.isStream(); }); } QPDF_BOOL qpdf_oh_is_indirect(qpdf_data qpdf, qpdf_oh oh) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_is_indirect"); return do_with_oh( qpdf, oh, return_false, [](QPDFObjectHandle& o) { return o.isIndirect(); }); } QPDF_BOOL qpdf_oh_is_scalar(qpdf_data qpdf, qpdf_oh oh) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_is_scalar"); return do_with_oh( qpdf, oh, return_false, [](QPDFObjectHandle& o) { return o.isScalar(); }); } QPDF_BOOL qpdf_oh_is_number(qpdf_data qpdf, qpdf_oh oh) { return do_with_oh(qpdf, oh, return_false, [](QPDFObjectHandle& o) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_is_number"); return o.isNumber(); }); } QPDF_BOOL qpdf_oh_is_name_and_equals(qpdf_data qpdf, qpdf_oh oh, char const* name) { return do_with_oh(qpdf, oh, return_false, [name](QPDFObjectHandle& o) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_is_name_and_equals"); return o.isNameAndEquals(name); }); } QPDF_BOOL qpdf_oh_is_dictionary_of_type(qpdf_data qpdf, qpdf_oh oh, char const* type, char const* subtype) { auto stype = (subtype == nullptr) ? "" : subtype; return do_with_oh(qpdf, oh, return_false, [type, stype](QPDFObjectHandle& o) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_is_dictionary_of_type"); return o.isDictionaryOfType(type, stype); }); } qpdf_object_type_e qpdf_oh_get_type_code(qpdf_data qpdf, qpdf_oh oh) { return do_with_oh( qpdf, oh, return_T(ot_uninitialized), [](QPDFObjectHandle& o) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_get_type_code"); return o.getTypeCode(); }); } char const* qpdf_oh_get_type_name(qpdf_data qpdf, qpdf_oh oh) { return do_with_oh( qpdf, oh, return_T(""), [qpdf](QPDFObjectHandle& o) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_get_type_name"); qpdf->tmp_string = o.getTypeName(); return qpdf->tmp_string.c_str(); }); } qpdf_oh qpdf_oh_wrap_in_array(qpdf_data qpdf, qpdf_oh oh) { return do_with_oh( qpdf, oh, [qpdf]() { return qpdf_oh_new_array(qpdf); }, [qpdf](QPDFObjectHandle& qoh) { if (qoh.isArray()) { QTC::TC("qpdf", "qpdf-c array to wrap_in_array"); return new_object(qpdf, qoh); } else { QTC::TC("qpdf", "qpdf-c non-array to wrap_in_array"); return new_object( qpdf, QPDFObjectHandle::newArray(std::vector{qoh})); } }); } qpdf_oh qpdf_oh_parse(qpdf_data qpdf, char const* object_str) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_parse"); return trap_oh_errors(qpdf, return_uninitialized(qpdf), [object_str](qpdf_data q) { return new_object(q, QPDFObjectHandle::parse(object_str)); }); } QPDF_BOOL qpdf_oh_get_bool_value(qpdf_data qpdf, qpdf_oh oh) { return do_with_oh(qpdf, oh, return_false, [](QPDFObjectHandle& o) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_get_bool_value"); return o.getBoolValue(); }); } QPDF_BOOL qpdf_oh_get_value_as_bool(qpdf_data qpdf, qpdf_oh oh, QPDF_BOOL* value) { return do_with_oh(qpdf, oh, return_false, [value](QPDFObjectHandle& o) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_get_value_as_bool"); bool v = *value; QPDF_BOOL result = o.getValueAsBool(v); if (result) { *value = v; } return result; }); } long long qpdf_oh_get_int_value(qpdf_data qpdf, qpdf_oh oh) { return do_with_oh(qpdf, oh, return_T(0LL), [](QPDFObjectHandle& o) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_get_int_value"); return o.getIntValue(); }); } QPDF_BOOL qpdf_oh_get_value_as_longlong(qpdf_data qpdf, qpdf_oh oh, long long* value) { return do_with_oh(qpdf, oh, return_false, [value](QPDFObjectHandle& o) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_get_value_as_longlong"); return o.getValueAsInt(*value); }); } int qpdf_oh_get_int_value_as_int(qpdf_data qpdf, qpdf_oh oh) { return do_with_oh(qpdf, oh, return_T(0), [](QPDFObjectHandle& o) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_get_int_value_as_int"); return o.getIntValueAsInt(); }); } QPDF_BOOL qpdf_oh_get_value_as_int(qpdf_data qpdf, qpdf_oh oh, int* value) { return do_with_oh(qpdf, oh, return_false, [value](QPDFObjectHandle& o) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_get_value_as_int"); return o.getValueAsInt(*value); }); } unsigned long long qpdf_oh_get_uint_value(qpdf_data qpdf, qpdf_oh oh) { return do_with_oh( qpdf, oh, return_T(0ULL), [](QPDFObjectHandle& o) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_get_uint_value"); return o.getUIntValue(); }); } QPDF_BOOL qpdf_oh_get_value_as_ulonglong(qpdf_data qpdf, qpdf_oh oh, unsigned long long* value) { return do_with_oh(qpdf, oh, return_false, [value](QPDFObjectHandle& o) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_get_value_as_ulonglong"); return o.getValueAsUInt(*value); }); } unsigned int qpdf_oh_get_uint_value_as_uint(qpdf_data qpdf, qpdf_oh oh) { return do_with_oh(qpdf, oh, return_T(0U), [](QPDFObjectHandle& o) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_get_uint_value_as_uint"); return o.getUIntValueAsUInt(); }); } QPDF_BOOL qpdf_oh_get_value_as_uint(qpdf_data qpdf, qpdf_oh oh, unsigned int* value) { return do_with_oh(qpdf, oh, return_false, [value](QPDFObjectHandle& o) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_get_value_as_uint"); return o.getValueAsUInt(*value); }); } char const* qpdf_oh_get_real_value(qpdf_data qpdf, qpdf_oh oh) { return do_with_oh( qpdf, oh, return_T(""), [qpdf](QPDFObjectHandle& o) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_get_real_value"); qpdf->tmp_string = o.getRealValue(); return qpdf->tmp_string.c_str(); }); } QPDF_BOOL qpdf_oh_get_value_as_real(qpdf_data qpdf, qpdf_oh oh, char const** value, size_t* length) { return do_with_oh( qpdf, oh, return_false, [qpdf, value, length](QPDFObjectHandle& o) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_get_value_as_real"); auto result = o.getValueAsReal(qpdf->tmp_string); if (result) { *value = qpdf->tmp_string.c_str(); *length = qpdf->tmp_string.length(); } return result; }); } double qpdf_oh_get_numeric_value(qpdf_data qpdf, qpdf_oh oh) { return do_with_oh(qpdf, oh, return_T(0.0), [](QPDFObjectHandle& o) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_get_numeric_value"); return o.getNumericValue(); }); } QPDF_BOOL qpdf_oh_get_value_as_number(qpdf_data qpdf, qpdf_oh oh, double* value) { return do_with_oh(qpdf, oh, return_false, [value](QPDFObjectHandle& o) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_get_value_as_number"); return o.getValueAsNumber(*value); }); } char const* qpdf_oh_get_name(qpdf_data qpdf, qpdf_oh oh) { return do_with_oh( qpdf, oh, return_T(""), [qpdf](QPDFObjectHandle& o) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_get_name"); qpdf->tmp_string = o.getName(); return qpdf->tmp_string.c_str(); }); } QPDF_BOOL qpdf_oh_get_value_as_name(qpdf_data qpdf, qpdf_oh oh, char const** value, size_t* length) { return do_with_oh( qpdf, oh, return_false, [qpdf, value, length](QPDFObjectHandle& o) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_get_value_as_name"); auto result = o.getValueAsName(qpdf->tmp_string); if (result) { *value = qpdf->tmp_string.c_str(); *length = qpdf->tmp_string.length(); } return result; }); } char const* qpdf_oh_get_string_value(qpdf_data qpdf, qpdf_oh oh) { return do_with_oh( qpdf, oh, return_T(""), [qpdf](QPDFObjectHandle& o) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_get_string_value"); qpdf->tmp_string = o.getStringValue(); return qpdf->tmp_string.c_str(); }); } QPDF_BOOL qpdf_oh_get_value_as_string(qpdf_data qpdf, qpdf_oh oh, char const** value, size_t* length) { return do_with_oh( qpdf, oh, return_false, [qpdf, value, length](QPDFObjectHandle& o) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_get_value_as_string"); auto result = o.getValueAsString(qpdf->tmp_string); if (result) { *value = qpdf->tmp_string.c_str(); *length = qpdf->tmp_string.length(); } return result; }); } char const* qpdf_oh_get_utf8_value(qpdf_data qpdf, qpdf_oh oh) { return do_with_oh( qpdf, oh, return_T(""), [qpdf](QPDFObjectHandle& o) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_get_utf8_value"); qpdf->tmp_string = o.getUTF8Value(); return qpdf->tmp_string.c_str(); }); } QPDF_BOOL qpdf_oh_get_value_as_utf8(qpdf_data qpdf, qpdf_oh oh, char const** value, size_t* length) { return do_with_oh( qpdf, oh, return_false, [qpdf, value, length](QPDFObjectHandle& o) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_get_value_as_utf8"); auto result = o.getValueAsUTF8(qpdf->tmp_string); if (result) { *value = qpdf->tmp_string.c_str(); *length = qpdf->tmp_string.length(); } return result; }); } char const* qpdf_oh_get_binary_string_value(qpdf_data qpdf, qpdf_oh oh, size_t* length) { return do_with_oh( qpdf, oh, return_T(""), [qpdf, length](QPDFObjectHandle& o) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_get_binary_string_value"); qpdf->tmp_string = o.getStringValue(); *length = qpdf->tmp_string.length(); return qpdf->tmp_string.c_str(); }); } char const* qpdf_oh_get_binary_utf8_value(qpdf_data qpdf, qpdf_oh oh, size_t* length) { return do_with_oh( qpdf, oh, return_T(""), [qpdf, length](QPDFObjectHandle& o) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_get_binary_utf8_value"); qpdf->tmp_string = o.getUTF8Value(); *length = qpdf->tmp_string.length(); return qpdf->tmp_string.c_str(); }); } int qpdf_oh_get_array_n_items(qpdf_data qpdf, qpdf_oh oh) { return do_with_oh(qpdf, oh, return_T(0), [](QPDFObjectHandle& o) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_get_array_n_items"); return o.getArrayNItems(); }); } qpdf_oh qpdf_oh_get_array_item(qpdf_data qpdf, qpdf_oh oh, int n) { return do_with_oh(qpdf, oh, return_null(qpdf), [qpdf, n](QPDFObjectHandle& o) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_get_array_item"); return new_object(qpdf, o.getArrayItem(n)); }); } void qpdf_oh_begin_dict_key_iter(qpdf_data qpdf, qpdf_oh oh) { qpdf->cur_iter_dict_keys = do_with_oh>( qpdf, oh, []() { return std::set(); }, [](QPDFObjectHandle& o) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_begin_dict_key_iter"); return o.getKeys(); }); qpdf->dict_iter = qpdf->cur_iter_dict_keys.begin(); } QPDF_BOOL qpdf_oh_dict_more_keys(qpdf_data qpdf) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_dict_more_keys"); return qpdf->dict_iter != qpdf->cur_iter_dict_keys.end(); } char const* qpdf_oh_dict_next_key(qpdf_data qpdf) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_dict_next_key"); if (qpdf_oh_dict_more_keys(qpdf)) { qpdf->cur_dict_key = *qpdf->dict_iter; ++qpdf->dict_iter; return qpdf->cur_dict_key.c_str(); } else { return nullptr; } } QPDF_BOOL qpdf_oh_has_key(qpdf_data qpdf, qpdf_oh oh, char const* key) { return do_with_oh(qpdf, oh, return_false, [key](QPDFObjectHandle& o) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_has_key"); return o.hasKey(key); }); } qpdf_oh qpdf_oh_get_key(qpdf_data qpdf, qpdf_oh oh, char const* key) { return do_with_oh(qpdf, oh, return_null(qpdf), [qpdf, key](QPDFObjectHandle& o) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_get_key"); return new_object(qpdf, o.getKey(key)); }); } qpdf_oh qpdf_oh_get_key_if_dict(qpdf_data qpdf, qpdf_oh oh, char const* key) { return do_with_oh(qpdf, oh, return_null(qpdf), [qpdf, key](QPDFObjectHandle& o) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_get_key_if_dict"); return new_object(qpdf, o.getKeyIfDict(key)); }); } QPDF_BOOL qpdf_oh_is_or_has_name(qpdf_data qpdf, qpdf_oh oh, char const* key) { return do_with_oh(qpdf, oh, return_false, [key](QPDFObjectHandle& o) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_is_or_has_name"); return o.isOrHasName(key); }); } qpdf_oh qpdf_oh_new_uninitialized(qpdf_data qpdf) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_new_uninitialized"); return new_object(qpdf, QPDFObjectHandle()); } qpdf_oh qpdf_oh_new_null(qpdf_data qpdf) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_new_null"); return new_object(qpdf, QPDFObjectHandle::newNull()); } qpdf_oh qpdf_oh_new_bool(qpdf_data qpdf, QPDF_BOOL value) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_new_bool"); return new_object(qpdf, QPDFObjectHandle::newBool(value)); } qpdf_oh qpdf_oh_new_integer(qpdf_data qpdf, long long value) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_new_integer"); return new_object(qpdf, QPDFObjectHandle::newInteger(value)); } qpdf_oh qpdf_oh_new_real_from_string(qpdf_data qpdf, char const* value) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_new_real_from_string"); return new_object(qpdf, QPDFObjectHandle::newReal(value)); } qpdf_oh qpdf_oh_new_real_from_double(qpdf_data qpdf, double value, int decimal_places) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_new_real_from_double"); return new_object(qpdf, QPDFObjectHandle::newReal(value, decimal_places)); } qpdf_oh qpdf_oh_new_name(qpdf_data qpdf, char const* name) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_new_name"); return new_object(qpdf, QPDFObjectHandle::newName(name)); } qpdf_oh qpdf_oh_new_string(qpdf_data qpdf, char const* str) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_new_string"); return new_object(qpdf, QPDFObjectHandle::newString(str)); } qpdf_oh qpdf_oh_new_unicode_string(qpdf_data qpdf, char const* utf8_str) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_new_unicode_string"); return new_object(qpdf, QPDFObjectHandle::newUnicodeString(utf8_str)); } qpdf_oh qpdf_oh_new_binary_string(qpdf_data qpdf, char const* str, size_t length) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_new_binary_string"); return new_object(qpdf, QPDFObjectHandle::newString(std::string(str, length))); } qpdf_oh qpdf_oh_new_binary_unicode_string(qpdf_data qpdf, char const* utf8_str, size_t length) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_new_binary_unicode_string"); return new_object(qpdf, QPDFObjectHandle::newUnicodeString(std::string(utf8_str, length))); } qpdf_oh qpdf_oh_new_array(qpdf_data qpdf) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_new_array"); return new_object(qpdf, QPDFObjectHandle::newArray()); } qpdf_oh qpdf_oh_new_dictionary(qpdf_data qpdf) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_new_dictionary"); return new_object(qpdf, QPDFObjectHandle::newDictionary()); } qpdf_oh qpdf_oh_new_stream(qpdf_data qpdf) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_new_stream"); return new_object(qpdf, qpdf->qpdf->newStream()); } void qpdf_oh_make_direct(qpdf_data qpdf, qpdf_oh oh) { do_with_oh_void(qpdf, oh, [](QPDFObjectHandle& o) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_make_direct"); o.makeDirect(); }); } qpdf_oh qpdf_make_indirect_object(qpdf_data qpdf, qpdf_oh oh) { return do_with_oh(qpdf, oh, return_uninitialized(qpdf), [qpdf](QPDFObjectHandle& o) { return new_object(qpdf, qpdf->qpdf->makeIndirectObject(o)); }); } static QPDFObjectHandle qpdf_oh_item_internal(qpdf_data qpdf, qpdf_oh item) { return do_with_oh( qpdf, item, []() { return QPDFObjectHandle::newNull(); }, [](QPDFObjectHandle& o) { return o; }); } void qpdf_oh_set_array_item(qpdf_data qpdf, qpdf_oh oh, int at, qpdf_oh item) { do_with_oh_void(qpdf, oh, [qpdf, at, item](QPDFObjectHandle& o) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_set_array_item"); o.setArrayItem(at, qpdf_oh_item_internal(qpdf, item)); }); } void qpdf_oh_insert_item(qpdf_data qpdf, qpdf_oh oh, int at, qpdf_oh item) { do_with_oh_void(qpdf, oh, [qpdf, at, item](QPDFObjectHandle& o) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_insert_item"); o.insertItem(at, qpdf_oh_item_internal(qpdf, item)); }); } void qpdf_oh_append_item(qpdf_data qpdf, qpdf_oh oh, qpdf_oh item) { do_with_oh_void(qpdf, oh, [qpdf, item](QPDFObjectHandle& o) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_append_item"); o.appendItem(qpdf_oh_item_internal(qpdf, item)); }); } void qpdf_oh_erase_item(qpdf_data qpdf, qpdf_oh oh, int at) { do_with_oh_void(qpdf, oh, [at](QPDFObjectHandle& o) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_erase_item"); o.eraseItem(at); }); } void qpdf_oh_replace_key(qpdf_data qpdf, qpdf_oh oh, char const* key, qpdf_oh item) { do_with_oh_void(qpdf, oh, [qpdf, key, item](QPDFObjectHandle& o) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_replace_key"); o.replaceKey(key, qpdf_oh_item_internal(qpdf, item)); }); } void qpdf_oh_remove_key(qpdf_data qpdf, qpdf_oh oh, char const* key) { do_with_oh_void(qpdf, oh, [key](QPDFObjectHandle& o) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_remove_key"); o.removeKey(key); }); } void qpdf_oh_replace_or_remove_key(qpdf_data qpdf, qpdf_oh oh, char const* key, qpdf_oh item) { do_with_oh_void(qpdf, oh, [qpdf, key, item](QPDFObjectHandle& o) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_replace_or_remove_key"); o.replaceKey(key, qpdf_oh_item_internal(qpdf, item)); }); } qpdf_oh qpdf_oh_get_dict(qpdf_data qpdf, qpdf_oh oh) { return do_with_oh(qpdf, oh, return_null(qpdf), [qpdf](QPDFObjectHandle& o) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_get_dict"); return new_object(qpdf, o.getDict()); }); } int qpdf_oh_get_object_id(qpdf_data qpdf, qpdf_oh oh) { return do_with_oh(qpdf, oh, return_T(0), [](QPDFObjectHandle& o) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_get_object_id"); return o.getObjectID(); }); } int qpdf_oh_get_generation(qpdf_data qpdf, qpdf_oh oh) { return do_with_oh(qpdf, oh, return_T(0), [](QPDFObjectHandle& o) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_get_generation"); return o.getGeneration(); }); } char const* qpdf_oh_unparse(qpdf_data qpdf, qpdf_oh oh) { return do_with_oh( qpdf, oh, return_T(""), [qpdf](QPDFObjectHandle& o) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_unparse"); qpdf->tmp_string = o.unparse(); return qpdf->tmp_string.c_str(); }); } char const* qpdf_oh_unparse_resolved(qpdf_data qpdf, qpdf_oh oh) { return do_with_oh( qpdf, oh, return_T(""), [qpdf](QPDFObjectHandle& o) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_unparse_resolved"); qpdf->tmp_string = o.unparseResolved(); return qpdf->tmp_string.c_str(); }); } char const* qpdf_oh_unparse_binary(qpdf_data qpdf, qpdf_oh oh) { return do_with_oh( qpdf, oh, return_T(""), [qpdf](QPDFObjectHandle& o) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_unparse_binary"); qpdf->tmp_string = o.unparseBinary(); return qpdf->tmp_string.c_str(); }); } qpdf_oh qpdf_oh_copy_foreign_object(qpdf_data qpdf, qpdf_data other_qpdf, qpdf_oh foreign_oh) { return do_with_oh( other_qpdf, foreign_oh, return_uninitialized(qpdf), [qpdf](QPDFObjectHandle& o) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_copy_foreign_object"); return new_object(qpdf, qpdf->qpdf->copyForeignObject(o)); }); } QPDF_ERROR_CODE qpdf_oh_get_stream_data( qpdf_data qpdf, qpdf_oh stream_oh, qpdf_stream_decode_level_e decode_level, QPDF_BOOL* filtered, unsigned char** bufp, size_t* len) { return trap_errors(qpdf, [stream_oh, decode_level, filtered, bufp, len](qpdf_data q) { auto stream = qpdf_oh_item_internal(q, stream_oh); Pipeline* p = nullptr; Pl_Buffer buf("stream data"); if (bufp) { p = &buf; } bool was_filtered = false; if (stream.pipeStreamData(p, &was_filtered, 0, decode_level, false, false)) { QTC::TC("qpdf", "qpdf-c stream data buf set", bufp ? 0 : 1); if (p && bufp && len) { buf.getMallocBuffer(bufp, len); } QTC::TC("qpdf", "qpdf-c stream data filtered set", filtered ? 0 : 1); if (filtered) { *filtered = was_filtered ? QPDF_TRUE : QPDF_FALSE; } } else { throw std::runtime_error("unable to access stream data for stream " + stream.unparse()); } }); } QPDF_ERROR_CODE qpdf_oh_get_page_content_data(qpdf_data qpdf, qpdf_oh page_oh, unsigned char** bufp, size_t* len) { return trap_errors(qpdf, [page_oh, bufp, len](qpdf_data q) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_get_page_content_data"); auto o = qpdf_oh_item_internal(q, page_oh); Pl_Buffer buf("page contents"); o.pipePageContents(&buf); buf.getMallocBuffer(bufp, len); }); } void qpdf_oh_free_buffer(unsigned char** bufp) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_free_buffer"); if (bufp && *bufp) { free(*bufp); *bufp = nullptr; } } void qpdf_oh_replace_stream_data( qpdf_data qpdf, qpdf_oh stream_oh, unsigned char const* buf, size_t len, qpdf_oh filter_oh, qpdf_oh decode_parms_oh) { do_with_oh_void( qpdf, stream_oh, [qpdf, buf, len, filter_oh, decode_parms_oh](QPDFObjectHandle& o) { QTC::TC("qpdf", "qpdf-c called qpdf_oh_replace_stream_data"); auto filter = qpdf_oh_item_internal(qpdf, filter_oh); auto decode_parms = qpdf_oh_item_internal(qpdf, decode_parms_oh); // XXX test with binary data with null o.replaceStreamData( std::string(reinterpret_cast(buf), len), filter, decode_parms); }); } int qpdf_get_num_pages(qpdf_data qpdf) { QTC::TC("qpdf", "qpdf-c called qpdf_num_pages"); int n = -1; QPDF_ERROR_CODE code = trap_errors(qpdf, [&n](qpdf_data q) { n = QIntC::to_int(q->qpdf->getAllPages().size()); }); if (code & QPDF_ERRORS) { return -1; } return n; } qpdf_oh qpdf_get_page_n(qpdf_data qpdf, size_t i) { QTC::TC("qpdf", "qpdf-c called qpdf_get_page_n"); qpdf_oh result = 0; QPDF_ERROR_CODE code = trap_errors( qpdf, [&result, i](qpdf_data q) { result = new_object(q, q->qpdf->getAllPages().at(i)); }); if ((code & QPDF_ERRORS) || (result == 0)) { return qpdf_oh_new_uninitialized(qpdf); } return result; } QPDF_ERROR_CODE qpdf_update_all_pages_cache(qpdf_data qpdf) { QTC::TC("qpdf", "qpdf-c called qpdf_update_all_pages_cache"); return trap_errors(qpdf, [](qpdf_data q) { q->qpdf->updateAllPagesCache(); }); } int qpdf_find_page_by_id(qpdf_data qpdf, int objid, int generation) { QTC::TC("qpdf", "qpdf-c called qpdf_find_page_by_id"); int n = -1; QPDFObjGen og(objid, generation); QPDF_ERROR_CODE code = trap_errors(qpdf, [&n, &og](qpdf_data q) { n = QIntC::to_int(q->qpdf->findPage(og)); }); if (code & QPDF_ERRORS) { return -1; } return n; } int qpdf_find_page_by_oh(qpdf_data qpdf, qpdf_oh oh) { QTC::TC("qpdf", "qpdf-c called qpdf_find_page_by_oh"); return do_with_oh(qpdf, oh, return_T(-1), [qpdf](QPDFObjectHandle& o) { return qpdf->qpdf->findPage(o); }); } QPDF_ERROR_CODE qpdf_push_inherited_attributes_to_page(qpdf_data qpdf) { QTC::TC("qpdf", "qpdf-c called qpdf_push_inherited_attributes_to_page"); return trap_errors(qpdf, [](qpdf_data q) { q->qpdf->pushInheritedAttributesToPage(); }); } QPDF_ERROR_CODE qpdf_add_page(qpdf_data qpdf, qpdf_data newpage_qpdf, qpdf_oh newpage, QPDF_BOOL first) { QTC::TC("qpdf", "qpdf-c called qpdf_add_page"); auto page = qpdf_oh_item_internal(newpage_qpdf, newpage); return trap_errors(qpdf, [&page, first](qpdf_data q) { q->qpdf->addPage(page, first); }); } QPDF_ERROR_CODE qpdf_add_page_at( qpdf_data qpdf, qpdf_data newpage_qpdf, qpdf_oh newpage, QPDF_BOOL before, qpdf_oh refpage) { QTC::TC("qpdf", "qpdf-c called qpdf_add_page_at"); auto page = qpdf_oh_item_internal(newpage_qpdf, newpage); auto ref = qpdf_oh_item_internal(qpdf, refpage); return trap_errors( qpdf, [&page, before, &ref](qpdf_data q) { q->qpdf->addPageAt(page, before, ref); }); } QPDF_ERROR_CODE qpdf_remove_page(qpdf_data qpdf, qpdf_oh page) { QTC::TC("qpdf", "qpdf-c called qpdf_remove_page"); auto p = qpdf_oh_item_internal(qpdf, page); return trap_errors(qpdf, [&p](qpdf_data q) { q->qpdf->removePage(p); }); } QPDF_ERROR_CODE qpdf_create_from_json_file(qpdf_data qpdf, char const* filename) { QPDF_ERROR_CODE status = QPDF_SUCCESS; qpdf->filename = filename; status = trap_errors(qpdf, [](qpdf_data q) { q->qpdf->createFromJSON(q->filename); }); return status; } QPDF_ERROR_CODE qpdf_create_from_json_data(qpdf_data qpdf, char const* buffer, unsigned long long size) { QPDF_ERROR_CODE status = QPDF_SUCCESS; qpdf->filename = "json buffer"; qpdf->buffer = buffer; qpdf->size = size; auto b = new Buffer(QUtil::unsigned_char_pointer(buffer), QIntC::to_size(size)); auto is = std::make_shared(qpdf->filename, b, true); status = trap_errors(qpdf, [&is](qpdf_data q) { q->qpdf->createFromJSON(is); }); return status; } QPDF_ERROR_CODE qpdf_update_from_json_file(qpdf_data qpdf, char const* filename) { QPDF_ERROR_CODE status = QPDF_SUCCESS; status = trap_errors(qpdf, [filename](qpdf_data q) { q->qpdf->updateFromJSON(filename); }); return status; } QPDF_ERROR_CODE qpdf_update_from_json_data(qpdf_data qpdf, char const* buffer, unsigned long long size) { QPDF_ERROR_CODE status = QPDF_SUCCESS; auto b = new Buffer(QUtil::unsigned_char_pointer(buffer), QIntC::to_size(size)); auto is = std::make_shared(qpdf->filename, b, true); status = trap_errors(qpdf, [&is](qpdf_data q) { q->qpdf->updateFromJSON(is); }); return status; } QPDF_ERROR_CODE qpdf_write_json( qpdf_data qpdf, int version, qpdf_write_fn_t fn, void* udata, enum qpdf_stream_decode_level_e decode_level, enum qpdf_json_stream_data_e json_stream_data, char const* file_prefix, char const* const* wanted_objects) { QPDF_ERROR_CODE status = QPDF_SUCCESS; auto p = std::make_shared("write_json", nullptr, fn, udata); std::set wanted_objects_set; if (wanted_objects) { for (auto i = wanted_objects; *i; ++i) { wanted_objects_set.insert(*i); } } status = trap_errors( qpdf, [version, p, decode_level, json_stream_data, file_prefix, &wanted_objects_set]( qpdf_data q) { q->qpdf->writeJSON( version, p.get(), decode_level, json_stream_data, file_prefix, wanted_objects_set); }); return status; } std::shared_ptr qpdf_c_get_qpdf(qpdf_data qpdf) { return qpdf->qpdf; } QPDF_ERROR_CODE qpdf_c_wrap(qpdf_data qpdf, std::function fn) { return trap_errors(qpdf, [&fn](qpdf_data) { fn(); }); }