From b1dad0de2a12a0feb0608d1f68f3f1e8144592e6 Mon Sep 17 00:00:00 2001 From: Jay Berkenbilt Date: Sun, 11 Feb 2024 15:32:02 -0500 Subject: Fix previous fix to setting checkbox value (fixes #1056) The code accepted values other than /Yes but still used /Yes as the checked value instead of obeying the normal appearance dictionary. --- libqpdf/QPDFFormFieldObjectHelper.cc | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) (limited to 'libqpdf') diff --git a/libqpdf/QPDFFormFieldObjectHelper.cc b/libqpdf/QPDFFormFieldObjectHelper.cc index 371ed271..40627c3d 100644 --- a/libqpdf/QPDFFormFieldObjectHelper.cc +++ b/libqpdf/QPDFFormFieldObjectHelper.cc @@ -310,8 +310,8 @@ QPDFFormFieldObjectHelper::setV(QPDFObjectHandle value, bool need_appearances) setCheckBoxValue((name != "/Off")); } if (!okay) { - this->oh.warnIfPossible("ignoring attempt to set a checkbox field to a value of " - "other than /Yes or /Off"); + this->oh.warnIfPossible( + "ignoring attempt to set a checkbox field to a value whose type is not name"); } } else if (isRadioButton()) { if (value.isName()) { @@ -415,9 +415,6 @@ QPDFFormFieldObjectHelper::setRadioButtonValue(QPDFObjectHandle name) void QPDFFormFieldObjectHelper::setCheckBoxValue(bool value) { - // Set /AS to /Yes or /Off in addition to setting /V. - QPDFObjectHandle name = QPDFObjectHandle::newName(value ? "/Yes" : "/Off"); - setFieldAttribute("/V", name); QPDFObjectHandle AP = this->oh.getKey("/AP"); QPDFObjectHandle annot; if (AP.isNull()) { @@ -439,6 +436,29 @@ QPDFFormFieldObjectHelper::setCheckBoxValue(bool value) } else { annot = this->oh; } + std::string on_value; + if (value) { + // Set the "on" value to the first value in the appearance stream's normal state dictionary + // that isn't /Off. If not found, fall back to /Yes. + if (AP.isDictionary()) { + auto N = AP.getKey("/N"); + if (N.isDictionary()) { + for (auto const& iter: N.ditems()) { + if (iter.first != "/Off") { + on_value = iter.first; + break; + } + } + } + } + if (on_value.empty()) { + on_value = "/Yes"; + } + } + + // Set /AS to the on value or /Off in addition to setting /V. + QPDFObjectHandle name = QPDFObjectHandle::newName(value ? on_value : "/Off"); + setFieldAttribute("/V", name); if (!annot.isInitialized()) { QTC::TC("qpdf", "QPDFObjectHandle broken checkbox"); this->oh.warnIfPossible("unable to set the value of this checkbox"); -- cgit v1.2.3-54-g00ecf