This commit is contained in:
m-holger 2024-04-28 15:31:07 -04:00 committed by GitHub
commit f9eff0bd0f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
22 changed files with 2019 additions and 1907 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,138 @@
// Copyright (c) 2005-2024 Jay Berkenbilt
//
// This file is part of qpdf.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Versions of qpdf prior to version 7 were released under the terms
// of version 2.0 of the Artistic License. At your option, you may
// continue to consider qpdf to be licensed under those terms. Please
// see the manual for additional information.
#ifndef QPDFOBJECTHANDLE_TYPED_HH
#define QPDFOBJECTHANDLE_TYPED_HH
#include <bitset>
class QPDFObjectHandle::Typed
{
public:
operator QPDFObjectHandle() const
{
return oh;
}
QPDF_DLL
operator bool() noexcept
{
return flags.test(fl_valid);
}
QPDF_DLL
operator bool() const noexcept
{
return flags.test(fl_valid);
}
QPDF_DLL
bool
null() const noexcept
{
return flags.test(fl_null);
}
QPDF_DLL
QPDFObjGen
getObjGen() const
{
return oh.getObjGen();
}
// ... and all the other methods applicable to all object types.
protected:
using Flags = std::bitset<3>;
enum flags { fl_valid, fl_null, fl_no_type_check };
Typed() = default;
Typed(QPDFObjectHandle const& oh, Flags flags) :
oh(oh),
flags(flags)
{
}
Typed(QPDFObjectHandle&& oh, Flags flags) :
oh(std::move(oh)),
flags(flags)
{
}
Typed(Typed const&) = default;
Typed(Typed&&) = default;
Typed& operator=(Typed const&) = default;
Typed& operator=(Typed&&) = default;
~Typed() = default;
QPDFObjectHandle oh;
Flags flags{};
};
class QPDFObjectHandle::Integer: public QPDFObjectHandle::Typed
{
friend class QPDFObjectHandle;
public:
QPDF_DLL
operator long long();
QPDF_DLL
operator int();
QPDF_DLL
operator unsigned long long();
QPDF_DLL
operator unsigned int();
QPDF_DLL
long long
value()
{
return *this;
}
template <typename T>
bool
assign_to(T& var)
{
if (flags.test(0)) {
var = *this;
return true;
}
return false;
}
private:
Integer() = default;
Integer(QPDFObjectHandle const& oh, Flags flags) :
QPDFObjectHandle::Typed(oh, flags)
{
}
Integer(QPDFObjectHandle&& oh, QPDF_Integer* ptr, Flags flags) :
QPDFObjectHandle::Typed(std::move(oh), flags)
{
}
};
#endif // QPDFOBJECTHANDLE_TYPED_HH

View File

@ -686,7 +686,7 @@ QPDF::read_xref(qpdf_offset_t xref_offset)
if (!m->trailer.isInitialized()) {
throw damagedPDF("", 0, "unable to find trailer while reading xref");
}
int size = m->trailer.getKey("/Size").getIntValueAsInt();
int size = m->trailer.getKey("/Size").asInteger();
int max_obj = 0;
if (!m->xref_table.empty()) {
max_obj = (*(m->xref_table.rbegin())).first.getObj();
@ -912,17 +912,13 @@ QPDF::read_xrefTable(qpdf_offset_t xref_offset)
}
}
if (cur_trailer.hasKey("/XRefStm")) {
if (m->ignore_xref_streams) {
QTC::TC("qpdf", "QPDF ignoring XRefStm in trailer");
} else {
if (cur_trailer.getKey("/XRefStm").isInteger()) {
// Read the xref stream but disregard any return value -- we'll use our trailer's
// /Prev key instead of the xref stream's.
(void)read_xrefStream(cur_trailer.getKey("/XRefStm").getIntValue());
} else {
throw damagedPDF("xref stream", xref_offset, "invalid /XRefStm");
}
if (!m->ignore_xref_streams) {
if (auto offset = cur_trailer.getKey("/XRefStm").asInteger()) {
// Read the xref stream but disregard any return value -- we'll use our trailer's
// /Prev key instead of the xref stream's.
(void)read_xrefStream(offset);
} else if (!offset.null()) {
throw damagedPDF("xref stream", xref_offset, "invalid /XRefStm");
}
}
@ -931,15 +927,12 @@ QPDF::read_xrefTable(qpdf_offset_t xref_offset)
insertFreeXrefEntry(og);
}
if (cur_trailer.hasKey("/Prev")) {
if (!cur_trailer.getKey("/Prev").isInteger()) {
QTC::TC("qpdf", "QPDF trailer prev not integer");
throw damagedPDF("trailer", "/Prev key in trailer dictionary is not an integer");
}
QTC::TC("qpdf", "QPDF prev key in trailer dictionary");
xref_offset = cur_trailer.getKey("/Prev").getIntValue();
if (auto prev = cur_trailer.getKey("/Prev").asInteger(true)) {
QTC::TC("qpdf", "QPDF prev key in trailer dictionary", prev.null() ? 0 : 1);
return prev;
} else {
xref_offset = 0;
QTC::TC("qpdf", "QPDF trailer prev not integer");
throw damagedPDF("trailer", "/Prev key in trailer dictionary is not an integer");
}
return xref_offset;
@ -987,7 +980,7 @@ QPDF::processXRefStream(qpdf_offset_t xref_offset, QPDFObjectHandle& xref_obj)
size_t entry_size = 0;
int max_bytes = sizeof(qpdf_offset_t);
for (int i = 0; i < 3; ++i) {
W[i] = W_obj.getArrayItem(i).getIntValueAsInt();
W[i] = W_obj.getArrayItem(i).asInteger();
if (W[i] > max_bytes) {
throw damagedPDF(
"xref stream",
@ -1013,8 +1006,8 @@ QPDF::processXRefStream(qpdf_offset_t xref_offset, QPDFObjectHandle& xref_obj)
"values");
}
for (int i = 0; i < n_index; ++i) {
if (Index_obj.getArrayItem(i).isInteger()) {
indx.push_back(Index_obj.getArrayItem(i).getIntValue());
if (auto index = Index_obj.getArrayItem(i).asInteger()) {
indx.emplace_back(index);
} else {
throw damagedPDF(
"xref stream",
@ -1026,9 +1019,8 @@ QPDF::processXRefStream(qpdf_offset_t xref_offset, QPDFObjectHandle& xref_obj)
QTC::TC("qpdf", "QPDF xref /Index is array", n_index == 2 ? 0 : 1);
} else {
QTC::TC("qpdf", "QPDF xref /Index is null");
long long size = dict.getKey("/Size").getIntValue();
indx.push_back(0);
indx.push_back(size);
indx.emplace_back(0);
indx.emplace_back(dict.getKey("/Size").asInteger());
}
size_t num_entries = 0;
@ -1131,18 +1123,12 @@ QPDF::processXRefStream(qpdf_offset_t xref_offset, QPDFObjectHandle& xref_obj)
setTrailer(dict);
}
if (dict.hasKey("/Prev")) {
if (!dict.getKey("/Prev").isInteger()) {
throw damagedPDF(
"xref stream", "/Prev key in xref stream dictionary is not an integer");
}
if (auto prev = dict.getKey("/Prev").asInteger(true)) {
QTC::TC("qpdf", "QPDF prev key in xref stream dictionary");
xref_offset = dict.getKey("/Prev").getIntValue();
return prev;
} else {
xref_offset = 0;
throw damagedPDF("xref stream", "/Prev key in xref stream dictionary is not an integer");
}
return xref_offset;
}
void
@ -1368,25 +1354,22 @@ QPDF::readStream(QPDFObjectHandle& object, QPDFObjGen og, qpdf_offset_t offset)
size_t length = 0;
try {
auto length_obj = object.getKey("/Length");
if (!length_obj.isInteger()) {
if (length_obj.isNull()) {
QTC::TC("qpdf", "QPDF stream without length");
throw damagedPDF(offset, "stream dictionary lacks /Length key");
if (auto length_obj = object.getKey("/Length").asInteger()) {
length = toS(length_obj.value());
// Seek in two steps to avoid potential integer overflow
m->file->seek(stream_offset, SEEK_SET);
m->file->seek(toO(length), SEEK_CUR);
if (!readToken(m->file).isWord("endstream")) {
QTC::TC("qpdf", "QPDF missing endstream");
throw damagedPDF("expected endstream");
}
} else if (length_obj.null()) {
QTC::TC("qpdf", "QPDF stream without length");
throw damagedPDF(offset, "stream dictionary lacks /Length key");
} else {
QTC::TC("qpdf", "QPDF stream length not integer");
throw damagedPDF(offset, "/Length key in stream dictionary is not an integer");
}
length = toS(length_obj.getUIntValue());
// Seek in two steps to avoid potential integer overflow
m->file->seek(stream_offset, SEEK_SET);
m->file->seek(toO(length), SEEK_CUR);
if (!readToken(m->file).isWord("endstream")) {
QTC::TC("qpdf", "QPDF missing endstream");
throw damagedPDF("expected endstream");
}
} catch (QPDFExc& e) {
if (m->attempt_recovery) {
warn(e);
@ -1778,15 +1761,14 @@ QPDF::resolveObjectsInStream(int obj_stream_number)
warn(damagedPDF(
"supposed object stream " + std::to_string(obj_stream_number) + " has wrong type"));
}
if (!(dict.getKey("/N").isInteger() && dict.getKey("/First").isInteger())) {
int n{0};
long long first{0};
if (!(dict.getKey("/N").asInteger().assign_to(n) &&
dict.getKey("/First").asInteger().assign_to(first))) {
throw damagedPDF(
("object stream " + std::to_string(obj_stream_number) + " has incorrect keys"));
}
int n = dict.getKey("/N").getIntValueAsInt();
int first = dict.getKey("/First").getIntValueAsInt();
std::map<int, int> offsets;
std::shared_ptr<Buffer> bp = obj_stream.getStreamData(qpdf_dl_specialized);
@ -2328,21 +2310,11 @@ QPDF::getPDFVersion() const
int
QPDF::getExtensionLevel()
{
int result = 0;
QPDFObjectHandle obj = getRoot();
if (obj.hasKey("/Extensions")) {
obj = obj.getKey("/Extensions");
if (obj.isDictionary() && obj.hasKey("/ADBE")) {
obj = obj.getKey("/ADBE");
if (obj.isDictionary() && obj.hasKey("/ExtensionLevel")) {
obj = obj.getKey("/ExtensionLevel");
if (obj.isInteger()) {
result = obj.getIntValueAsInt();
}
}
}
}
return result;
return getRoot()
.getKey("/Extensions")
.getKeyIfDict("/ADBE")
.getKeyIfDict("/ExtensionLevel")
.asInteger(true);
}
QPDFObjectHandle

View File

@ -740,9 +740,7 @@ QPDFAcroFormDocumentHelper::transformAnnotations(
if (acroform.getKey("/DA").isString()) {
default_da = acroform.getKey("/DA").getUTF8Value();
}
if (acroform.getKey("/Q").isInteger()) {
default_q = acroform.getKey("/Q").getIntValueAsInt();
}
acroform.getKey("/Q").asInteger().assign_to(default_q);
}
if (from_acroform.isDictionary()) {
if (from_acroform.getKey("/DR").isDictionary()) {
@ -755,9 +753,7 @@ QPDFAcroFormDocumentHelper::transformAnnotations(
if (from_acroform.getKey("/DA").isString()) {
from_default_da = from_acroform.getKey("/DA").getUTF8Value();
}
if (from_acroform.getKey("/Q").isInteger()) {
from_default_q = from_acroform.getKey("/Q").getIntValueAsInt();
}
from_acroform.getKey("/Q").asInteger().assign_to(from_default_q);
}
if (from_default_da != default_da) {
override_da = true;

View File

@ -42,8 +42,8 @@ QPDFAnnotationObjectHelper::getAppearanceState()
int
QPDFAnnotationObjectHelper::getFlags()
{
QPDFObjectHandle flags_obj = this->oh.getKey("/F");
return flags_obj.isInteger() ? flags_obj.getIntValueAsInt() : 0;
auto flags_obj = this->oh.getKey("/F").asInteger();
return flags_obj ? flags_obj : 0;
}
QPDFObjectHandle

View File

@ -57,11 +57,8 @@ QPDFEFStreamObjectHelper::getModDate()
size_t
QPDFEFStreamObjectHelper::getSize()
{
auto val = getParam("/Size");
if (val.isInteger()) {
return QIntC::to_size(val.getUIntValueAsUInt());
}
return 0;
auto val = getParam("/Size").asInteger();
return val ? QIntC::to_size(val.value()) : 0;
}
std::string

View File

@ -213,25 +213,19 @@ QPDFFormFieldObjectHelper::getDefaultAppearance()
int
QPDFFormFieldObjectHelper::getQuadding()
{
QPDFObjectHandle fv = getInheritableFieldValue("/Q");
bool looked_in_acroform = false;
if (!fv.isInteger()) {
fv = getFieldFromAcroForm("/Q");
looked_in_acroform = true;
if (auto fv = getInheritableFieldValue("/Q").asInteger()) {
QTC::TC("qpdf", "QPDFFormFieldObjectHelper Q present");
return fv;
} else {
QTC::TC("qpdf", "QPDFFormFieldObjectHelper Q present looked");
return getFieldFromAcroForm("/Q").asInteger(true);
}
int result = 0;
if (fv.isInteger()) {
QTC::TC("qpdf", "QPDFFormFieldObjectHelper Q present", looked_in_acroform ? 0 : 1);
result = QIntC::to_int(fv.getIntValue());
}
return result;
}
int
QPDFFormFieldObjectHelper::getFlags()
{
QPDFObjectHandle f = getInheritableFieldValue("/Ff");
return f.isInteger() ? f.getIntValueAsInt() : 0;
return getInheritableFieldValue("/Ff").asInteger(true);
}
bool

View File

@ -130,8 +130,8 @@ ImageOptimizer::makePipeline(std::string const& description, Pipeline* next)
}
return result;
}
QPDFObjectHandle components_obj = dict.getKey("/BitsPerComponent");
if (!(components_obj.isInteger() && (components_obj.getIntValue() == 8))) {
auto components_obj = dict.getKey("/BitsPerComponent").asInteger();
if (!(components_obj && (components_obj.value() == 8))) {
QTC::TC("qpdf", "QPDFJob image optimize bits per component");
if (!description.empty()) {
o.doIfVerbose([&](Pipeline& v, std::string const& prefix) {
@ -144,14 +144,14 @@ ImageOptimizer::makePipeline(std::string const& description, Pipeline* next)
// Files have been seen in the wild whose width and height are floating point, which is goofy,
// but we can deal with it.
JDIMENSION w = 0;
if (w_obj.isInteger()) {
w = w_obj.getUIntValueAsUInt();
if (auto w_int = w_obj.asInteger()) {
w = w_int;
} else {
w = static_cast<JDIMENSION>(w_obj.getNumericValue());
}
JDIMENSION h = 0;
if (h_obj.isInteger()) {
h = h_obj.getUIntValueAsUInt();
if (auto h_int = h_obj.asInteger()) {
h = h_int;
} else {
h = static_cast<JDIMENSION>(h_obj.getNumericValue());
}
@ -216,7 +216,7 @@ ImageOptimizer::evaluate(std::string const& description)
if (!image.pipeStreamData(p.get(), 0, qpdf_dl_specialized)) {
return false;
}
long long orig_length = image.getDict().getKey("/Length").getIntValue();
long long orig_length = image.getDict().getKey("/Length").asInteger();
if (c.getCount() >= orig_length) {
QTC::TC("qpdf", "QPDFJob image optimize no shrink");
o.doIfVerbose([&](Pipeline& v, std::string const& prefix) {
@ -858,8 +858,8 @@ QPDFJob::doShowPages(QPDF& pdf)
std::string const& name = iter2.first;
QPDFObjectHandle image = iter2.second;
QPDFObjectHandle dict = image.getDict();
int width = dict.getKey("/Width").getIntValueAsInt();
int height = dict.getKey("/Height").getIntValueAsInt();
int width = dict.getKey("/Width").asInteger();
int height = dict.getKey("/Height").asInteger();
cout << " " << name << ": " << image.unparse() << ", " << width << " x "
<< height << "\n";
}
@ -1651,7 +1651,7 @@ QPDFJob::doInspection(QPDF& pdf)
}
if (m->show_npages) {
QTC::TC("qpdf", "QPDFJob npages");
cout << pdf.getRoot().getKey("/Pages").getKey("/Count").getIntValue() << "\n";
cout << pdf.getRoot().getKey("/Pages").getKey("/Count").asInteger().value() << "\n";
}
if (m->show_encryption) {
showEncryption(pdf);
@ -3081,10 +3081,9 @@ QPDFJob::writeOutfile(QPDF& pdf)
try {
QUtil::remove_file(backup.c_str());
} catch (QPDFSystemError& e) {
*m->log->getError()
<< m->message_prefix << ": unable to delete original file (" << e.what() << ");"
<< " original file left in " << backup
<< ", but the input was successfully replaced\n";
*m->log->getError() << m->message_prefix << ": unable to delete original file ("
<< e.what() << ");" << " original file left in " << backup
<< ", but the input was successfully replaced\n";
}
}
}

View File

@ -22,12 +22,14 @@ namespace
int
compareKeys(QPDFObjectHandle a, QPDFObjectHandle b) const override
{
if (!(keyValid(a) && keyValid(b))) {
auto ai = a.asInteger();
auto bi = b.asInteger();
if (!(ai && bi)) {
// We don't call this without calling keyValid first
throw std::logic_error("comparing invalid keys");
}
auto as = a.getIntValue();
auto bs = b.getIntValue();
auto as = ai.value();
auto bs = bi.value();
return ((as < bs) ? -1 : (as > bs) ? 1 : 0);
}
};
@ -91,7 +93,7 @@ QPDFNumberTreeObjectHelper::iterator::updateIValue()
{
if (impl->valid()) {
auto p = *impl;
this->ivalue.first = p->first.getIntValue();
this->ivalue.first = p->first.asInteger();
this->ivalue.second = p->second;
} else {
this->ivalue.first = 0;

View File

@ -273,12 +273,6 @@ QPDFObjectHandle::asInlineImage()
return dereference() ? obj->as<QPDF_InlineImage>() : nullptr;
}
QPDF_Integer*
QPDFObjectHandle::asInteger()
{
return dereference() ? obj->as<QPDF_Integer>() : nullptr;
}
QPDF_Name*
QPDFObjectHandle::asName()
{
@ -499,110 +493,123 @@ QPDFObjectHandle::getValueAsBool(bool& value)
// Integer accessors
QPDFObjectHandle::Integer
QPDFObjectHandle::asInteger(bool optional)
{
if (isInteger()) {
return {*this, 1U};
}
if (isNull()) {
return {*this, optional ? 3U : 2U};
}
return {*this, 0U};
}
QPDFObjectHandle::Integer::operator long long()
{
if (flags == 1U) {
if (auto ptr = oh.obj ? oh.obj->as<QPDF_Integer>() : nullptr) {
return ptr->getVal();
} else {
throw std::logic_error("object changed");
}
}
if (!flags.test(fl_valid)) {
oh.typeWarning("integer", "returning 0");
}
QTC::TC("qpdf", "QPDFObjectHandle integer returning 0");
return 0;
}
QPDFObjectHandle::Integer::operator int()
{
auto value = operator long long();
if (value < INT_MIN) {
QTC::TC("qpdf", "QPDFObjectHandle int returning INT_MIN");
oh.warnIfPossible("requested value of integer is too small; returning INT_MIN");
return INT_MIN;
}
if (value > INT_MAX) {
QTC::TC("qpdf", "QPDFObjectHandle int returning INT_MAX");
oh.warnIfPossible("requested value of integer is too big; returning INT_MAX");
return INT_MAX;
}
return static_cast<int>(value);
}
QPDFObjectHandle::Integer::operator unsigned long long()
{
auto value = operator long long();
if (value < 0) {
QTC::TC("qpdf", "QPDFObjectHandle uint returning 0");
oh.warnIfPossible("unsigned value request for negative number; returning 0");
return 0;
}
return static_cast<unsigned long long>(value);
}
QPDFObjectHandle::Integer::operator unsigned int()
{
auto value = operator long long();
if (value < 0) {
QTC::TC("qpdf", "QPDFObjectHandle uint uint returning 0");
oh.warnIfPossible("unsigned integer value request for negative number; returning 0");
return 0;
}
if (value > UINT_MAX) {
QTC::TC("qpdf", "QPDFObjectHandle uint returning UINT_MAX");
oh.warnIfPossible("requested value of unsigned integer is too big; returning UINT_MAX");
return UINT_MAX;
}
return static_cast<unsigned int>(value);
}
long long
QPDFObjectHandle::getIntValue()
{
auto integer = asInteger();
if (integer) {
return integer->getVal();
} else {
typeWarning("integer", "returning 0");
QTC::TC("qpdf", "QPDFObjectHandle integer returning 0");
return 0;
}
return asInteger();
}
bool
QPDFObjectHandle::getValueAsInt(long long& value)
{
auto integer = asInteger();
if (integer == nullptr) {
return false;
}
value = integer->getVal();
return true;
return asInteger().assign_to(value);
}
int
QPDFObjectHandle::getIntValueAsInt()
{
int result = 0;
long long v = getIntValue();
if (v < INT_MIN) {
QTC::TC("qpdf", "QPDFObjectHandle int returning INT_MIN");
warnIfPossible("requested value of integer is too small; returning INT_MIN");
result = INT_MIN;
} else if (v > INT_MAX) {
QTC::TC("qpdf", "QPDFObjectHandle int returning INT_MAX");
warnIfPossible("requested value of integer is too big; returning INT_MAX");
result = INT_MAX;
} else {
result = static_cast<int>(v);
}
return result;
return asInteger();
}
bool
QPDFObjectHandle::getValueAsInt(int& value)
{
if (!isInteger()) {
return false;
}
value = getIntValueAsInt();
return true;
return asInteger().assign_to(value);
}
unsigned long long
QPDFObjectHandle::getUIntValue()
{
unsigned long long result = 0;
long long v = getIntValue();
if (v < 0) {
QTC::TC("qpdf", "QPDFObjectHandle uint returning 0");
warnIfPossible("unsigned value request for negative number; returning 0");
} else {
result = static_cast<unsigned long long>(v);
}
return result;
return asInteger();
}
bool
QPDFObjectHandle::getValueAsUInt(unsigned long long& value)
{
if (!isInteger()) {
return false;
}
value = getUIntValue();
return true;
return asInteger().assign_to(value);
}
unsigned int
QPDFObjectHandle::getUIntValueAsUInt()
{
unsigned int result = 0;
long long v = getIntValue();
if (v < 0) {
QTC::TC("qpdf", "QPDFObjectHandle uint uint returning 0");
warnIfPossible("unsigned integer value request for negative number; returning 0");
result = 0;
} else if (v > UINT_MAX) {
QTC::TC("qpdf", "QPDFObjectHandle uint returning UINT_MAX");
warnIfPossible("requested value of unsigned integer is too big; returning UINT_MAX");
result = UINT_MAX;
} else {
result = static_cast<unsigned int>(v);
}
return result;
return asInteger();
}
bool
QPDFObjectHandle::getValueAsUInt(unsigned int& value)
{
if (!isInteger()) {
return false;
}
value = getUIntValueAsUInt();
return true;
return asInteger().assign_to(value);
}
// Real accessors

View File

@ -83,11 +83,7 @@ QPDFOutlineObjectHelper::getDestPage()
int
QPDFOutlineObjectHelper::getCount()
{
int count = 0;
if (this->oh.hasKey("/Count")) {
count = this->oh.getKey("/Count").getIntValueAsInt();
}
return count;
return this->oh.getKey("/Count").asInteger(true);
}
std::string

View File

@ -88,11 +88,7 @@ QPDFPageDocumentHelper::flattenAnnotationsForPage(
std::vector<QPDFAnnotationObjectHelper> annots = page.getAnnotations();
std::vector<QPDFObjectHandle> new_annots;
std::string new_content;
int rotate = 0;
QPDFObjectHandle rotate_obj = page.getObjectHandle().getKey("/Rotate");
if (rotate_obj.isInteger() && rotate_obj.getIntValue()) {
rotate = rotate_obj.getIntValueAsInt();
}
int rotate = page.getObjectHandle().getKey("/Rotate").asInteger(true);
int next_fx = 1;
for (auto& aoh: annots) {
QPDFObjectHandle as = aoh.getAppearanceStream("/N");

View File

@ -36,11 +36,8 @@ QPDFPageLabelDocumentHelper::getLabelForPage(long long page_idx)
}
QPDFObjectHandle S = label.getKey("/S"); // type (D, R, r, A, a)
QPDFObjectHandle P = label.getKey("/P"); // prefix
QPDFObjectHandle St = label.getKey("/St"); // starting number
long long start = 1;
if (St.isInteger()) {
start = St.getIntValue();
}
auto St = label.getKey("/St").asInteger(); // starting number
long long start = St ? St : 1;
QIntC::range_check(start, offset);
start += offset;
result = QPDFObjectHandle::newDictionary();
@ -72,14 +69,14 @@ QPDFPageLabelDocumentHelper::getLabelsForPageRange(
bool skip_first = false;
if (size >= 2) {
QPDFObjectHandle last = new_labels.at(size - 1);
QPDFObjectHandle last_idx = new_labels.at(size - 2);
if (last_idx.isInteger() && last.isDictionary() &&
auto last_idx = new_labels.at(size - 2).asInteger();
auto st = label.getKey("/St").asInteger();
auto last_st = last.getKey("/St").asInteger();
if (last_idx && last.isDictionary() &&
(label.getKey("/S").unparse() == last.getKey("/S").unparse()) &&
(label.getKey("/P").unparse() == last.getKey("/P").unparse()) &&
label.getKey("/St").isInteger() && last.getKey("/St").isInteger()) {
long long int st_delta =
label.getKey("/St").getIntValue() - last.getKey("/St").getIntValue();
long long int idx_delta = new_start_idx - last_idx.getIntValue();
(label.getKey("/P").unparse() == last.getKey("/P").unparse()) && st && last_st) {
auto st_delta = st.value() - last_st.value();
auto idx_delta = new_start_idx - last_idx.value();
if (st_delta == idx_delta) {
QTC::TC("qpdf", "QPDFPageLabelDocumentHelper skip first");
skip_first = true;

View File

@ -667,14 +667,14 @@ QPDFPageObjectHelper::getMatrixForTransformations(bool invert)
if (!bbox.isRectangle()) {
return matrix;
}
QPDFObjectHandle rotate_obj = getAttribute("/Rotate", false);
auto rotate_obj = getAttribute("/Rotate", false).asInteger();
QPDFObjectHandle scale_obj = getAttribute("/UserUnit", false);
if (!(rotate_obj.isNull() && scale_obj.isNull())) {
if (!(rotate_obj.null() && scale_obj.isNull())) {
QPDFObjectHandle::Rectangle rect = bbox.getArrayAsRectangle();
double width = rect.urx - rect.llx;
double height = rect.ury - rect.lly;
double scale = (scale_obj.isNumber() ? scale_obj.getNumericValue() : 1.0);
int rotate = (rotate_obj.isInteger() ? rotate_obj.getIntValueAsInt() : 0);
int rotate = rotate_obj ? rotate_obj : 0;
if (invert) {
if (scale == 0.0) {
return matrix;
@ -863,12 +863,9 @@ QPDFPageObjectHelper::flattenRotation(QPDFAcroFormDocumentHelper* afdh)
{
QPDF& qpdf =
this->oh.getQPDF("QPDFPageObjectHelper::flattenRotation called with a direct object");
auto rotate_oh = this->oh.getKey("/Rotate");
int rotate = 0;
if (rotate_oh.isInteger()) {
rotate = rotate_oh.getIntValueAsInt();
}
if (!((rotate == 90) || (rotate == 180) || (rotate == 270))) {
auto rotate_key = this->oh.getKey("/Rotate").asInteger();
int rotate = rotate_key ? rotate_key : 0;
if (!(rotate == 90 || rotate == 180 || rotate == 270)) {
return;
}
auto mediabox = this->oh.getKey("/MediaBox");

View File

@ -656,10 +656,11 @@ QPDFWriter::copyEncryptionParameters(QPDF& qpdf)
generateID();
m->id1 = trailer.getKey("/ID").getArrayItem(0).getStringValue();
QPDFObjectHandle encrypt = trailer.getKey("/Encrypt");
int V = encrypt.getKey("/V").getIntValueAsInt();
int V = encrypt.getKey("/V").asInteger();
int key_len = 5;
if (V > 1) {
key_len = encrypt.getKey("/Length").getIntValueAsInt() / 8;
key_len = encrypt.getKey("/Length").asInteger();
key_len /= 8;
}
if (encrypt.hasKey("/EncryptMetadata") && encrypt.getKey("/EncryptMetadata").isBool()) {
m->encrypt_metadata = encrypt.getKey("/EncryptMetadata").getBoolValue();
@ -687,9 +688,9 @@ QPDFWriter::copyEncryptionParameters(QPDF& qpdf)
setEncryptionParametersInternal(
V,
encrypt.getKey("/R").getIntValueAsInt(),
encrypt.getKey("/R").asInteger(),
key_len,
static_cast<int>(encrypt.getKey("/P").getIntValue()),
static_cast<int>(encrypt.getKey("/P").asInteger().value()),
encrypt.getKey("/O").getStringValue(),
encrypt.getKey("/U").getStringValue(),
OE,
@ -1415,10 +1416,10 @@ QPDFWriter::unparseObject(
if (extensions.isInitialized()) {
QTC::TC("qpdf", "QPDFWriter preserve Extensions");
QPDFObjectHandle adbe = extensions.getKey("/ADBE");
auto ext_level = adbe.getKeyIfDict("/ExtensionLevel").asInteger();
if (adbe.isDictionary() &&
adbe.getKey("/BaseVersion").isNameAndEquals("/" + m->final_pdf_version) &&
adbe.getKey("/ExtensionLevel").isInteger() &&
(adbe.getKey("/ExtensionLevel").getIntValue() == m->final_extension_level)) {
ext_level && (static_cast<int>(ext_level) == m->final_extension_level)) {
QTC::TC("qpdf", "QPDFWriter preserve ADBE");
} else {
if (need_extensions_adbe) {

View File

@ -586,7 +586,7 @@ QPDF_Stream::pipeStreamData(
qpdf_offset_t actual_length = count.getCount();
qpdf_offset_t desired_length = 0;
if (success && this->stream_dict.hasKey("/Length")) {
desired_length = this->stream_dict.getKey("/Length").getIntValue();
desired_length = this->stream_dict.getKey("/Length").asInteger();
if (actual_length == desired_length) {
QTC::TC("qpdf", "QPDF_Stream pipe use stream provider");
} else {

View File

@ -766,21 +766,22 @@ QPDF::initializeEncryption()
m->file->getLastOffset(),
"file uses encryption SubFilters, which qpdf does not support");
}
if (!(encryption_dict.getKey("/V").isInteger() && encryption_dict.getKey("/R").isInteger() &&
int V{0};
int R{0};
long long p_temp{0};
if (!(encryption_dict.getKey("/V").asInteger().assign_to(V) &&
encryption_dict.getKey("/R").asInteger().assign_to(R) &&
encryption_dict.getKey("/O").isString() && encryption_dict.getKey("/U").isString() &&
encryption_dict.getKey("/P").isInteger())) {
encryption_dict.getKey("/P").asInteger().assign_to(p_temp))) {
throw damagedPDF(
"encryption dictionary",
"some encryption dictionary parameters are missing or the wrong "
"type");
}
int V = encryption_dict.getKey("/V").getIntValueAsInt();
int R = encryption_dict.getKey("/R").getIntValueAsInt();
std::string O = encryption_dict.getKey("/O").getStringValue();
std::string U = encryption_dict.getKey("/U").getStringValue();
int P = static_cast<int>(encryption_dict.getKey("/P").getIntValue());
int P = static_cast<int>(p_temp);
// If supporting new encryption R/V values, remember to update error message inside this if
// statement.
@ -840,8 +841,8 @@ QPDF::initializeEncryption()
} else if (V == 5) {
Length = 256;
} else {
if (encryption_dict.getKey("/Length").isInteger()) {
Length = encryption_dict.getKey("/Length").getIntValueAsInt();
if (auto l = encryption_dict.getKey("/Length").asInteger()) {
Length = l;
if ((Length % 8) || (Length < 40) || (Length > 128)) {
Length = 0;
}
@ -1249,12 +1250,9 @@ QPDF::isEncrypted(
if (m->encp->encrypted) {
QPDFObjectHandle trailer = getTrailer();
QPDFObjectHandle encrypt = trailer.getKey("/Encrypt");
QPDFObjectHandle Pkey = encrypt.getKey("/P");
QPDFObjectHandle Rkey = encrypt.getKey("/R");
QPDFObjectHandle Vkey = encrypt.getKey("/V");
P = static_cast<int>(Pkey.getIntValue());
R = Rkey.getIntValueAsInt();
V = Vkey.getIntValueAsInt();
P = static_cast<int>(static_cast<long long>(encrypt.getKey("/P").asInteger()));
R = encrypt.getKey("/R").asInteger();
V = encrypt.getKey("/V").asInteger();
stream_method = m->encp->cf_stream;
string_method = m->encp->cf_string;
file_method = m->encp->cf_file;

View File

@ -139,9 +139,8 @@ QPDF::isLinearized()
return false;
}
QPDFObjectHandle L = candidate.getKey("/L");
if (L.isInteger()) {
qpdf_offset_t Li = L.getIntValue();
if (auto L = candidate.getKey("/L").asInteger()) {
qpdf_offset_t Li = L;
m->file->seek(0, SEEK_END);
if (Li != m->file->tell()) {
QTC::TC("qpdf", "QPDF /L mismatch");
@ -169,30 +168,28 @@ QPDF::readLinearizationData()
// /L is read and stored in linp by isLinearized()
QPDFObjectHandle H = m->lindict.getKey("/H");
QPDFObjectHandle O = m->lindict.getKey("/O");
QPDFObjectHandle E = m->lindict.getKey("/E");
QPDFObjectHandle N = m->lindict.getKey("/N");
QPDFObjectHandle T = m->lindict.getKey("/T");
QPDFObjectHandle P = m->lindict.getKey("/P");
auto O = m->lindict.getKey("/O").asInteger();
auto E = m->lindict.getKey("/E").asInteger();
auto N = m->lindict.getKey("/N").asInteger();
auto T = m->lindict.getKey("/T").asInteger();
auto P = m->lindict.getKey("/P").asInteger(true);
if (!(H.isArray() && O.isInteger() && E.isInteger() && N.isInteger() && T.isInteger() &&
(P.isInteger() || P.isNull()))) {
if (!(H.isArray() && O && E && N && T && P)) {
throw damagedPDF(
"linearization dictionary",
"some keys in linearization dictionary are of the wrong type");
}
// Hint table array: offset length [ offset length ]
size_t n_H_items = toS(H.getArrayNItems());
int n_H_items = H.getArrayNItems();
if (!((n_H_items == 2) || (n_H_items == 4))) {
throw damagedPDF("linearization dictionary", "H has the wrong number of items");
}
std::vector<int> H_items;
for (size_t i = 0; i < n_H_items; ++i) {
QPDFObjectHandle oh(H.getArrayItem(toI(i)));
if (oh.isInteger()) {
H_items.push_back(oh.getIntValueAsInt());
for (int i = 0; i < n_H_items; ++i) {
if (auto h = H.getArrayItem(toI(i)).asInteger()) {
H_items.push_back(h);
} else {
throw damagedPDF("linearization dictionary", "some H items are of the wrong type");
}
@ -212,28 +209,22 @@ QPDF::readLinearizationData()
}
// P: first page number
int first_page = 0;
if (P.isInteger()) {
QTC::TC("qpdf", "QPDF P present in lindict");
first_page = P.getIntValueAsInt();
} else {
QTC::TC("qpdf", "QPDF P absent in lindict");
}
QTC::TC("qpdf", "QPDF P present in lindict", P.null() ? 0 : 1);
// Store linearization parameter data
// Various places in the code use linp.npages, which is initialized from N, to pre-allocate
// memory, so make sure it's accurate and bail right now if it's not.
if (N.getIntValue() != static_cast<long long>(getAllPages().size())) {
if (static_cast<long long>(N) != static_cast<long long>(getAllPages().size())) {
throw damagedPDF("linearization hint table", "/N does not match number of pages");
}
// file_size initialized by isLinearized()
m->linp.first_page_object = O.getIntValueAsInt();
m->linp.first_page_end = E.getIntValue();
m->linp.npages = N.getIntValueAsInt();
m->linp.xref_zero_offset = T.getIntValue();
m->linp.first_page = first_page;
m->linp.first_page_object = O;
m->linp.first_page_end = E;
m->linp.npages = N;
m->linp.xref_zero_offset = T;
m->linp.first_page = P;
m->linp.H_offset = H0_offset;
m->linp.H_length = H0_length;
@ -256,8 +247,8 @@ QPDF::readLinearizationData()
// /L page label
// Individual hint table offsets
QPDFObjectHandle HS = H0.getKey("/S"); // shared object
QPDFObjectHandle HO = H0.getKey("/O"); // outline
int HS = H0.getKey("/S").asInteger(); // shared object
auto HO = H0.getKey("/O").asInteger(); // outline
auto hbp = pb.getBufferSharedPointer();
Buffer* hb = hbp.get();
@ -266,18 +257,18 @@ QPDF::readLinearizationData()
readHPageOffset(BitStream(h_buf, h_size));
int HSi = HS.getIntValueAsInt();
if ((HSi < 0) || (toS(HSi) >= h_size)) {
if ((HS < 0) || (toS(HS) >= h_size)) {
throw damagedPDF("linearization hint table", "/S (shared object) offset is out of bounds");
}
readHSharedObject(BitStream(h_buf + HSi, h_size - toS(HSi)));
readHSharedObject(BitStream(h_buf + HS, h_size - toS(HS)));
if (HO.isInteger()) {
int HOi = HO.getIntValueAsInt();
if ((HOi < 0) || (toS(HOi) >= h_size)) {
if (HO) {
int HOi = HO;
auto HOs = toS(HOi);
if (HOi < 0 || HOs >= h_size) {
throw damagedPDF("linearization hint table", "/O (outline) offset is out of bounds");
}
readHGeneric(BitStream(h_buf + HOi, h_size - toS(HOi)), m->outline_hints);
readHGeneric(BitStream(h_buf + HOi, h_size - HOs), m->outline_hints);
}
}
@ -304,7 +295,7 @@ QPDF::readHintStream(Pipeline& pl, qpdf_offset_t offset, size_t length)
if (length_obj.isIndirect()) {
QTC::TC("qpdf", "QPDF hint table length indirect");
// Force resolution
(void)length_obj.getIntValue();
(void)length_obj.isInteger();
ObjCache& oc2 = m->obj_cache[length_obj.getObjGen()];
min_end_offset = oc2.end_before_space;
max_end_offset = oc2.end_after_space;

View File

@ -290,7 +290,7 @@ QPDF::addPage(QPDFObjectHandle newpage, bool first)
if (first) {
insertPage(newpage, 0);
} else {
insertPage(newpage, getRoot().getKey("/Pages").getKey("/Count").getIntValueAsInt());
insertPage(newpage, getRoot().getKey("/Pages").getKey("/Count").asInteger());
}
}

View File

@ -28,10 +28,10 @@ SF_FlateLzwDecode::setDecodeParms(QPDFObjectHandle decode_parms)
bool filterable = true;
std::set<std::string> keys = decode_parms.getKeys();
for (auto const& key: keys) {
QPDFObjectHandle value = decode_parms.getKey(key);
auto value = decode_parms.getKey(key).asInteger();
if (key == "/Predictor") {
if (value.isInteger()) {
this->predictor = value.getIntValueAsInt();
if (value) {
this->predictor = value;
if (!((this->predictor == 1) || (this->predictor == 2) ||
((this->predictor >= 10) && (this->predictor <= 15)))) {
filterable = false;
@ -40,23 +40,22 @@ SF_FlateLzwDecode::setDecodeParms(QPDFObjectHandle decode_parms)
filterable = false;
}
} else if ((key == "/Columns") || (key == "/Colors") || (key == "/BitsPerComponent")) {
if (value.isInteger()) {
int val = value.getIntValueAsInt();
if (value) {
if (key == "/Columns") {
this->columns = val;
this->columns = value;
} else if (key == "/Colors") {
this->colors = val;
this->colors = value;
} else if (key == "/BitsPerComponent") {
this->bits_per_component = val;
this->bits_per_component = value;
}
} else {
filterable = false;
}
} else if (lzw && (key == "/EarlyChange")) {
if (value.isInteger()) {
int earlychange = value.getIntValueAsInt();
if (value) {
int earlychange = value;
this->early_code_change = (earlychange == 1);
if (!((earlychange == 0) || (earlychange == 1))) {
if (!(earlychange == 0 || earlychange == 1)) {
filterable = false;
}
} else {

View File

@ -6,8 +6,7 @@ QPDF check generation 1
QPDF check obj 1
QPDF hint table length indirect 0
QPDF hint table length direct 0
QPDF P absent in lindict 0
QPDF P present in lindict 0
QPDF P present in lindict 1
QPDF expected n n obj 0
QPDF /L mismatch 0
QPDF err /T mismatch 0
@ -79,9 +78,8 @@ QPDFObjectHandle makeDirect loop 0
QPDFObjectHandle copy stream 1
QPDF default for xref stream field 0 0
QPDF prev key in xref stream dictionary 0
QPDF prev key in trailer dictionary 0
QPDF prev key in trailer dictionary 1
QPDF found xref stream 0
QPDF ignoring XRefStm in trailer 0
QPDF xref deleted object 0
SF_FlateLzwDecode PNG filter 0
QPDF xref /Index is null 0
@ -332,7 +330,8 @@ QPDFFormFieldObjectHelper TU present 0
QPDFFormFieldObjectHelper TM present 0
QPDFFormFieldObjectHelper TU absent 0
QPDFFormFieldObjectHelper TM absent 0
QPDFFormFieldObjectHelper Q present 1
QPDFFormFieldObjectHelper Q present 0
QPDFFormFieldObjectHelper Q present looked 0
QPDFFormFieldObjectHelper DA present 1
QPDFAnnotationObjectHelper AS present 0
QPDFAnnotationObjectHelper AS absent 0