mirror of
https://github.com/qpdf/qpdf.git
synced 2024-06-03 19:00:51 +00:00
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.
This commit is contained in:
parent
b1b789df42
commit
b1dad0de2a
|
@ -1,3 +1,11 @@
|
||||||
|
2024-02-11 Jay Berkenbilt <ejb@ql.org>
|
||||||
|
|
||||||
|
* The previous fix to #1056 was incomplete. When setting a check
|
||||||
|
box value, the previous fix allowed any value other than /Off to
|
||||||
|
mean checked. Now we also set the actual value based on the
|
||||||
|
allowable non-/Off value in the normal appearance dictionary.
|
||||||
|
Fixes #1056.
|
||||||
|
|
||||||
2024-02-03 Jay Berkenbilt <ejb@ql.org>
|
2024-02-03 Jay Berkenbilt <ejb@ql.org>
|
||||||
|
|
||||||
* Add fuzz testing for JSON.
|
* Add fuzz testing for JSON.
|
||||||
|
|
|
@ -166,7 +166,9 @@ class QPDFFormFieldObjectHelper: public QPDFObjectHelper
|
||||||
// either /Tx (text) or /Ch (choice), set /NeedAppearances to true. You can explicitly tell this
|
// either /Tx (text) or /Ch (choice), set /NeedAppearances to true. You can explicitly tell this
|
||||||
// method not to set /NeedAppearances if you are going to generate an appearance stream
|
// method not to set /NeedAppearances if you are going to generate an appearance stream
|
||||||
// yourself. Starting with qpdf 8.3.0, this method handles fields of type /Btn (checkboxes,
|
// yourself. Starting with qpdf 8.3.0, this method handles fields of type /Btn (checkboxes,
|
||||||
// radio buttons, pushbuttons) specially.
|
// radio buttons, pushbuttons) specially. When setting a checkbox value, any value other than
|
||||||
|
// /Off will be treated as on, and the actual value set will be based on the appearance stream's
|
||||||
|
// /N dictionary, so the value that ends up in /V may not exactly match the value you pass in.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
void setV(QPDFObjectHandle value, bool need_appearances = true);
|
void setV(QPDFObjectHandle value, bool need_appearances = true);
|
||||||
|
|
||||||
|
|
|
@ -310,8 +310,8 @@ QPDFFormFieldObjectHelper::setV(QPDFObjectHandle value, bool need_appearances)
|
||||||
setCheckBoxValue((name != "/Off"));
|
setCheckBoxValue((name != "/Off"));
|
||||||
}
|
}
|
||||||
if (!okay) {
|
if (!okay) {
|
||||||
this->oh.warnIfPossible("ignoring attempt to set a checkbox field to a value of "
|
this->oh.warnIfPossible(
|
||||||
"other than /Yes or /Off");
|
"ignoring attempt to set a checkbox field to a value whose type is not name");
|
||||||
}
|
}
|
||||||
} else if (isRadioButton()) {
|
} else if (isRadioButton()) {
|
||||||
if (value.isName()) {
|
if (value.isName()) {
|
||||||
|
@ -415,9 +415,6 @@ QPDFFormFieldObjectHelper::setRadioButtonValue(QPDFObjectHandle name)
|
||||||
void
|
void
|
||||||
QPDFFormFieldObjectHelper::setCheckBoxValue(bool value)
|
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 AP = this->oh.getKey("/AP");
|
||||||
QPDFObjectHandle annot;
|
QPDFObjectHandle annot;
|
||||||
if (AP.isNull()) {
|
if (AP.isNull()) {
|
||||||
|
@ -439,6 +436,29 @@ QPDFFormFieldObjectHelper::setCheckBoxValue(bool value)
|
||||||
} else {
|
} else {
|
||||||
annot = this->oh;
|
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()) {
|
if (!annot.isInitialized()) {
|
||||||
QTC::TC("qpdf", "QPDFObjectHandle broken checkbox");
|
QTC::TC("qpdf", "QPDFObjectHandle broken checkbox");
|
||||||
this->oh.warnIfPossible("unable to set the value of this checkbox");
|
this->oh.warnIfPossible("unable to set the value of this checkbox");
|
||||||
|
|
|
@ -122,7 +122,7 @@ endobj
|
||||||
>>
|
>>
|
||||||
/P 15 0 R
|
/P 15 0 R
|
||||||
/T (checkbox1)
|
/T (checkbox1)
|
||||||
/V /Yes
|
/V /Yup
|
||||||
>>
|
>>
|
||||||
endobj
|
endobj
|
||||||
|
|
||||||
|
@ -589,10 +589,10 @@ endobj
|
||||||
/AP <<
|
/AP <<
|
||||||
/N <<
|
/N <<
|
||||||
/Off 64 0 R
|
/Off 64 0 R
|
||||||
/Yes 66 0 R
|
/Yup 66 0 R
|
||||||
>>
|
>>
|
||||||
>>
|
>>
|
||||||
/AS /Yes
|
/AS /Yup
|
||||||
/F 4
|
/F 4
|
||||||
/Rect [
|
/Rect [
|
||||||
118.649
|
118.649
|
||||||
|
|
|
@ -3481,7 +3481,7 @@ endobj
|
||||||
/AP <<
|
/AP <<
|
||||||
/N <<
|
/N <<
|
||||||
/Off 24 0 R
|
/Off 24 0 R
|
||||||
/Yes 26 0 R
|
/Yup 26 0 R
|
||||||
>>
|
>>
|
||||||
>>
|
>>
|
||||||
/AS /Off
|
/AS /Off
|
||||||
|
|
|
@ -1942,7 +1942,9 @@ test_51(QPDF& pdf, char const* arg2)
|
||||||
} else if (Tval == "checkbox1") {
|
} else if (Tval == "checkbox1") {
|
||||||
std::cout << "turning checkbox1 on\n";
|
std::cout << "turning checkbox1 on\n";
|
||||||
QPDFFormFieldObjectHelper foh(field);
|
QPDFFormFieldObjectHelper foh(field);
|
||||||
foh.setV(QPDFObjectHandle::newName("/Yes"));
|
// The value that eventually gets set is based on what's allowed in /N and may not match
|
||||||
|
// this value.
|
||||||
|
foh.setV(QPDFObjectHandle::newName("/Sure"));
|
||||||
} else if (Tval == "checkbox2") {
|
} else if (Tval == "checkbox2") {
|
||||||
std::cout << "turning checkbox2 off\n";
|
std::cout << "turning checkbox2 off\n";
|
||||||
QPDFFormFieldObjectHelper foh(field);
|
QPDFFormFieldObjectHelper foh(field);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user