1 #include <qpdf/qpdf-c.h>
2 
3 #include <qpdf/QPDF.hh>
4 #include <qpdf/QPDFWriter.hh>
5 #include <qpdf/QTC.hh>
6 #include <qpdf/QPDFExc.hh>
7 #include <qpdf/Pl_Discard.hh>
8 #include <qpdf/Pl_Buffer.hh>
9 #include <qpdf/QIntC.hh>
10 #include <qpdf/QUtil.hh>
11 
12 #include <list>
13 #include <string>
14 #include <stdexcept>
15 #include <cstring>
16 #include <functional>
17 
18 struct _qpdf_error
19 {
20     PointerHolder<QPDFExc> exc;
21 };
22 
23 struct _qpdf_data
24 {
25     _qpdf_data();
26     ~_qpdf_data();
27 
28     PointerHolder<QPDF> qpdf;
29     PointerHolder<QPDFWriter> qpdf_writer;
30 
31     PointerHolder<QPDFExc> error;
32     _qpdf_error tmp_error;
33     std::list<QPDFExc> warnings;
34     std::string tmp_string;
35 
36     // Parameters for functions we call
37     char const* filename;	// or description
38     char const* buffer;
39     unsigned long long size;
40     char const* password;
41     bool write_memory;
42     PointerHolder<Buffer> output_buffer;
43 
44     // QPDFObjectHandle support
45     bool silence_errors;
46     bool oh_error_occurred;
47     std::map<qpdf_oh, PointerHolder<QPDFObjectHandle>> oh_cache;
48     qpdf_oh next_oh;
49     std::set<std::string> cur_iter_dict_keys;
50     std::set<std::string>::const_iterator dict_iter;
51     std::string cur_dict_key;
52 };
53 
_qpdf_data()54 _qpdf_data::_qpdf_data() :
55     write_memory(false),
56     silence_errors(false),
57     oh_error_occurred(false),
58     next_oh(0)
59 {
60 }
61 
~_qpdf_data()62 _qpdf_data::~_qpdf_data()
63 {
64 }
65 
66 class ProgressReporter: public QPDFWriter::ProgressReporter
67 {
68   public:
69     ProgressReporter(void (*handler)(int, void*), void* data);
70     virtual ~ProgressReporter() = default;
71     virtual void reportProgress(int);
72 
73   private:
74     void (*handler)(int, void*);
75     void* data;
76 };
77 
ProgressReporter(void (* handler)(int,void *),void * data)78 ProgressReporter::ProgressReporter(void (*handler)(int, void*), void* data) :
79     handler(handler),
80     data(data)
81 {
82 }
83 
84 void
reportProgress(int progress)85 ProgressReporter::reportProgress(int progress)
86 {
87     this->handler(progress, this->data);
88 }
89 
90 // must set qpdf->filename and qpdf->password
call_read(qpdf_data qpdf)91 static void call_read(qpdf_data qpdf)
92 {
93     qpdf->qpdf->processFile(qpdf->filename, qpdf->password);
94 }
95 
96 // must set qpdf->filename, qpdf->buffer, qpdf->size, and qpdf->password
call_read_memory(qpdf_data qpdf)97 static void call_read_memory(qpdf_data qpdf)
98 {
99     qpdf->qpdf->processMemoryFile(qpdf->filename, qpdf->buffer,
100 				  QIntC::to_size(qpdf->size), qpdf->password);
101 }
102 
103 // must set qpdf->filename
call_init_write(qpdf_data qpdf)104 static void call_init_write(qpdf_data qpdf)
105 {
106     qpdf->qpdf_writer = new QPDFWriter(*(qpdf->qpdf), qpdf->filename);
107 }
108 
call_init_write_memory(qpdf_data qpdf)109 static void call_init_write_memory(qpdf_data qpdf)
110 {
111     qpdf->qpdf_writer = new QPDFWriter(*(qpdf->qpdf));
112     qpdf->qpdf_writer->setOutputMemory();
113 }
114 
call_write(qpdf_data qpdf)115 static void call_write(qpdf_data qpdf)
116 {
117     qpdf->qpdf_writer->write();
118 }
119 
call_check(qpdf_data qpdf)120 static void call_check(qpdf_data qpdf)
121 {
122     QPDFWriter w(*qpdf->qpdf);
123     Pl_Discard discard;
124     w.setOutputPipeline(&discard);
125     w.setDecodeLevel(qpdf_dl_all);
126     w.write();
127 }
128 
trap_errors(qpdf_data qpdf,std::function<void (qpdf_data)> fn)129 static QPDF_ERROR_CODE trap_errors(
130     qpdf_data qpdf, std::function<void(qpdf_data)> fn)
131 {
132     QPDF_ERROR_CODE status = QPDF_SUCCESS;
133     try
134     {
135 	fn(qpdf);
136     }
137     catch (QPDFExc& e)
138     {
139 	qpdf->error = new QPDFExc(e);
140 	status |= QPDF_ERRORS;
141     }
142     catch (std::runtime_error& e)
143     {
144 	qpdf->error = new QPDFExc(qpdf_e_system, "", "", 0, e.what());
145 	status |= QPDF_ERRORS;
146     }
147     catch (std::exception& e)
148     {
149 	qpdf->error = new QPDFExc(qpdf_e_internal, "", "", 0, e.what());
150 	status |= QPDF_ERRORS;
151     }
152 
153     if (qpdf_more_warnings(qpdf))
154     {
155 	status |= QPDF_WARNINGS;
156     }
157     return status;
158 }
159 
qpdf_get_qpdf_version()160 char const* qpdf_get_qpdf_version()
161 {
162     QTC::TC("qpdf", "qpdf-c called qpdf_get_qpdf_version");
163     return QPDF::QPDFVersion().c_str();
164 }
165 
qpdf_init()166 qpdf_data qpdf_init()
167 {
168     QTC::TC("qpdf", "qpdf-c called qpdf_init");
169     qpdf_data qpdf = new _qpdf_data();
170     qpdf->qpdf = new QPDF();
171     return qpdf;
172 }
173 
qpdf_cleanup(qpdf_data * qpdf)174 void qpdf_cleanup(qpdf_data* qpdf)
175 {
176     QTC::TC("qpdf", "qpdf-c called qpdf_cleanup");
177     qpdf_oh_release_all(*qpdf);
178     if ((*qpdf)->error.getPointer())
179     {
180         QTC::TC("qpdf", "qpdf-c cleanup warned about unhandled error");
181         std::cerr << "WARNING: application did not handle error: "
182                   <<  (*qpdf)->error->what() << std::endl;
183 
184     }
185     delete *qpdf;
186     *qpdf = 0;
187 }
188 
qpdf_get_last_string_length(qpdf_data qpdf)189 size_t qpdf_get_last_string_length(qpdf_data qpdf)
190 {
191     return qpdf->tmp_string.length();
192 }
193 
qpdf_more_warnings(qpdf_data qpdf)194 QPDF_BOOL qpdf_more_warnings(qpdf_data qpdf)
195 {
196     QTC::TC("qpdf", "qpdf-c called qpdf_more_warnings");
197 
198     if (qpdf->warnings.empty())
199     {
200 	std::vector<QPDFExc> w = qpdf->qpdf->getWarnings();
201 	if (! w.empty())
202 	{
203 	    qpdf->warnings.assign(w.begin(), w.end());
204 	}
205     }
206     if (qpdf->warnings.empty())
207     {
208 	return QPDF_FALSE;
209     }
210     else
211     {
212 	return QPDF_TRUE;
213     }
214 }
215 
qpdf_has_error(qpdf_data qpdf)216 QPDF_BOOL qpdf_has_error(qpdf_data qpdf)
217 {
218     QTC::TC("qpdf", "qpdf-c called qpdf_has_error");
219     return (qpdf->error.getPointer() ? QPDF_TRUE : QPDF_FALSE);
220 }
221 
qpdf_get_error(qpdf_data qpdf)222 qpdf_error qpdf_get_error(qpdf_data qpdf)
223 {
224     if (qpdf->error.getPointer())
225     {
226 	qpdf->tmp_error.exc = qpdf->error;
227 	qpdf->error = 0;
228 	QTC::TC("qpdf", "qpdf-c qpdf_get_error returned error");
229 	return &qpdf->tmp_error;
230     }
231     else
232     {
233 	return 0;
234     }
235 }
236 
qpdf_next_warning(qpdf_data qpdf)237 qpdf_error qpdf_next_warning(qpdf_data qpdf)
238 {
239     if (qpdf_more_warnings(qpdf))
240     {
241 	qpdf->tmp_error.exc = new QPDFExc(qpdf->warnings.front());
242 	qpdf->warnings.pop_front();
243 	QTC::TC("qpdf", "qpdf-c qpdf_next_warning returned warning");
244 	return &qpdf->tmp_error;
245     }
246     else
247     {
248 	return 0;
249     }
250 }
251 
qpdf_get_error_full_text(qpdf_data qpdf,qpdf_error e)252 char const* qpdf_get_error_full_text(qpdf_data qpdf, qpdf_error e)
253 {
254     if (e == 0)
255     {
256 	return "";
257     }
258     return e->exc->what();
259 }
260 
qpdf_get_error_code(qpdf_data qpdf,qpdf_error e)261 enum qpdf_error_code_e qpdf_get_error_code(qpdf_data qpdf, qpdf_error e)
262 {
263     if (e == 0)
264     {
265 	return qpdf_e_success;
266     }
267     return e->exc->getErrorCode();
268 }
269 
qpdf_get_error_filename(qpdf_data qpdf,qpdf_error e)270 char const* qpdf_get_error_filename(qpdf_data qpdf, qpdf_error e)
271 {
272     if (e == 0)
273     {
274 	return "";
275     }
276     return e->exc->getFilename().c_str();
277 }
278 
qpdf_get_error_file_position(qpdf_data qpdf,qpdf_error e)279 unsigned long long qpdf_get_error_file_position(qpdf_data qpdf, qpdf_error e)
280 {
281     if (e == 0)
282     {
283 	return 0;
284     }
285     return QIntC::to_ulonglong(e->exc->getFilePosition());
286 }
287 
qpdf_get_error_message_detail(qpdf_data qpdf,qpdf_error e)288 char const* qpdf_get_error_message_detail(qpdf_data qpdf, qpdf_error e)
289 {
290     if (e == 0)
291     {
292 	return "";
293     }
294     return e->exc->getMessageDetail().c_str();
295 }
296 
qpdf_check_pdf(qpdf_data qpdf)297 QPDF_ERROR_CODE qpdf_check_pdf(qpdf_data qpdf)
298 {
299     QPDF_ERROR_CODE status = trap_errors(qpdf, &call_check);
300     QTC::TC("qpdf", "qpdf-c called qpdf_check_pdf");
301     return status;
302 }
303 
qpdf_set_suppress_warnings(qpdf_data qpdf,QPDF_BOOL value)304 void qpdf_set_suppress_warnings(qpdf_data qpdf, QPDF_BOOL value)
305 {
306     QTC::TC("qpdf", "qpdf-c called qpdf_set_suppress_warnings");
307     qpdf->qpdf->setSuppressWarnings(value != QPDF_FALSE);
308 }
309 
qpdf_set_ignore_xref_streams(qpdf_data qpdf,QPDF_BOOL value)310 void qpdf_set_ignore_xref_streams(qpdf_data qpdf, QPDF_BOOL value)
311 {
312     QTC::TC("qpdf", "qpdf-c called qpdf_set_ignore_xref_streams");
313     qpdf->qpdf->setIgnoreXRefStreams(value != QPDF_FALSE);
314 }
315 
qpdf_set_attempt_recovery(qpdf_data qpdf,QPDF_BOOL value)316 void qpdf_set_attempt_recovery(qpdf_data qpdf, QPDF_BOOL value)
317 {
318     QTC::TC("qpdf", "qpdf-c called qpdf_set_attempt_recovery");
319     qpdf->qpdf->setAttemptRecovery(value != QPDF_FALSE);
320 }
321 
qpdf_read(qpdf_data qpdf,char const * filename,char const * password)322 QPDF_ERROR_CODE qpdf_read(qpdf_data qpdf, char const* filename,
323 			  char const* password)
324 {
325     QPDF_ERROR_CODE status = QPDF_SUCCESS;
326     qpdf->filename = filename;
327     qpdf->password = password;
328     status = trap_errors(qpdf, &call_read);
329     // We no longer have a good way to exercise a file with both
330     // warnings and errors because qpdf is getting much better at
331     // recovering.
332     QTC::TC("qpdf", "qpdf-c called qpdf_read",
333             (status == 0) ? 0
334             : (status & QPDF_WARNINGS) ? 1
335             : (status & QPDF_ERRORS) ? 2 :
336             -1
337         );
338     return status;
339 }
340 
qpdf_read_memory(qpdf_data qpdf,char const * description,char const * buffer,unsigned long long size,char const * password)341 QPDF_ERROR_CODE qpdf_read_memory(qpdf_data qpdf,
342 				 char const* description,
343 				 char const* buffer,
344 				 unsigned long long size,
345 				 char const* password)
346 {
347     QPDF_ERROR_CODE status = QPDF_SUCCESS;
348     qpdf->filename = description;
349     qpdf->buffer = buffer;
350     qpdf->size = size;
351     qpdf->password = password;
352     status = trap_errors(qpdf, &call_read_memory);
353     QTC::TC("qpdf", "qpdf-c called qpdf_read_memory", status);
354     return status;
355 }
356 
qpdf_get_pdf_version(qpdf_data qpdf)357 char const* qpdf_get_pdf_version(qpdf_data qpdf)
358 {
359     QTC::TC("qpdf", "qpdf-c called qpdf_get_pdf_version");
360     qpdf->tmp_string = qpdf->qpdf->getPDFVersion();
361     return qpdf->tmp_string.c_str();
362 }
363 
qpdf_get_pdf_extension_level(qpdf_data qpdf)364 int qpdf_get_pdf_extension_level(qpdf_data qpdf)
365 {
366     QTC::TC("qpdf", "qpdf-c called qpdf_get_pdf_extension_level");
367     return qpdf->qpdf->getExtensionLevel();
368 }
369 
qpdf_get_user_password(qpdf_data qpdf)370 char const* qpdf_get_user_password(qpdf_data qpdf)
371 {
372     QTC::TC("qpdf", "qpdf-c called qpdf_get_user_password");
373     qpdf->tmp_string = qpdf->qpdf->getTrimmedUserPassword();
374     return qpdf->tmp_string.c_str();
375 }
376 
qpdf_get_info_key(qpdf_data qpdf,char const * key)377 char const* qpdf_get_info_key(qpdf_data qpdf, char const* key)
378 {
379     char const* result = 0;
380     QPDFObjectHandle trailer = qpdf->qpdf->getTrailer();
381     if (trailer.hasKey("/Info"))
382     {
383 	QPDFObjectHandle info = trailer.getKey("/Info");
384 	if (info.hasKey(key))
385 	{
386 	    QPDFObjectHandle value = info.getKey(key);
387 	    if (value.isString())
388 	    {
389 		qpdf->tmp_string = value.getStringValue();
390 		result = qpdf->tmp_string.c_str();
391 	    }
392 	}
393     }
394     QTC::TC("qpdf", "qpdf-c get_info_key", (result == 0 ? 0 : 1));
395     return result;
396 }
397 
qpdf_set_info_key(qpdf_data qpdf,char const * key,char const * value)398 void qpdf_set_info_key(qpdf_data qpdf, char const* key, char const* value)
399 {
400     if ((key == 0) || (std::strlen(key) == 0) || (key[0] != '/'))
401     {
402 	return;
403     }
404     QPDFObjectHandle value_object;
405     if (value)
406     {
407 	QTC::TC("qpdf", "qpdf-c set_info_key to value");
408 	value_object = QPDFObjectHandle::newString(value);
409     }
410     else
411     {
412 	QTC::TC("qpdf", "qpdf-c set_info_key to null");
413 	value_object = QPDFObjectHandle::newNull();
414     }
415 
416     QPDFObjectHandle trailer = qpdf->qpdf->getTrailer();
417     if (! trailer.hasKey("/Info"))
418     {
419 	QTC::TC("qpdf", "qpdf-c add info to trailer");
420 	trailer.replaceKey(
421 	    "/Info",
422 	    qpdf->qpdf->makeIndirectObject(QPDFObjectHandle::newDictionary()));
423     }
424     else
425     {
426 	QTC::TC("qpdf", "qpdf-c set-info-key use existing info");
427     }
428 
429     QPDFObjectHandle info = trailer.getKey("/Info");
430     info.replaceOrRemoveKey(key, value_object);
431 }
432 
qpdf_is_linearized(qpdf_data qpdf)433 QPDF_BOOL qpdf_is_linearized(qpdf_data qpdf)
434 {
435     QTC::TC("qpdf", "qpdf-c called qpdf_is_linearized");
436     return (qpdf->qpdf->isLinearized() ? QPDF_TRUE : QPDF_FALSE);
437 }
438 
qpdf_is_encrypted(qpdf_data qpdf)439 QPDF_BOOL qpdf_is_encrypted(qpdf_data qpdf)
440 {
441     QTC::TC("qpdf", "qpdf-c called qpdf_is_encrypted");
442     return (qpdf->qpdf->isEncrypted() ? QPDF_TRUE : QPDF_FALSE);
443 }
444 
qpdf_allow_accessibility(qpdf_data qpdf)445 QPDF_BOOL qpdf_allow_accessibility(qpdf_data qpdf)
446 {
447     QTC::TC("qpdf", "qpdf-c called qpdf_allow_accessibility");
448     return (qpdf->qpdf->allowAccessibility() ? QPDF_TRUE : QPDF_FALSE);
449 }
450 
qpdf_allow_extract_all(qpdf_data qpdf)451 QPDF_BOOL qpdf_allow_extract_all(qpdf_data qpdf)
452 {
453     QTC::TC("qpdf", "qpdf-c called qpdf_allow_extract_all");
454     return (qpdf->qpdf->allowExtractAll() ? QPDF_TRUE : QPDF_FALSE);
455 }
456 
qpdf_allow_print_low_res(qpdf_data qpdf)457 QPDF_BOOL qpdf_allow_print_low_res(qpdf_data qpdf)
458 {
459     QTC::TC("qpdf", "qpdf-c called qpdf_allow_print_low_res");
460     return (qpdf->qpdf->allowPrintLowRes() ? QPDF_TRUE : QPDF_FALSE);
461 }
462 
qpdf_allow_print_high_res(qpdf_data qpdf)463 QPDF_BOOL qpdf_allow_print_high_res(qpdf_data qpdf)
464 {
465     QTC::TC("qpdf", "qpdf-c called qpdf_allow_print_high_res");
466     return (qpdf->qpdf->allowPrintHighRes() ? QPDF_TRUE : QPDF_FALSE);
467 }
468 
qpdf_allow_modify_assembly(qpdf_data qpdf)469 QPDF_BOOL qpdf_allow_modify_assembly(qpdf_data qpdf)
470 {
471     QTC::TC("qpdf", "qpdf-c called qpdf_allow_modify_assembly");
472     return (qpdf->qpdf->allowModifyAssembly() ? QPDF_TRUE : QPDF_FALSE);
473 }
474 
qpdf_allow_modify_form(qpdf_data qpdf)475 QPDF_BOOL qpdf_allow_modify_form(qpdf_data qpdf)
476 {
477     QTC::TC("qpdf", "qpdf-c called qpdf_allow_modify_form");
478     return (qpdf->qpdf->allowModifyForm() ? QPDF_TRUE : QPDF_FALSE);
479 }
480 
qpdf_allow_modify_annotation(qpdf_data qpdf)481 QPDF_BOOL qpdf_allow_modify_annotation(qpdf_data qpdf)
482 {
483     QTC::TC("qpdf", "qpdf-c called qpdf_allow_modify_annotation");
484     return (qpdf->qpdf->allowModifyAnnotation() ? QPDF_TRUE : QPDF_FALSE);
485 }
486 
qpdf_allow_modify_other(qpdf_data qpdf)487 QPDF_BOOL qpdf_allow_modify_other(qpdf_data qpdf)
488 {
489     QTC::TC("qpdf", "qpdf-c called qpdf_allow_modify_other");
490     return (qpdf->qpdf->allowModifyOther() ? QPDF_TRUE : QPDF_FALSE);
491 }
492 
qpdf_allow_modify_all(qpdf_data qpdf)493 QPDF_BOOL qpdf_allow_modify_all(qpdf_data qpdf)
494 {
495     QTC::TC("qpdf", "qpdf-c called qpdf_allow_modify_all");
496     return (qpdf->qpdf->allowModifyAll() ? QPDF_TRUE : QPDF_FALSE);
497 }
498 
qpdf_init_write_internal(qpdf_data qpdf)499 static void qpdf_init_write_internal(qpdf_data qpdf)
500 {
501     if (qpdf->qpdf_writer.getPointer())
502     {
503 	QTC::TC("qpdf", "qpdf-c called qpdf_init_write multiple times");
504 	qpdf->qpdf_writer = 0;
505 	if (qpdf->output_buffer.getPointer())
506 	{
507 	    qpdf->output_buffer = 0;
508 	    qpdf->write_memory = false;
509 	    qpdf->filename = 0;
510 	}
511     }
512 }
513 
qpdf_init_write(qpdf_data qpdf,char const * filename)514 QPDF_ERROR_CODE qpdf_init_write(qpdf_data qpdf, char const* filename)
515 {
516     qpdf_init_write_internal(qpdf);
517     qpdf->filename = filename;
518     QPDF_ERROR_CODE status = trap_errors(qpdf, &call_init_write);
519     QTC::TC("qpdf", "qpdf-c called qpdf_init_write", status);
520     return status;
521 }
522 
qpdf_init_write_memory(qpdf_data qpdf)523 QPDF_ERROR_CODE qpdf_init_write_memory(qpdf_data qpdf)
524 {
525     qpdf_init_write_internal(qpdf);
526     QPDF_ERROR_CODE status = trap_errors(qpdf, &call_init_write_memory);
527     QTC::TC("qpdf", "qpdf-c called qpdf_init_write_memory");
528     qpdf->write_memory = true;
529     return status;
530 }
531 
qpdf_get_buffer_internal(qpdf_data qpdf)532 static void qpdf_get_buffer_internal(qpdf_data qpdf)
533 {
534     if (qpdf->write_memory && (qpdf->output_buffer == 0))
535     {
536 	qpdf->output_buffer = qpdf->qpdf_writer->getBuffer();
537     }
538 }
539 
qpdf_get_buffer_length(qpdf_data qpdf)540 size_t qpdf_get_buffer_length(qpdf_data qpdf)
541 {
542     qpdf_get_buffer_internal(qpdf);
543     size_t result = 0;
544     if (qpdf->output_buffer.getPointer())
545     {
546 	result = qpdf->output_buffer->getSize();
547     }
548     return result;
549 }
550 
qpdf_get_buffer(qpdf_data qpdf)551 unsigned char const* qpdf_get_buffer(qpdf_data qpdf)
552 {
553     unsigned char const* result = 0;
554     qpdf_get_buffer_internal(qpdf);
555     if (qpdf->output_buffer.getPointer())
556     {
557 	result = qpdf->output_buffer->getBuffer();
558     }
559     return result;
560 }
561 
qpdf_set_object_stream_mode(qpdf_data qpdf,qpdf_object_stream_e mode)562 void qpdf_set_object_stream_mode(qpdf_data qpdf, qpdf_object_stream_e mode)
563 {
564     QTC::TC("qpdf", "qpdf-c called qpdf_set_object_stream_mode");
565     qpdf->qpdf_writer->setObjectStreamMode(mode);
566 }
567 
qpdf_set_compress_streams(qpdf_data qpdf,QPDF_BOOL value)568 void qpdf_set_compress_streams(qpdf_data qpdf, QPDF_BOOL value)
569 {
570     QTC::TC("qpdf", "qpdf-c called qpdf_set_compress_streams");
571     qpdf->qpdf_writer->setCompressStreams(value != QPDF_FALSE);
572 }
573 
qpdf_set_decode_level(qpdf_data qpdf,qpdf_stream_decode_level_e level)574 void qpdf_set_decode_level(qpdf_data qpdf, qpdf_stream_decode_level_e level)
575 {
576     QTC::TC("qpdf", "qpdf-c called qpdf_set_decode_level");
577     qpdf->qpdf_writer->setDecodeLevel(level);
578 }
579 
qpdf_set_preserve_unreferenced_objects(qpdf_data qpdf,QPDF_BOOL value)580 void qpdf_set_preserve_unreferenced_objects(qpdf_data qpdf, QPDF_BOOL value)
581 {
582     QTC::TC("qpdf", "qpdf-c called qpdf_set_preserve_unreferenced_objects");
583     qpdf->qpdf_writer->setPreserveUnreferencedObjects(value != QPDF_FALSE);
584 }
585 
qpdf_set_newline_before_endstream(qpdf_data qpdf,QPDF_BOOL value)586 void qpdf_set_newline_before_endstream(qpdf_data qpdf, QPDF_BOOL value)
587 {
588     QTC::TC("qpdf", "qpdf-c called qpdf_set_newline_before_endstream");
589     qpdf->qpdf_writer->setNewlineBeforeEndstream(value != QPDF_FALSE);
590 }
591 
qpdf_set_stream_data_mode(qpdf_data qpdf,qpdf_stream_data_e mode)592 void qpdf_set_stream_data_mode(qpdf_data qpdf, qpdf_stream_data_e mode)
593 {
594     QTC::TC("qpdf", "qpdf-c called qpdf_set_stream_data_mode");
595     qpdf->qpdf_writer->setStreamDataMode(mode);
596 }
597 
qpdf_set_content_normalization(qpdf_data qpdf,QPDF_BOOL value)598 void qpdf_set_content_normalization(qpdf_data qpdf, QPDF_BOOL value)
599 {
600     QTC::TC("qpdf", "qpdf-c called qpdf_set_content_normalization");
601     qpdf->qpdf_writer->setContentNormalization(value != QPDF_FALSE);
602 }
603 
qpdf_set_qdf_mode(qpdf_data qpdf,QPDF_BOOL value)604 void qpdf_set_qdf_mode(qpdf_data qpdf, QPDF_BOOL value)
605 {
606     QTC::TC("qpdf", "qpdf-c called qpdf_set_qdf_mode");
607     qpdf->qpdf_writer->setQDFMode(value != QPDF_FALSE);
608 }
609 
qpdf_set_deterministic_ID(qpdf_data qpdf,QPDF_BOOL value)610 void qpdf_set_deterministic_ID(qpdf_data qpdf, QPDF_BOOL value)
611 {
612     QTC::TC("qpdf", "qpdf-c called qpdf_set_deterministic_ID");
613     qpdf->qpdf_writer->setDeterministicID(value != QPDF_FALSE);
614 }
615 
qpdf_set_static_ID(qpdf_data qpdf,QPDF_BOOL value)616 void qpdf_set_static_ID(qpdf_data qpdf, QPDF_BOOL value)
617 {
618     QTC::TC("qpdf", "qpdf-c called qpdf_set_static_ID");
619     qpdf->qpdf_writer->setStaticID(value != QPDF_FALSE);
620 }
621 
qpdf_set_static_aes_IV(qpdf_data qpdf,QPDF_BOOL value)622 void qpdf_set_static_aes_IV(qpdf_data qpdf, QPDF_BOOL value)
623 {
624     QTC::TC("qpdf", "qpdf-c called qpdf_set_static_aes_IV");
625     qpdf->qpdf_writer->setStaticAesIV(value != QPDF_FALSE);
626 }
627 
qpdf_set_suppress_original_object_IDs(qpdf_data qpdf,QPDF_BOOL value)628 void qpdf_set_suppress_original_object_IDs(
629     qpdf_data qpdf, QPDF_BOOL value)
630 {
631     QTC::TC("qpdf", "qpdf-c called qpdf_set_suppress_original_object_IDs");
632     qpdf->qpdf_writer->setSuppressOriginalObjectIDs(value != QPDF_FALSE);
633 }
634 
qpdf_set_preserve_encryption(qpdf_data qpdf,QPDF_BOOL value)635 void qpdf_set_preserve_encryption(qpdf_data qpdf, QPDF_BOOL value)
636 {
637     QTC::TC("qpdf", "qpdf-c called qpdf_set_preserve_encryption");
638     qpdf->qpdf_writer->setPreserveEncryption(value != QPDF_FALSE);
639 }
640 
qpdf_set_r2_encryption_parameters(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)641 void qpdf_set_r2_encryption_parameters(
642     qpdf_data qpdf, char const* user_password, char const* owner_password,
643     QPDF_BOOL allow_print, QPDF_BOOL allow_modify,
644     QPDF_BOOL allow_extract, QPDF_BOOL allow_annotate)
645 {
646     QTC::TC("qpdf", "qpdf-c called qpdf_set_r2_encryption_parameters");
647     qpdf->qpdf_writer->setR2EncryptionParameters(
648 	user_password, owner_password,
649 	allow_print != QPDF_FALSE, allow_modify != QPDF_FALSE,
650         allow_extract != QPDF_FALSE, allow_annotate != QPDF_FALSE);
651 }
652 
qpdf_set_r3_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)653 void qpdf_set_r3_encryption_parameters2(
654     qpdf_data qpdf, char const* user_password, char const* owner_password,
655     QPDF_BOOL allow_accessibility, QPDF_BOOL allow_extract,
656     QPDF_BOOL allow_assemble, QPDF_BOOL allow_annotate_and_form,
657     QPDF_BOOL allow_form_filling, QPDF_BOOL allow_modify_other,
658     enum qpdf_r3_print_e print)
659 {
660     QTC::TC("qpdf", "qpdf-c called qpdf_set_r3_encryption_parameters");
661     qpdf->qpdf_writer->setR3EncryptionParameters(
662         user_password, owner_password,
663         allow_accessibility != QPDF_FALSE, allow_extract != QPDF_FALSE,
664         allow_assemble != QPDF_FALSE, allow_annotate_and_form != QPDF_FALSE,
665         allow_form_filling != QPDF_FALSE, allow_modify_other != QPDF_FALSE,
666         print);
667 }
668 
qpdf_set_r4_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,QPDF_BOOL use_aes)669 void qpdf_set_r4_encryption_parameters2(
670     qpdf_data qpdf, char const* user_password, char const* owner_password,
671     QPDF_BOOL allow_accessibility, QPDF_BOOL allow_extract,
672     QPDF_BOOL allow_assemble, QPDF_BOOL allow_annotate_and_form,
673     QPDF_BOOL allow_form_filling, QPDF_BOOL allow_modify_other,
674     enum qpdf_r3_print_e print,
675     QPDF_BOOL encrypt_metadata, QPDF_BOOL use_aes)
676 {
677     QTC::TC("qpdf", "qpdf-c called qpdf_set_r4_encryption_parameters");
678     qpdf->qpdf_writer->setR4EncryptionParameters(
679         user_password, owner_password,
680         allow_accessibility != QPDF_FALSE, allow_extract != QPDF_FALSE,
681         allow_assemble != QPDF_FALSE, allow_annotate_and_form != QPDF_FALSE,
682         allow_form_filling != QPDF_FALSE, allow_modify_other != QPDF_FALSE,
683         print, encrypt_metadata != QPDF_FALSE, use_aes != QPDF_FALSE);
684 }
685 
686 
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)687 void qpdf_set_r5_encryption_parameters2(
688     qpdf_data qpdf, char const* user_password, char const* owner_password,
689     QPDF_BOOL allow_accessibility, QPDF_BOOL allow_extract,
690     QPDF_BOOL allow_assemble, QPDF_BOOL allow_annotate_and_form,
691     QPDF_BOOL allow_form_filling, QPDF_BOOL allow_modify_other,
692     enum qpdf_r3_print_e print, QPDF_BOOL encrypt_metadata)
693 {
694     QTC::TC("qpdf", "qpdf-c called qpdf_set_r5_encryption_parameters");
695     qpdf->qpdf_writer->setR5EncryptionParameters(
696         user_password, owner_password,
697         allow_accessibility != QPDF_FALSE, allow_extract != QPDF_FALSE,
698         allow_assemble != QPDF_FALSE, allow_annotate_and_form != QPDF_FALSE,
699         allow_form_filling != QPDF_FALSE, allow_modify_other != QPDF_FALSE,
700         print, encrypt_metadata != QPDF_FALSE);
701 }
702 
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)703 void qpdf_set_r6_encryption_parameters2(
704     qpdf_data qpdf, char const* user_password, char const* owner_password,
705     QPDF_BOOL allow_accessibility, QPDF_BOOL allow_extract,
706     QPDF_BOOL allow_assemble, QPDF_BOOL allow_annotate_and_form,
707     QPDF_BOOL allow_form_filling, QPDF_BOOL allow_modify_other,
708     enum qpdf_r3_print_e print, QPDF_BOOL encrypt_metadata)
709 {
710     QTC::TC("qpdf", "qpdf-c called qpdf_set_r6_encryption_parameters");
711     qpdf->qpdf_writer->setR6EncryptionParameters(
712         user_password, owner_password,
713         allow_accessibility != QPDF_FALSE, allow_extract != QPDF_FALSE,
714         allow_assemble != QPDF_FALSE, allow_annotate_and_form != QPDF_FALSE,
715         allow_form_filling != QPDF_FALSE, allow_modify_other != QPDF_FALSE,
716         print, encrypt_metadata != QPDF_FALSE);
717 }
718 
qpdf_set_r3_encryption_parameters(qpdf_data qpdf,char const * user_password,char const * owner_password,QPDF_BOOL allow_accessibility,QPDF_BOOL allow_extract,qpdf_r3_print_e print,qpdf_r3_modify_e modify)719 void qpdf_set_r3_encryption_parameters(
720     qpdf_data qpdf, char const* user_password, char const* owner_password,
721     QPDF_BOOL allow_accessibility, QPDF_BOOL allow_extract,
722     qpdf_r3_print_e print, qpdf_r3_modify_e modify)
723 {
724 #ifdef _MSC_VER
725 # pragma warning (disable: 4996)
726 #endif
727 #if (defined(__GNUC__) || defined(__clang__))
728 # pragma GCC diagnostic push
729 # pragma GCC diagnostic ignored "-Wdeprecated-declarations"
730 #endif
731     qpdf->qpdf_writer->setR3EncryptionParameters(
732 	user_password, owner_password,
733 	allow_accessibility != QPDF_FALSE, allow_extract != QPDF_FALSE,
734         print, modify);
735 #if (defined(__GNUC__) || defined(__clang__))
736 # pragma GCC diagnostic pop
737 #endif
738 }
739 
qpdf_set_r4_encryption_parameters(qpdf_data qpdf,char const * user_password,char const * owner_password,QPDF_BOOL allow_accessibility,QPDF_BOOL allow_extract,qpdf_r3_print_e print,qpdf_r3_modify_e modify,QPDF_BOOL encrypt_metadata,QPDF_BOOL use_aes)740 void qpdf_set_r4_encryption_parameters(
741     qpdf_data qpdf, char const* user_password, char const* owner_password,
742     QPDF_BOOL allow_accessibility, QPDF_BOOL allow_extract,
743     qpdf_r3_print_e print, qpdf_r3_modify_e modify,
744     QPDF_BOOL encrypt_metadata, QPDF_BOOL use_aes)
745 {
746 #ifdef _MSC_VER
747 # pragma warning (disable: 4996)
748 #endif
749 #if (defined(__GNUC__) || defined(__clang__))
750 # pragma GCC diagnostic push
751 # pragma GCC diagnostic ignored "-Wdeprecated-declarations"
752 #endif
753     qpdf->qpdf_writer->setR4EncryptionParameters(
754 	user_password, owner_password,
755 	allow_accessibility != QPDF_FALSE, allow_extract != QPDF_FALSE,
756         print, modify,
757 	encrypt_metadata != QPDF_FALSE, use_aes != QPDF_FALSE);
758 #if (defined(__GNUC__) || defined(__clang__))
759 # pragma GCC diagnostic pop
760 #endif
761 }
762 
qpdf_set_r5_encryption_parameters(qpdf_data qpdf,char const * user_password,char const * owner_password,QPDF_BOOL allow_accessibility,QPDF_BOOL allow_extract,qpdf_r3_print_e print,qpdf_r3_modify_e modify,QPDF_BOOL encrypt_metadata)763 void qpdf_set_r5_encryption_parameters(
764     qpdf_data qpdf, char const* user_password, char const* owner_password,
765     QPDF_BOOL allow_accessibility, QPDF_BOOL allow_extract,
766     qpdf_r3_print_e print, qpdf_r3_modify_e modify,
767     QPDF_BOOL encrypt_metadata)
768 {
769 #ifdef _MSC_VER
770 # pragma warning (disable: 4996)
771 #endif
772 #if (defined(__GNUC__) || defined(__clang__))
773 # pragma GCC diagnostic push
774 # pragma GCC diagnostic ignored "-Wdeprecated-declarations"
775 #endif
776     qpdf->qpdf_writer->setR5EncryptionParameters(
777 	user_password, owner_password,
778 	allow_accessibility != QPDF_FALSE, allow_extract != QPDF_FALSE,
779         print, modify,
780 	encrypt_metadata != QPDF_FALSE);
781 #if (defined(__GNUC__) || defined(__clang__))
782 # pragma GCC diagnostic pop
783 #endif
784 }
785 
qpdf_set_r6_encryption_parameters(qpdf_data qpdf,char const * user_password,char const * owner_password,QPDF_BOOL allow_accessibility,QPDF_BOOL allow_extract,qpdf_r3_print_e print,qpdf_r3_modify_e modify,QPDF_BOOL encrypt_metadata)786 void qpdf_set_r6_encryption_parameters(
787     qpdf_data qpdf, char const* user_password, char const* owner_password,
788     QPDF_BOOL allow_accessibility, QPDF_BOOL allow_extract,
789     qpdf_r3_print_e print, qpdf_r3_modify_e modify,
790     QPDF_BOOL encrypt_metadata)
791 {
792 #ifdef _MSC_VER
793 # pragma warning (disable: 4996)
794 #endif
795 #if (defined(__GNUC__) || defined(__clang__))
796 # pragma GCC diagnostic push
797 # pragma GCC diagnostic ignored "-Wdeprecated-declarations"
798 #endif
799     qpdf->qpdf_writer->setR6EncryptionParameters(
800 	user_password, owner_password,
801 	allow_accessibility != QPDF_FALSE, allow_extract != QPDF_FALSE,
802         print, modify, encrypt_metadata != QPDF_FALSE);
803 #if (defined(__GNUC__) || defined(__clang__))
804 # pragma GCC diagnostic pop
805 #endif
806 }
807 
qpdf_set_linearization(qpdf_data qpdf,QPDF_BOOL value)808 void qpdf_set_linearization(qpdf_data qpdf, QPDF_BOOL value)
809 {
810     QTC::TC("qpdf", "qpdf-c called qpdf_set_linearization");
811     qpdf->qpdf_writer->setLinearization(value != QPDF_FALSE);
812 }
813 
qpdf_set_minimum_pdf_version(qpdf_data qpdf,char const * version)814 void qpdf_set_minimum_pdf_version(qpdf_data qpdf, char const* version)
815 {
816     qpdf_set_minimum_pdf_version_and_extension(qpdf, version, 0);
817 }
818 
qpdf_set_minimum_pdf_version_and_extension(qpdf_data qpdf,char const * version,int extension_level)819 void qpdf_set_minimum_pdf_version_and_extension(
820     qpdf_data qpdf, char const* version, int extension_level)
821 {
822     QTC::TC("qpdf", "qpdf-c called qpdf_set_minimum_pdf_version");
823     qpdf->qpdf_writer->setMinimumPDFVersion(version, extension_level);
824 }
825 
qpdf_force_pdf_version(qpdf_data qpdf,char const * version)826 void qpdf_force_pdf_version(qpdf_data qpdf, char const* version)
827 {
828     qpdf_force_pdf_version_and_extension(qpdf, version, 0);
829 }
830 
qpdf_force_pdf_version_and_extension(qpdf_data qpdf,char const * version,int extension_level)831 void qpdf_force_pdf_version_and_extension(
832     qpdf_data qpdf, char const* version, int extension_level)
833 {
834     QTC::TC("qpdf", "qpdf-c called qpdf_force_pdf_version");
835     qpdf->qpdf_writer->forcePDFVersion(version, extension_level);
836 }
837 
qpdf_register_progress_reporter(qpdf_data qpdf,void (* report_progress)(int percent,void * data),void * data)838 void qpdf_register_progress_reporter(
839     qpdf_data qpdf,
840     void (*report_progress)(int percent, void* data),
841     void* data)
842 {
843     QTC::TC("qpdf", "qpdf-c registered progress reporter");
844     qpdf->qpdf_writer->registerProgressReporter(
845         new ProgressReporter(report_progress, data));
846 }
847 
qpdf_write(qpdf_data qpdf)848 QPDF_ERROR_CODE qpdf_write(qpdf_data qpdf)
849 {
850     QPDF_ERROR_CODE status = QPDF_SUCCESS;
851     status = trap_errors(qpdf, &call_write);
852     QTC::TC("qpdf", "qpdf-c called qpdf_write", (status == 0) ? 0 : 1);
853     return status;
854 }
855 
qpdf_silence_errors(qpdf_data qpdf)856 void qpdf_silence_errors(qpdf_data qpdf)
857 {
858     QTC::TC("qpdf", "qpdf-c silence oh errors");
859     qpdf->silence_errors = true;
860 }
861 
862 template<class RET>
trap_oh_errors(qpdf_data qpdf,std::function<RET ()> fallback,std::function<RET (qpdf_data)> fn)863 static RET trap_oh_errors(
864     qpdf_data qpdf,
865     std::function<RET()> fallback,
866     std::function<RET(qpdf_data)> fn)
867 {
868     // Note: fallback is a function so we don't have to evaluate it
869     // unless needed. This is important because sometimes the fallback
870     // creates an object.
871     RET ret;
872     QPDF_ERROR_CODE status = trap_errors(qpdf, [&ret, fn] (qpdf_data q) {
873         ret = fn(q);
874     });
875     if (status & QPDF_ERRORS)
876     {
877         if (! qpdf->silence_errors)
878         {
879             QTC::TC("qpdf", "qpdf-c warn about oh error",
880                     qpdf->oh_error_occurred ? 0 : 1);
881             if (! qpdf->oh_error_occurred)
882             {
883                 qpdf->warnings.push_back(
884                     QPDFExc(
885                         qpdf_e_internal,
886                         qpdf->qpdf->getFilename(),
887                         "", 0,
888                         "C API function caught an exception that it isn't"
889                         " returning; please point the application developer"
890                         " to ERROR HANDLING in qpdf-c.h"));
891                 qpdf->oh_error_occurred = true;
892             }
893             std::cerr << qpdf->error->what() << std::endl;
894         }
895         return fallback();
896     }
897     return ret;
898 }
899 
900 static qpdf_oh
new_object(qpdf_data qpdf,QPDFObjectHandle const & qoh)901 new_object(qpdf_data qpdf, QPDFObjectHandle const& qoh)
902 {
903     qpdf_oh oh = ++qpdf->next_oh; // never return 0
904     qpdf->oh_cache[oh] = new QPDFObjectHandle(qoh);
905     return oh;
906 }
907 
qpdf_oh_new_object(qpdf_data qpdf,qpdf_oh oh)908 qpdf_oh qpdf_oh_new_object(qpdf_data qpdf, qpdf_oh oh)
909 {
910     QTC::TC("qpdf", "qpdf-c called qpdf_new_object");
911     return new_object(qpdf, *(qpdf->oh_cache[oh]));
912 }
913 
qpdf_oh_release(qpdf_data qpdf,qpdf_oh oh)914 void qpdf_oh_release(qpdf_data qpdf, qpdf_oh oh)
915 {
916     QTC::TC("qpdf", "qpdf-c called qpdf_oh_release");
917     qpdf->oh_cache.erase(oh);
918 }
919 
qpdf_oh_release_all(qpdf_data qpdf)920 void qpdf_oh_release_all(qpdf_data qpdf)
921 {
922     QTC::TC("qpdf", "qpdf-c called qpdf_oh_release_all");
923     qpdf->oh_cache.clear();
924 }
925 
926 template <class T>
return_T(T const & r)927 static std::function<T()> return_T(T const& r)
928 {
929     return [&r]() { return r; };
930 }
931 
return_false()932 static QPDF_BOOL return_false()
933 {
934     return QPDF_FALSE;
935 }
936 
return_uninitialized(qpdf_data qpdf)937 static std::function<qpdf_oh()> return_uninitialized(qpdf_data qpdf)
938 {
939     return [qpdf]() { return qpdf_oh_new_uninitialized(qpdf); };
940 }
941 
return_null(qpdf_data qpdf)942 static std::function<qpdf_oh()> return_null(qpdf_data qpdf)
943 {
944     return [qpdf]() { return qpdf_oh_new_null(qpdf); };
945 }
946 
qpdf_get_trailer(qpdf_data qpdf)947 qpdf_oh qpdf_get_trailer(qpdf_data qpdf)
948 {
949     QTC::TC("qpdf", "qpdf-c called qpdf_get_trailer");
950     return trap_oh_errors<qpdf_oh>(
951         qpdf, return_uninitialized(qpdf), [] (qpdf_data q) {
952             return new_object(q, q->qpdf->getTrailer());
953         });
954 }
955 
qpdf_get_root(qpdf_data qpdf)956 qpdf_oh qpdf_get_root(qpdf_data qpdf)
957 {
958     QTC::TC("qpdf", "qpdf-c called qpdf_get_root");
959     return trap_oh_errors<qpdf_oh>(
960         qpdf, return_uninitialized(qpdf), [] (qpdf_data q) {
961             return new_object(q, q->qpdf->getRoot());
962         });
963 }
964 
qpdf_get_object_by_id(qpdf_data qpdf,int objid,int generation)965 qpdf_oh qpdf_get_object_by_id(qpdf_data qpdf, int objid, int generation)
966 {
967     QTC::TC("qpdf", "qpdf-c called qpdf_get_object_by_id");
968     return new_object(qpdf, qpdf->qpdf->getObjectByID(objid, generation));
969 }
970 
971 template<class RET>
do_with_oh(qpdf_data qpdf,qpdf_oh oh,std::function<RET ()> fallback,std::function<RET (QPDFObjectHandle &)> fn)972 static RET do_with_oh(
973     qpdf_data qpdf, qpdf_oh oh,
974     std::function<RET()> fallback,
975     std::function<RET(QPDFObjectHandle&)> fn)
976 {
977     return trap_oh_errors<RET>(
978         qpdf, fallback, [fn, oh](qpdf_data q) {
979             auto i = q->oh_cache.find(oh);
980             bool result = ((i != q->oh_cache.end()) &&
981                            (i->second).getPointer());
982             if (! result)
983             {
984                 QTC::TC("qpdf", "qpdf-c invalid object handle");
985                 throw QPDFExc(
986                     qpdf_e_internal,
987                     q->qpdf->getFilename(),
988                     std::string("C API object handle ") +
989                     QUtil::uint_to_string(oh),
990                     0, "attempted access to unknown object handle");
991             }
992             return fn(*(q->oh_cache[oh]));
993         });
994 }
995 
do_with_oh_void(qpdf_data qpdf,qpdf_oh oh,std::function<void (QPDFObjectHandle &)> fn)996 static void do_with_oh_void(
997     qpdf_data qpdf, qpdf_oh oh,
998     std::function<void(QPDFObjectHandle&)> fn)
999 {
1000     do_with_oh<bool>(
1001         qpdf, oh, return_T<bool>(false), [fn](QPDFObjectHandle& o) {
1002             fn(o);
1003             return true; // unused
1004         });
1005 }
1006 
qpdf_replace_object(qpdf_data qpdf,int objid,int generation,qpdf_oh oh)1007 void qpdf_replace_object(qpdf_data qpdf, int objid, int generation, qpdf_oh oh)
1008 {
1009     do_with_oh_void(
1010         qpdf, oh, [qpdf, objid, generation](QPDFObjectHandle& o) {
1011             QTC::TC("qpdf", "qpdf-c called qpdf_replace_object");
1012             qpdf->qpdf->replaceObject(objid, generation, o);
1013         });
1014 }
1015 
qpdf_oh_is_initialized(qpdf_data qpdf,qpdf_oh oh)1016 QPDF_BOOL qpdf_oh_is_initialized(qpdf_data qpdf, qpdf_oh oh)
1017 {
1018     QTC::TC("qpdf", "qpdf-c called qpdf_oh_is_initialized");
1019     return do_with_oh<QPDF_BOOL>(
1020         qpdf, oh, return_false, [](QPDFObjectHandle& o) {
1021             return o.isInitialized();
1022         });
1023 }
1024 
qpdf_oh_is_bool(qpdf_data qpdf,qpdf_oh oh)1025 QPDF_BOOL qpdf_oh_is_bool(qpdf_data qpdf, qpdf_oh oh)
1026 {
1027     QTC::TC("qpdf", "qpdf-c called qpdf_oh_is_bool");
1028     return do_with_oh<QPDF_BOOL>(
1029         qpdf, oh, return_false, [](QPDFObjectHandle& o) {
1030             return o.isBool();
1031         });
1032 }
1033 
qpdf_oh_is_null(qpdf_data qpdf,qpdf_oh oh)1034 QPDF_BOOL qpdf_oh_is_null(qpdf_data qpdf, qpdf_oh oh)
1035 {
1036     QTC::TC("qpdf", "qpdf-c called qpdf_oh_is_null");
1037     return do_with_oh<QPDF_BOOL>(
1038         qpdf, oh, return_false, [](QPDFObjectHandle& o) {
1039             return o.isNull();
1040         });
1041 }
1042 
qpdf_oh_is_integer(qpdf_data qpdf,qpdf_oh oh)1043 QPDF_BOOL qpdf_oh_is_integer(qpdf_data qpdf, qpdf_oh oh)
1044 {
1045     QTC::TC("qpdf", "qpdf-c called qpdf_oh_is_integer");
1046     return do_with_oh<QPDF_BOOL>(
1047         qpdf, oh, return_false, [](QPDFObjectHandle& o) {
1048             return o.isInteger();
1049         });
1050 }
1051 
qpdf_oh_is_real(qpdf_data qpdf,qpdf_oh oh)1052 QPDF_BOOL qpdf_oh_is_real(qpdf_data qpdf, qpdf_oh oh)
1053 {
1054     QTC::TC("qpdf", "qpdf-c called qpdf_oh_is_real");
1055     return do_with_oh<QPDF_BOOL>(
1056         qpdf, oh, return_false, [](QPDFObjectHandle& o) {
1057             return o.isReal();
1058         });
1059 }
1060 
qpdf_oh_is_name(qpdf_data qpdf,qpdf_oh oh)1061 QPDF_BOOL qpdf_oh_is_name(qpdf_data qpdf, qpdf_oh oh)
1062 {
1063     QTC::TC("qpdf", "qpdf-c called qpdf_oh_is_name");
1064     return do_with_oh<QPDF_BOOL>(
1065         qpdf, oh, return_false, [](QPDFObjectHandle& o) {
1066             return o.isName();
1067         });
1068 }
1069 
qpdf_oh_is_string(qpdf_data qpdf,qpdf_oh oh)1070 QPDF_BOOL qpdf_oh_is_string(qpdf_data qpdf, qpdf_oh oh)
1071 {
1072     QTC::TC("qpdf", "qpdf-c called qpdf_oh_is_string");
1073     return do_with_oh<QPDF_BOOL>(
1074         qpdf, oh, return_false, [](QPDFObjectHandle& o) {
1075             return o.isString();
1076         });
1077 }
1078 
qpdf_oh_is_operator(qpdf_data qpdf,qpdf_oh oh)1079 QPDF_BOOL qpdf_oh_is_operator(qpdf_data qpdf, qpdf_oh oh)
1080 {
1081     QTC::TC("qpdf", "qpdf-c called qpdf_oh_is_operator");
1082     return do_with_oh<QPDF_BOOL>(
1083         qpdf, oh, return_false, [](QPDFObjectHandle& o) {
1084             return o.isOperator();
1085         });
1086 }
1087 
qpdf_oh_is_inline_image(qpdf_data qpdf,qpdf_oh oh)1088 QPDF_BOOL qpdf_oh_is_inline_image(qpdf_data qpdf, qpdf_oh oh)
1089 {
1090     QTC::TC("qpdf", "qpdf-c called qpdf_oh_is_inline_image");
1091     return do_with_oh<QPDF_BOOL>(
1092         qpdf, oh, return_false, [](QPDFObjectHandle& o) {
1093             return o.isInlineImage();
1094         });
1095 }
1096 
qpdf_oh_is_array(qpdf_data qpdf,qpdf_oh oh)1097 QPDF_BOOL qpdf_oh_is_array(qpdf_data qpdf, qpdf_oh oh)
1098 {
1099     QTC::TC("qpdf", "qpdf-c called qpdf_oh_is_array");
1100     return do_with_oh<QPDF_BOOL>(
1101         qpdf, oh, return_false, [](QPDFObjectHandle& o) {
1102             return o.isArray();
1103         });
1104 }
1105 
qpdf_oh_is_dictionary(qpdf_data qpdf,qpdf_oh oh)1106 QPDF_BOOL qpdf_oh_is_dictionary(qpdf_data qpdf, qpdf_oh oh)
1107 {
1108     QTC::TC("qpdf", "qpdf-c called qpdf_oh_is_dictionary");
1109     return do_with_oh<QPDF_BOOL>(
1110         qpdf, oh, return_false, [](QPDFObjectHandle& o) {
1111             return o.isDictionary();
1112         });
1113 }
1114 
qpdf_oh_is_stream(qpdf_data qpdf,qpdf_oh oh)1115 QPDF_BOOL qpdf_oh_is_stream(qpdf_data qpdf, qpdf_oh oh)
1116 {
1117     QTC::TC("qpdf", "qpdf-c called qpdf_oh_is_stream");
1118     return do_with_oh<QPDF_BOOL>(
1119         qpdf, oh, return_false, [](QPDFObjectHandle& o) {
1120             return o.isStream();
1121         });
1122 }
1123 
qpdf_oh_is_indirect(qpdf_data qpdf,qpdf_oh oh)1124 QPDF_BOOL qpdf_oh_is_indirect(qpdf_data qpdf, qpdf_oh oh)
1125 {
1126     QTC::TC("qpdf", "qpdf-c called qpdf_oh_is_indirect");
1127     return do_with_oh<QPDF_BOOL>(
1128         qpdf, oh, return_false, [](QPDFObjectHandle& o) {
1129             return o.isIndirect();
1130         });
1131 }
1132 
qpdf_oh_is_scalar(qpdf_data qpdf,qpdf_oh oh)1133 QPDF_BOOL qpdf_oh_is_scalar(qpdf_data qpdf, qpdf_oh oh)
1134 {
1135     QTC::TC("qpdf", "qpdf-c called qpdf_oh_is_scalar");
1136     return do_with_oh<QPDF_BOOL>(
1137         qpdf, oh, return_false, [](QPDFObjectHandle& o) {
1138             return o.isScalar();
1139         });
1140 }
1141 
qpdf_oh_is_number(qpdf_data qpdf,qpdf_oh oh)1142 QPDF_BOOL qpdf_oh_is_number(qpdf_data qpdf, qpdf_oh oh)
1143 {
1144     return do_with_oh<QPDF_BOOL>(
1145         qpdf, oh, return_false, [](QPDFObjectHandle& o) {
1146             QTC::TC("qpdf", "qpdf-c called qpdf_oh_is_number");
1147             return o.isNumber();
1148         });
1149 }
1150 
qpdf_oh_get_type_code(qpdf_data qpdf,qpdf_oh oh)1151 qpdf_object_type_e qpdf_oh_get_type_code(qpdf_data qpdf, qpdf_oh oh)
1152 {
1153     return do_with_oh<qpdf_object_type_e>(
1154         qpdf, oh, return_T<qpdf_object_type_e>(ot_uninitialized),
1155         [](QPDFObjectHandle& o) {
1156             QTC::TC("qpdf", "qpdf-c called qpdf_oh_get_type_code");
1157             return o.getTypeCode();
1158         });
1159 }
1160 
qpdf_oh_get_type_name(qpdf_data qpdf,qpdf_oh oh)1161 char const* qpdf_oh_get_type_name(qpdf_data qpdf, qpdf_oh oh)
1162 {
1163     return do_with_oh<char const*>(
1164         qpdf, oh, return_T<char const*>(""), [qpdf](QPDFObjectHandle& o) {
1165             QTC::TC("qpdf", "qpdf-c called qpdf_oh_get_type_name");
1166             qpdf->tmp_string = o.getTypeName();
1167             return qpdf->tmp_string.c_str();
1168         });
1169 }
1170 
qpdf_oh_wrap_in_array(qpdf_data qpdf,qpdf_oh oh)1171 qpdf_oh qpdf_oh_wrap_in_array(qpdf_data qpdf, qpdf_oh oh)
1172 {
1173     return do_with_oh<qpdf_oh>(
1174         qpdf, oh,
1175         [qpdf](){ return qpdf_oh_new_array(qpdf); },
1176         [qpdf](QPDFObjectHandle& qoh) {
1177             if (qoh.isArray())
1178             {
1179                 QTC::TC("qpdf", "qpdf-c array to wrap_in_array");
1180                 return new_object(qpdf, qoh);
1181             }
1182             else
1183             {
1184                 QTC::TC("qpdf", "qpdf-c non-array to wrap_in_array");
1185                 return new_object(qpdf,
1186                                   QPDFObjectHandle::newArray(
1187                                       std::vector<QPDFObjectHandle>{qoh}));
1188             }
1189             });
1190 }
1191 
qpdf_oh_parse(qpdf_data qpdf,char const * object_str)1192 qpdf_oh qpdf_oh_parse(qpdf_data qpdf, char const* object_str)
1193 {
1194     QTC::TC("qpdf", "qpdf-c called qpdf_oh_parse");
1195     return trap_oh_errors<qpdf_oh>(
1196         qpdf, return_uninitialized(qpdf), [object_str] (qpdf_data q) {
1197             return new_object(q, QPDFObjectHandle::parse(object_str));
1198         });
1199 }
1200 
qpdf_oh_get_bool_value(qpdf_data qpdf,qpdf_oh oh)1201 QPDF_BOOL qpdf_oh_get_bool_value(qpdf_data qpdf, qpdf_oh oh)
1202 {
1203     return do_with_oh<QPDF_BOOL>(
1204         qpdf, oh, return_false, [](QPDFObjectHandle& o) {
1205             QTC::TC("qpdf", "qpdf-c called qpdf_oh_get_bool_value");
1206             return o.getBoolValue();
1207         });
1208 }
1209 
qpdf_oh_get_int_value(qpdf_data qpdf,qpdf_oh oh)1210 long long qpdf_oh_get_int_value(qpdf_data qpdf, qpdf_oh oh)
1211 {
1212     return do_with_oh<long long>(
1213         qpdf, oh, return_T<long long>(0LL), [](QPDFObjectHandle& o) {
1214             QTC::TC("qpdf", "qpdf-c called qpdf_oh_get_int_value");
1215             return o.getIntValue();
1216         });
1217 }
1218 
qpdf_oh_get_int_value_as_int(qpdf_data qpdf,qpdf_oh oh)1219 int qpdf_oh_get_int_value_as_int(qpdf_data qpdf, qpdf_oh oh)
1220 {
1221     return do_with_oh<int>(
1222         qpdf, oh, return_T<int>(0), [](QPDFObjectHandle& o) {
1223             QTC::TC("qpdf", "qpdf-c called qpdf_oh_get_int_value_as_int");
1224             return o.getIntValueAsInt();
1225         });
1226 }
1227 
qpdf_oh_get_uint_value(qpdf_data qpdf,qpdf_oh oh)1228 unsigned long long qpdf_oh_get_uint_value(qpdf_data qpdf, qpdf_oh oh)
1229 {
1230     return do_with_oh<unsigned long long>(
1231         qpdf, oh, return_T<unsigned long long>(0ULL), [](QPDFObjectHandle& o) {
1232             QTC::TC("qpdf", "qpdf-c called qpdf_oh_get_uint_value");
1233             return o.getUIntValue();
1234         });
1235 }
1236 
qpdf_oh_get_uint_value_as_uint(qpdf_data qpdf,qpdf_oh oh)1237 unsigned int qpdf_oh_get_uint_value_as_uint(qpdf_data qpdf, qpdf_oh oh)
1238 {
1239     return do_with_oh<unsigned int>(
1240         qpdf, oh, return_T<unsigned int>(0U), [](QPDFObjectHandle& o) {
1241             QTC::TC("qpdf", "qpdf-c called qpdf_oh_get_uint_value_as_uint");
1242             return o.getUIntValueAsUInt();
1243         });
1244 }
1245 
qpdf_oh_get_real_value(qpdf_data qpdf,qpdf_oh oh)1246 char const* qpdf_oh_get_real_value(qpdf_data qpdf, qpdf_oh oh)
1247 {
1248     return do_with_oh<char const*>(
1249         qpdf, oh, return_T<char const*>(""), [qpdf](QPDFObjectHandle& o) {
1250             QTC::TC("qpdf", "qpdf-c called qpdf_oh_get_real_value");
1251             qpdf->tmp_string = o.getRealValue();
1252             return qpdf->tmp_string.c_str();
1253         });
1254 }
1255 
qpdf_oh_get_numeric_value(qpdf_data qpdf,qpdf_oh oh)1256 double qpdf_oh_get_numeric_value(qpdf_data qpdf, qpdf_oh oh)
1257 {
1258     return do_with_oh<double>(
1259         qpdf, oh, return_T<double>(0.0), [](QPDFObjectHandle& o) {
1260             QTC::TC("qpdf", "qpdf-c called qpdf_oh_get_numeric_value");
1261             return o.getNumericValue();
1262         });
1263 }
1264 
qpdf_oh_get_name(qpdf_data qpdf,qpdf_oh oh)1265 char const* qpdf_oh_get_name(qpdf_data qpdf, qpdf_oh oh)
1266 {
1267     return do_with_oh<char const*>(
1268         qpdf, oh, return_T<char const*>(""), [qpdf](QPDFObjectHandle& o) {
1269             QTC::TC("qpdf", "qpdf-c called qpdf_oh_get_name");
1270             qpdf->tmp_string = o.getName();
1271             return qpdf->tmp_string.c_str();
1272         });
1273 }
1274 
qpdf_oh_get_string_value(qpdf_data qpdf,qpdf_oh oh)1275 char const* qpdf_oh_get_string_value(qpdf_data qpdf, qpdf_oh oh)
1276 {
1277     return do_with_oh<char const*>(
1278         qpdf, oh, return_T<char const*>(""), [qpdf](QPDFObjectHandle& o) {
1279             QTC::TC("qpdf", "qpdf-c called qpdf_oh_get_string_value");
1280             qpdf->tmp_string = o.getStringValue();
1281             return qpdf->tmp_string.c_str();
1282         });
1283 }
1284 
qpdf_oh_get_utf8_value(qpdf_data qpdf,qpdf_oh oh)1285 char const* qpdf_oh_get_utf8_value(qpdf_data qpdf, qpdf_oh oh)
1286 {
1287     return do_with_oh<char const*>(
1288         qpdf, oh, return_T<char const*>(""), [qpdf](QPDFObjectHandle& o) {
1289             QTC::TC("qpdf", "qpdf-c called qpdf_oh_get_utf8_value");
1290             qpdf->tmp_string = o.getUTF8Value();
1291             return qpdf->tmp_string.c_str();
1292         });
1293 }
1294 
qpdf_oh_get_binary_string_value(qpdf_data qpdf,qpdf_oh oh,size_t * length)1295 char const* qpdf_oh_get_binary_string_value(
1296     qpdf_data qpdf, qpdf_oh oh, size_t* length)
1297 {
1298     return do_with_oh<char const*>(
1299         qpdf, oh,
1300         return_T<char const*>(""),
1301         [qpdf, length](QPDFObjectHandle& o) {
1302             QTC::TC("qpdf", "qpdf-c called qpdf_oh_get_binary_string_value");
1303             qpdf->tmp_string = o.getStringValue();
1304             *length = qpdf->tmp_string.length();
1305             return qpdf->tmp_string.c_str();
1306         });
1307 }
1308 
qpdf_oh_get_array_n_items(qpdf_data qpdf,qpdf_oh oh)1309 int qpdf_oh_get_array_n_items(qpdf_data qpdf, qpdf_oh oh)
1310 {
1311     return do_with_oh<int>(
1312         qpdf, oh, return_T<int>(0), [](QPDFObjectHandle& o) {
1313             QTC::TC("qpdf", "qpdf-c called qpdf_oh_get_array_n_items");
1314             return o.getArrayNItems();
1315         });
1316 }
1317 
qpdf_oh_get_array_item(qpdf_data qpdf,qpdf_oh oh,int n)1318 qpdf_oh qpdf_oh_get_array_item(qpdf_data qpdf, qpdf_oh oh, int n)
1319 {
1320     return do_with_oh<qpdf_oh>(
1321         qpdf, oh, return_null(qpdf), [qpdf, n](QPDFObjectHandle& o) {
1322             QTC::TC("qpdf", "qpdf-c called qpdf_oh_get_array_item");
1323             return new_object(qpdf, o.getArrayItem(n));
1324         });
1325 }
1326 
qpdf_oh_begin_dict_key_iter(qpdf_data qpdf,qpdf_oh oh)1327 void qpdf_oh_begin_dict_key_iter(qpdf_data qpdf, qpdf_oh oh)
1328 {
1329     qpdf->cur_iter_dict_keys = do_with_oh<std::set<std::string>>(
1330         qpdf, oh,
1331         [](){ return std::set<std::string>(); },
1332         [](QPDFObjectHandle& o) {
1333             QTC::TC("qpdf", "qpdf-c called qpdf_oh_begin_dict_key_iter");
1334             return o.getKeys();
1335         });
1336     qpdf->dict_iter = qpdf->cur_iter_dict_keys.begin();
1337 }
1338 
qpdf_oh_dict_more_keys(qpdf_data qpdf)1339 QPDF_BOOL qpdf_oh_dict_more_keys(qpdf_data qpdf)
1340 {
1341     QTC::TC("qpdf", "qpdf-c called qpdf_oh_dict_more_keys");
1342     return qpdf->dict_iter != qpdf->cur_iter_dict_keys.end();
1343 }
1344 
qpdf_oh_dict_next_key(qpdf_data qpdf)1345 char const* qpdf_oh_dict_next_key(qpdf_data qpdf)
1346 {
1347     QTC::TC("qpdf", "qpdf-c called qpdf_oh_dict_next_key");
1348     if (qpdf_oh_dict_more_keys(qpdf))
1349     {
1350         qpdf->cur_dict_key = *qpdf->dict_iter;
1351         ++qpdf->dict_iter;
1352         return qpdf->cur_dict_key.c_str();
1353     }
1354     else
1355     {
1356         return nullptr;
1357     }
1358 }
1359 
qpdf_oh_has_key(qpdf_data qpdf,qpdf_oh oh,char const * key)1360 QPDF_BOOL qpdf_oh_has_key(qpdf_data qpdf, qpdf_oh oh, char const* key)
1361 {
1362     return do_with_oh<QPDF_BOOL>(
1363         qpdf, oh, return_false, [key](QPDFObjectHandle& o) {
1364             QTC::TC("qpdf", "qpdf-c called qpdf_oh_has_key");
1365             return o.hasKey(key);
1366         });
1367 }
1368 
qpdf_oh_get_key(qpdf_data qpdf,qpdf_oh oh,char const * key)1369 qpdf_oh qpdf_oh_get_key(qpdf_data qpdf, qpdf_oh oh, char const* key)
1370 {
1371     return do_with_oh<qpdf_oh>(
1372         qpdf, oh, return_null(qpdf), [qpdf, key](QPDFObjectHandle& o) {
1373             QTC::TC("qpdf", "qpdf-c called qpdf_oh_get_key");
1374             return new_object(qpdf, o.getKey(key));
1375         });
1376 }
1377 
qpdf_oh_is_or_has_name(qpdf_data qpdf,qpdf_oh oh,char const * key)1378 QPDF_BOOL qpdf_oh_is_or_has_name(qpdf_data qpdf, qpdf_oh oh, char const* key)
1379 {
1380     return do_with_oh<QPDF_BOOL>(
1381         qpdf, oh, return_false, [key](QPDFObjectHandle& o) {
1382             QTC::TC("qpdf", "qpdf-c called qpdf_oh_is_or_has_name");
1383             return o.isOrHasName(key);
1384         });
1385 }
1386 
qpdf_oh_new_uninitialized(qpdf_data qpdf)1387 qpdf_oh qpdf_oh_new_uninitialized(qpdf_data qpdf)
1388 {
1389     QTC::TC("qpdf", "qpdf-c called qpdf_oh_new_uninitialized");
1390     return new_object(qpdf, QPDFObjectHandle());
1391 }
1392 
qpdf_oh_new_null(qpdf_data qpdf)1393 qpdf_oh qpdf_oh_new_null(qpdf_data qpdf)
1394 {
1395     QTC::TC("qpdf", "qpdf-c called qpdf_oh_new_null");
1396     return new_object(qpdf, QPDFObjectHandle::newNull());
1397 }
1398 
qpdf_oh_new_bool(qpdf_data qpdf,QPDF_BOOL value)1399 qpdf_oh qpdf_oh_new_bool(qpdf_data qpdf, QPDF_BOOL value)
1400 {
1401     QTC::TC("qpdf", "qpdf-c called qpdf_oh_new_bool");
1402     return new_object(qpdf, QPDFObjectHandle::newBool(value));
1403 }
1404 
qpdf_oh_new_integer(qpdf_data qpdf,long long value)1405 qpdf_oh qpdf_oh_new_integer(qpdf_data qpdf, long long value)
1406 {
1407     QTC::TC("qpdf", "qpdf-c called qpdf_oh_new_integer");
1408     return new_object(qpdf, QPDFObjectHandle::newInteger(value));
1409 }
1410 
qpdf_oh_new_real_from_string(qpdf_data qpdf,char const * value)1411 qpdf_oh qpdf_oh_new_real_from_string(qpdf_data qpdf, char const* value)
1412 {
1413     QTC::TC("qpdf", "qpdf-c called qpdf_oh_new_real_from_string");
1414     return new_object(qpdf, QPDFObjectHandle::newReal(value));
1415 }
1416 
qpdf_oh_new_real_from_double(qpdf_data qpdf,double value,int decimal_places)1417 qpdf_oh qpdf_oh_new_real_from_double(qpdf_data qpdf,
1418                                      double value, int decimal_places)
1419 {
1420     QTC::TC("qpdf", "qpdf-c called qpdf_oh_new_real_from_double");
1421     return new_object(qpdf, QPDFObjectHandle::newReal(value, decimal_places));
1422 }
1423 
qpdf_oh_new_name(qpdf_data qpdf,char const * name)1424 qpdf_oh qpdf_oh_new_name(qpdf_data qpdf, char const* name)
1425 {
1426     QTC::TC("qpdf", "qpdf-c called qpdf_oh_new_name");
1427     return new_object(qpdf, QPDFObjectHandle::newName(name));
1428 }
1429 
qpdf_oh_new_string(qpdf_data qpdf,char const * str)1430 qpdf_oh qpdf_oh_new_string(qpdf_data qpdf, char const* str)
1431 {
1432     QTC::TC("qpdf", "qpdf-c called qpdf_oh_new_string");
1433     return new_object(qpdf, QPDFObjectHandle::newString(str));
1434 }
1435 
qpdf_oh_new_unicode_string(qpdf_data qpdf,char const * utf8_str)1436 qpdf_oh qpdf_oh_new_unicode_string(qpdf_data qpdf, char const* utf8_str)
1437 {
1438     QTC::TC("qpdf", "qpdf-c called qpdf_oh_new_unicode_string");
1439     return new_object(qpdf, QPDFObjectHandle::newUnicodeString(utf8_str));
1440 }
1441 
qpdf_oh_new_binary_string(qpdf_data qpdf,char const * str,size_t length)1442 qpdf_oh qpdf_oh_new_binary_string(
1443     qpdf_data qpdf, char const* str, size_t length)
1444 {
1445     QTC::TC("qpdf", "qpdf-c called qpdf_oh_new_binary_string");
1446     return new_object(
1447         qpdf, QPDFObjectHandle::newString(std::string(str, length)));
1448 }
1449 
qpdf_oh_new_array(qpdf_data qpdf)1450 qpdf_oh qpdf_oh_new_array(qpdf_data qpdf)
1451 {
1452     QTC::TC("qpdf", "qpdf-c called qpdf_oh_new_array");
1453     return new_object(qpdf, QPDFObjectHandle::newArray());
1454 }
1455 
qpdf_oh_new_dictionary(qpdf_data qpdf)1456 qpdf_oh qpdf_oh_new_dictionary(qpdf_data qpdf)
1457 {
1458     QTC::TC("qpdf", "qpdf-c called qpdf_oh_new_dictionary");
1459     return new_object(qpdf, QPDFObjectHandle::newDictionary());
1460 }
1461 
qpdf_oh_new_stream(qpdf_data qpdf)1462 qpdf_oh qpdf_oh_new_stream(qpdf_data qpdf)
1463 {
1464     QTC::TC("qpdf", "qpdf-c called qpdf_oh_new_stream");
1465     return new_object(
1466         qpdf, QPDFObjectHandle::newStream(qpdf->qpdf.getPointer()));
1467 }
1468 
qpdf_oh_make_direct(qpdf_data qpdf,qpdf_oh oh)1469 void qpdf_oh_make_direct(qpdf_data qpdf, qpdf_oh oh)
1470 {
1471     do_with_oh_void(
1472         qpdf, oh, [](QPDFObjectHandle& o) {
1473             QTC::TC("qpdf", "qpdf-c called qpdf_oh_make_direct");
1474             o.makeDirect();
1475         });
1476 }
1477 
qpdf_make_indirect_object(qpdf_data qpdf,qpdf_oh oh)1478 qpdf_oh qpdf_make_indirect_object(qpdf_data qpdf, qpdf_oh oh)
1479 {
1480     return do_with_oh<qpdf_oh>(
1481         qpdf, oh,
1482         return_uninitialized(qpdf),
1483         [qpdf](QPDFObjectHandle& o) {
1484             return new_object(qpdf, qpdf->qpdf->makeIndirectObject(o));
1485         });
1486 }
1487 
1488 static QPDFObjectHandle
qpdf_oh_item_internal(qpdf_data qpdf,qpdf_oh item)1489 qpdf_oh_item_internal(qpdf_data qpdf, qpdf_oh item)
1490 {
1491     return do_with_oh<QPDFObjectHandle>(
1492         qpdf, item,
1493         [](){return QPDFObjectHandle::newNull();},
1494         [](QPDFObjectHandle& o) {
1495             return o;
1496         });
1497 }
1498 
qpdf_oh_set_array_item(qpdf_data qpdf,qpdf_oh oh,int at,qpdf_oh item)1499 void qpdf_oh_set_array_item(qpdf_data qpdf, qpdf_oh oh,
1500                             int at, qpdf_oh item)
1501 {
1502     do_with_oh_void(
1503         qpdf, oh, [qpdf, at, item](QPDFObjectHandle& o) {
1504             QTC::TC("qpdf", "qpdf-c called qpdf_oh_set_array_item");
1505             o.setArrayItem(at, qpdf_oh_item_internal(qpdf, item));
1506         });
1507 }
1508 
qpdf_oh_insert_item(qpdf_data qpdf,qpdf_oh oh,int at,qpdf_oh item)1509 void qpdf_oh_insert_item(qpdf_data qpdf, qpdf_oh oh, int at, qpdf_oh item)
1510 {
1511     do_with_oh_void(
1512         qpdf, oh, [qpdf, at, item](QPDFObjectHandle& o) {
1513             QTC::TC("qpdf", "qpdf-c called qpdf_oh_insert_item");
1514             o.insertItem(at, qpdf_oh_item_internal(qpdf, item));
1515         });
1516 }
1517 
qpdf_oh_append_item(qpdf_data qpdf,qpdf_oh oh,qpdf_oh item)1518 void qpdf_oh_append_item(qpdf_data qpdf, qpdf_oh oh, qpdf_oh item)
1519 {
1520     do_with_oh_void(
1521         qpdf, oh, [qpdf, item](QPDFObjectHandle& o) {
1522             QTC::TC("qpdf", "qpdf-c called qpdf_oh_append_item");
1523             o.appendItem(qpdf_oh_item_internal(qpdf, item));
1524         });
1525 }
1526 
qpdf_oh_erase_item(qpdf_data qpdf,qpdf_oh oh,int at)1527 void qpdf_oh_erase_item(qpdf_data qpdf, qpdf_oh oh, int at)
1528 {
1529     do_with_oh_void(
1530         qpdf, oh, [at](QPDFObjectHandle& o) {
1531             QTC::TC("qpdf", "qpdf-c called qpdf_oh_erase_item");
1532             o.eraseItem(at);
1533         });
1534 }
1535 
qpdf_oh_replace_key(qpdf_data qpdf,qpdf_oh oh,char const * key,qpdf_oh item)1536 void qpdf_oh_replace_key(qpdf_data qpdf, qpdf_oh oh,
1537                          char const* key, qpdf_oh item)
1538 {
1539     do_with_oh_void(
1540         qpdf, oh, [qpdf, key, item](QPDFObjectHandle& o) {
1541             QTC::TC("qpdf", "qpdf-c called qpdf_oh_replace_key");
1542             o.replaceKey(key, qpdf_oh_item_internal(qpdf, item));
1543         });
1544 }
1545 
qpdf_oh_remove_key(qpdf_data qpdf,qpdf_oh oh,char const * key)1546 void qpdf_oh_remove_key(qpdf_data qpdf, qpdf_oh oh, char const* key)
1547 {
1548     do_with_oh_void(
1549         qpdf, oh, [key](QPDFObjectHandle& o) {
1550             QTC::TC("qpdf", "qpdf-c called qpdf_oh_remove_key");
1551             o.removeKey(key);
1552         });
1553 }
1554 
qpdf_oh_replace_or_remove_key(qpdf_data qpdf,qpdf_oh oh,char const * key,qpdf_oh item)1555 void qpdf_oh_replace_or_remove_key(qpdf_data qpdf, qpdf_oh oh,
1556                                    char const* key, qpdf_oh item)
1557 {
1558     do_with_oh_void(
1559         qpdf, oh, [qpdf, key, item](QPDFObjectHandle& o) {
1560             QTC::TC("qpdf", "qpdf-c called qpdf_oh_replace_or_remove_key");
1561             o.replaceOrRemoveKey(key, qpdf_oh_item_internal(qpdf, item));
1562         });
1563 }
1564 
qpdf_oh_get_dict(qpdf_data qpdf,qpdf_oh oh)1565 qpdf_oh qpdf_oh_get_dict(qpdf_data qpdf, qpdf_oh oh)
1566 {
1567     return do_with_oh<qpdf_oh>(
1568         qpdf, oh, return_null(qpdf), [qpdf](QPDFObjectHandle& o) {
1569             QTC::TC("qpdf", "qpdf-c called qpdf_oh_get_dict");
1570             return new_object(qpdf, o.getDict());
1571         });
1572 }
1573 
qpdf_oh_get_object_id(qpdf_data qpdf,qpdf_oh oh)1574 int qpdf_oh_get_object_id(qpdf_data qpdf, qpdf_oh oh)
1575 {
1576     return do_with_oh<int>(
1577         qpdf, oh, return_T<int>(0), [](QPDFObjectHandle& o) {
1578             QTC::TC("qpdf", "qpdf-c called qpdf_oh_get_object_id");
1579             return o.getObjectID();
1580         });
1581 }
1582 
qpdf_oh_get_generation(qpdf_data qpdf,qpdf_oh oh)1583 int qpdf_oh_get_generation(qpdf_data qpdf, qpdf_oh oh)
1584 {
1585     return do_with_oh<int>(
1586         qpdf, oh, return_T<int>(0), [](QPDFObjectHandle& o) {
1587             QTC::TC("qpdf", "qpdf-c called qpdf_oh_get_generation");
1588             return o.getGeneration();
1589         });
1590 }
1591 
qpdf_oh_unparse(qpdf_data qpdf,qpdf_oh oh)1592 char const* qpdf_oh_unparse(qpdf_data qpdf, qpdf_oh oh)
1593 {
1594     return do_with_oh<char const*>(
1595         qpdf, oh, return_T<char const*>(""), [qpdf](QPDFObjectHandle& o) {
1596             QTC::TC("qpdf", "qpdf-c called qpdf_oh_unparse");
1597             qpdf->tmp_string = o.unparse();
1598             return qpdf->tmp_string.c_str();
1599         });
1600 }
1601 
qpdf_oh_unparse_resolved(qpdf_data qpdf,qpdf_oh oh)1602 char const* qpdf_oh_unparse_resolved(qpdf_data qpdf, qpdf_oh oh)
1603 {
1604     return do_with_oh<char const*>(
1605         qpdf, oh, return_T<char const*>(""), [qpdf](QPDFObjectHandle& o) {
1606             QTC::TC("qpdf", "qpdf-c called qpdf_oh_unparse_resolved");
1607             qpdf->tmp_string = o.unparseResolved();
1608             return qpdf->tmp_string.c_str();
1609         });
1610 }
1611 
qpdf_oh_unparse_binary(qpdf_data qpdf,qpdf_oh oh)1612 char const* qpdf_oh_unparse_binary(qpdf_data qpdf, qpdf_oh oh)
1613 {
1614     return do_with_oh<char const*>(
1615         qpdf, oh, return_T<char const*>(""), [qpdf](QPDFObjectHandle& o) {
1616             QTC::TC("qpdf", "qpdf-c called qpdf_oh_unparse_binary");
1617             qpdf->tmp_string = o.unparseBinary();
1618             return qpdf->tmp_string.c_str();
1619         });
1620 }
1621 
qpdf_oh_copy_foreign_object(qpdf_data qpdf,qpdf_data other_qpdf,qpdf_oh foreign_oh)1622 qpdf_oh qpdf_oh_copy_foreign_object(
1623     qpdf_data qpdf, qpdf_data other_qpdf, qpdf_oh foreign_oh)
1624 {
1625     return do_with_oh<qpdf_oh>(
1626         other_qpdf, foreign_oh,
1627         return_uninitialized(qpdf),
1628         [qpdf](QPDFObjectHandle& o) {
1629             QTC::TC("qpdf", "qpdf-c called qpdf_oh_copy_foreign_object");
1630             return new_object(qpdf, qpdf->qpdf->copyForeignObject(o));
1631         });
1632 }
1633 
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)1634 QPDF_ERROR_CODE qpdf_oh_get_stream_data(
1635     qpdf_data qpdf, qpdf_oh stream_oh,
1636     qpdf_stream_decode_level_e decode_level, QPDF_BOOL* filtered,
1637     unsigned char** bufp, size_t* len)
1638 {
1639     return trap_errors(qpdf, [stream_oh, decode_level,
1640                               filtered, bufp, len] (qpdf_data q) {
1641         auto stream = qpdf_oh_item_internal(q, stream_oh);
1642         Pipeline* p = nullptr;
1643         Pl_Buffer buf("stream data");
1644         if (bufp)
1645         {
1646             p = &buf;
1647         }
1648         bool was_filtered = false;
1649         if (stream.pipeStreamData(
1650                 p, &was_filtered, 0, decode_level, false, false))
1651         {
1652             QTC::TC("qpdf", "qpdf-c stream data buf set",
1653                     bufp ? 0 : 1);
1654             if (p && bufp && len)
1655             {
1656                 buf.getMallocBuffer(bufp, len);
1657             }
1658             QTC::TC("qpdf", "qpdf-c stream data filtered set",
1659                     filtered ? 0 : 1);
1660             if (filtered)
1661             {
1662                 *filtered = was_filtered ? QPDF_TRUE : QPDF_FALSE;
1663             }
1664         }
1665         else
1666         {
1667             throw std::runtime_error(
1668                 "unable to access stream data for stream " + stream.unparse());
1669         }
1670     });
1671 }
1672 
qpdf_oh_get_page_content_data(qpdf_data qpdf,qpdf_oh page_oh,unsigned char ** bufp,size_t * len)1673 QPDF_ERROR_CODE qpdf_oh_get_page_content_data(
1674     qpdf_data qpdf, qpdf_oh page_oh,
1675     unsigned char** bufp, size_t* len)
1676 {
1677     return trap_errors(qpdf, [page_oh, bufp, len] (qpdf_data q) {
1678         QTC::TC("qpdf", "qpdf-c called qpdf_oh_get_page_content_data");
1679         auto o = qpdf_oh_item_internal(q, page_oh);
1680         Pl_Buffer buf("page contents");
1681         o.pipePageContents(&buf);
1682         buf.getMallocBuffer(bufp, len);
1683     });
1684 }
1685 
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)1686 void qpdf_oh_replace_stream_data(
1687     qpdf_data qpdf, qpdf_oh stream_oh,
1688     unsigned char const* buf, size_t len,
1689     qpdf_oh filter_oh, qpdf_oh decode_parms_oh)
1690 {
1691     do_with_oh_void(qpdf, stream_oh, [
1692                         qpdf, buf, len, filter_oh,
1693                         decode_parms_oh](QPDFObjectHandle& o) {
1694         QTC::TC("qpdf", "qpdf-c called qpdf_oh_replace_stream_data");
1695         auto filter = qpdf_oh_item_internal(qpdf, filter_oh);
1696         auto decode_parms = qpdf_oh_item_internal(qpdf, decode_parms_oh);
1697         // XXX test with binary data with null
1698         o.replaceStreamData(
1699             std::string(reinterpret_cast<char const*>(buf), len),
1700             filter, decode_parms);
1701     });
1702 }
1703 
qpdf_get_num_pages(qpdf_data qpdf)1704 int qpdf_get_num_pages(qpdf_data qpdf)
1705 {
1706     QTC::TC("qpdf", "qpdf-c called qpdf_num_pages");
1707     int n = -1;
1708     QPDF_ERROR_CODE code = trap_errors(qpdf, [&n](qpdf_data q) {
1709         n = QIntC::to_int(q->qpdf->getAllPages().size());
1710     });
1711     if (code & QPDF_ERRORS)
1712     {
1713         return -1;
1714     }
1715     return n;
1716 }
1717 
qpdf_get_page_n(qpdf_data qpdf,size_t i)1718 qpdf_oh qpdf_get_page_n(qpdf_data qpdf, size_t i)
1719 {
1720     QTC::TC("qpdf", "qpdf-c called qpdf_get_page_n");
1721     qpdf_oh result = 0;
1722     QPDF_ERROR_CODE code = trap_errors(qpdf, [&result, i](qpdf_data q) {
1723         result = new_object(q, q->qpdf->getAllPages().at(i));
1724     });
1725     if ((code & QPDF_ERRORS) || (result == 0))
1726     {
1727         return qpdf_oh_new_uninitialized(qpdf);
1728     }
1729     return result;
1730 }
1731 
qpdf_update_all_pages_cache(qpdf_data qpdf)1732 QPDF_ERROR_CODE qpdf_update_all_pages_cache(qpdf_data qpdf)
1733 {
1734     QTC::TC("qpdf", "qpdf-c called qpdf_update_all_pages_cache");
1735     return trap_errors(qpdf, [](qpdf_data q) {
1736         q->qpdf->updateAllPagesCache();
1737     });
1738 }
1739 
qpdf_find_page_by_id(qpdf_data qpdf,int objid,int generation)1740 int qpdf_find_page_by_id(qpdf_data qpdf, int objid, int generation)
1741 {
1742     QTC::TC("qpdf", "qpdf-c called qpdf_find_page_by_id");
1743     int n = -1;
1744     QPDFObjGen og(objid, generation);
1745     QPDF_ERROR_CODE code = trap_errors(qpdf, [&n, &og](qpdf_data q) {
1746         n = QIntC::to_int(q->qpdf->findPage(og));
1747     });
1748     if (code & QPDF_ERRORS)
1749     {
1750         return -1;
1751     }
1752     return n;
1753 }
1754 
qpdf_find_page_by_oh(qpdf_data qpdf,qpdf_oh oh)1755 int qpdf_find_page_by_oh(qpdf_data qpdf, qpdf_oh oh)
1756 {
1757     QTC::TC("qpdf", "qpdf-c called qpdf_find_page_by_oh");
1758     return do_with_oh<int>(
1759         qpdf, oh, return_T<int>(-1), [qpdf](QPDFObjectHandle& o) {
1760             return qpdf->qpdf->findPage(o);
1761         });
1762 }
1763 
qpdf_push_inherited_attributes_to_page(qpdf_data qpdf)1764 QPDF_ERROR_CODE qpdf_push_inherited_attributes_to_page(qpdf_data qpdf)
1765 {
1766     QTC::TC("qpdf", "qpdf-c called qpdf_push_inherited_attributes_to_page");
1767     return trap_errors(qpdf, [](qpdf_data q) {
1768         q->qpdf->pushInheritedAttributesToPage();
1769     });
1770 }
1771 
qpdf_add_page(qpdf_data qpdf,qpdf_data newpage_qpdf,qpdf_oh newpage,QPDF_BOOL first)1772 QPDF_ERROR_CODE qpdf_add_page(
1773     qpdf_data qpdf, qpdf_data newpage_qpdf, qpdf_oh newpage, QPDF_BOOL first)
1774 {
1775     QTC::TC("qpdf", "qpdf-c called qpdf_add_page");
1776     auto page = qpdf_oh_item_internal(newpage_qpdf, newpage);
1777     return trap_errors(qpdf, [&page, first](qpdf_data q) {
1778         q->qpdf->addPage(page, first);
1779     });
1780 }
1781 
qpdf_add_page_at(qpdf_data qpdf,qpdf_data newpage_qpdf,qpdf_oh newpage,QPDF_BOOL before,qpdf_oh refpage)1782 QPDF_ERROR_CODE qpdf_add_page_at(
1783     qpdf_data qpdf, qpdf_data newpage_qpdf, qpdf_oh newpage,
1784     QPDF_BOOL before, qpdf_oh refpage)
1785 {
1786     QTC::TC("qpdf", "qpdf-c called qpdf_add_page_at");
1787     auto page = qpdf_oh_item_internal(newpage_qpdf, newpage);
1788     auto ref = qpdf_oh_item_internal(qpdf, refpage);
1789     return trap_errors(qpdf, [&page, before, &ref](qpdf_data q) {
1790         q->qpdf->addPageAt(page, before, ref);
1791     });
1792 }
1793 
qpdf_remove_page(qpdf_data qpdf,qpdf_oh page)1794 QPDF_ERROR_CODE qpdf_remove_page(qpdf_data qpdf, qpdf_oh page)
1795 {
1796     QTC::TC("qpdf", "qpdf-c called qpdf_remove_page");
1797     auto p = qpdf_oh_item_internal(qpdf, page);
1798     return trap_errors(qpdf, [&p](qpdf_data q) {
1799         q->qpdf->removePage(p);
1800     });
1801 }
1802