mirror of
https://github.com/qpdf/qpdf.git
synced 2025-02-08 06:38:24 +00:00
Merge pull request #731 from m-holger/og_unparse
Tidy QPDFObjGen related code
This commit is contained in:
commit
5696a507b6
@ -29,8 +29,7 @@ class ImageProvider: public QPDFObjectHandle::StreamDataProvider
|
|||||||
public:
|
public:
|
||||||
ImageProvider(std::string const& color_space, std::string const& filter);
|
ImageProvider(std::string const& color_space, std::string const& filter);
|
||||||
virtual ~ImageProvider() = default;
|
virtual ~ImageProvider() = default;
|
||||||
virtual void
|
virtual void provideStreamData(QPDFObjGen const&, Pipeline* pipeline);
|
||||||
provideStreamData(int objid, int generation, Pipeline* pipeline);
|
|
||||||
size_t getWidth() const;
|
size_t getWidth() const;
|
||||||
size_t getHeight() const;
|
size_t getHeight() const;
|
||||||
|
|
||||||
@ -93,7 +92,7 @@ ImageProvider::getHeight() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ImageProvider::provideStreamData(int objid, int generation, Pipeline* pipeline)
|
ImageProvider::provideStreamData(QPDFObjGen const&, Pipeline* pipeline)
|
||||||
{
|
{
|
||||||
std::vector<std::shared_ptr<Pipeline>> to_delete;
|
std::vector<std::shared_ptr<Pipeline>> to_delete;
|
||||||
Pipeline* p = pipeline;
|
Pipeline* p = pipeline;
|
||||||
@ -292,7 +291,7 @@ check(
|
|||||||
ImageProvider* p = new ImageProvider(desired_color_space, "null");
|
ImageProvider* p = new ImageProvider(desired_color_space, "null");
|
||||||
std::shared_ptr<QPDFObjectHandle::StreamDataProvider> provider(p);
|
std::shared_ptr<QPDFObjectHandle::StreamDataProvider> provider(p);
|
||||||
Pl_Buffer b_p("get image data");
|
Pl_Buffer b_p("get image data");
|
||||||
provider->provideStreamData(0, 0, &b_p);
|
provider->provideStreamData(QPDFObjGen(), &b_p);
|
||||||
std::shared_ptr<Buffer> desired_data(b_p.getBuffer());
|
std::shared_ptr<Buffer> desired_data(b_p.getBuffer());
|
||||||
|
|
||||||
if (desired_data->getSize() != actual_data->getSize()) {
|
if (desired_data->getSize() != actual_data->getSize()) {
|
||||||
|
@ -201,7 +201,7 @@ class StreamReplacer: public QPDFObjectHandle::StreamDataProvider
|
|||||||
StreamReplacer(QPDF* pdf);
|
StreamReplacer(QPDF* pdf);
|
||||||
virtual ~StreamReplacer() = default;
|
virtual ~StreamReplacer() = default;
|
||||||
virtual void
|
virtual void
|
||||||
provideStreamData(int objid, int generation, Pipeline* pipeline) override;
|
provideStreamData(QPDFObjGen const& og, Pipeline* pipeline) override;
|
||||||
|
|
||||||
void registerStream(
|
void registerStream(
|
||||||
QPDFObjectHandle stream,
|
QPDFObjectHandle stream,
|
||||||
@ -384,9 +384,8 @@ StreamReplacer::registerStream(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
StreamReplacer::provideStreamData(int objid, int generation, Pipeline* pipeline)
|
StreamReplacer::provideStreamData(QPDFObjGen const& og, Pipeline* pipeline)
|
||||||
{
|
{
|
||||||
QPDFObjGen og(objid, generation);
|
|
||||||
QPDFObjectHandle orig = this->copied_streams[og];
|
QPDFObjectHandle orig = this->copied_streams[og];
|
||||||
// call maybeReplace again, this time with the pipeline and no
|
// call maybeReplace again, this time with the pipeline and no
|
||||||
// dict_updates. In this mode, maybeReplace doesn't make any
|
// dict_updates. In this mode, maybeReplace doesn't make any
|
||||||
|
@ -35,7 +35,7 @@ class ImageInverter: public QPDFObjectHandle::StreamDataProvider
|
|||||||
public:
|
public:
|
||||||
virtual ~ImageInverter() = default;
|
virtual ~ImageInverter() = default;
|
||||||
virtual void
|
virtual void
|
||||||
provideStreamData(int objid, int generation, Pipeline* pipeline) override;
|
provideStreamData(QPDFObjGen const& og, Pipeline* pipeline) override;
|
||||||
|
|
||||||
void registerImage(
|
void registerImage(
|
||||||
QPDFObjectHandle image,
|
QPDFObjectHandle image,
|
||||||
@ -82,12 +82,11 @@ ImageInverter::registerImage(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ImageInverter::provideStreamData(int objid, int generation, Pipeline* pipeline)
|
ImageInverter::provideStreamData(QPDFObjGen const& og, Pipeline* pipeline)
|
||||||
{
|
{
|
||||||
// Use the object and generation number supplied to look up the
|
// Use the object and generation number supplied to look up the
|
||||||
// image data. Then invert the image data and write the inverted
|
// image data. Then invert the image data and write the inverted
|
||||||
// data to the pipeline.
|
// data to the pipeline.
|
||||||
QPDFObjGen og(objid, generation);
|
|
||||||
std::shared_ptr<Buffer> data =
|
std::shared_ptr<Buffer> data =
|
||||||
this->copied_images[og].getStreamData(qpdf_dl_all);
|
this->copied_images[og].getStreamData(qpdf_dl_all);
|
||||||
size_t size = data->getSize();
|
size_t size = data->getSize();
|
||||||
|
@ -815,9 +815,9 @@ class QPDF
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
static std::shared_ptr<QPDFObject>
|
static std::shared_ptr<QPDFObject>
|
||||||
resolve(QPDF* qpdf, int objid, int generation)
|
resolve(QPDF* qpdf, QPDFObjGen const& og)
|
||||||
{
|
{
|
||||||
return qpdf->resolve(objid, generation);
|
return qpdf->resolve(og);
|
||||||
}
|
}
|
||||||
static bool
|
static bool
|
||||||
objectChanged(
|
objectChanged(
|
||||||
@ -879,8 +879,7 @@ class QPDF
|
|||||||
static bool
|
static bool
|
||||||
pipeStreamData(
|
pipeStreamData(
|
||||||
QPDF* qpdf,
|
QPDF* qpdf,
|
||||||
int objid,
|
QPDFObjGen const& og,
|
||||||
int generation,
|
|
||||||
qpdf_offset_t offset,
|
qpdf_offset_t offset,
|
||||||
size_t length,
|
size_t length,
|
||||||
QPDFObjectHandle dict,
|
QPDFObjectHandle dict,
|
||||||
@ -889,8 +888,7 @@ class QPDF
|
|||||||
bool will_retry)
|
bool will_retry)
|
||||||
{
|
{
|
||||||
return qpdf->pipeStreamData(
|
return qpdf->pipeStreamData(
|
||||||
objid,
|
og,
|
||||||
generation,
|
|
||||||
offset,
|
offset,
|
||||||
length,
|
length,
|
||||||
dict,
|
dict,
|
||||||
@ -959,8 +957,7 @@ class QPDF
|
|||||||
std::string user_password;
|
std::string user_password;
|
||||||
std::string encryption_key;
|
std::string encryption_key;
|
||||||
std::string cached_object_encryption_key;
|
std::string cached_object_encryption_key;
|
||||||
int cached_key_objid;
|
QPDFObjGen cached_key_og;
|
||||||
int cached_key_generation;
|
|
||||||
bool user_password_matched;
|
bool user_password_matched;
|
||||||
bool owner_password_matched;
|
bool owner_password_matched;
|
||||||
};
|
};
|
||||||
@ -973,8 +970,7 @@ class QPDF
|
|||||||
ForeignStreamData(
|
ForeignStreamData(
|
||||||
std::shared_ptr<EncryptionParameters> encp,
|
std::shared_ptr<EncryptionParameters> encp,
|
||||||
std::shared_ptr<InputSource> file,
|
std::shared_ptr<InputSource> file,
|
||||||
int foreign_objid,
|
QPDFObjGen const& foreign_og,
|
||||||
int foreign_generation,
|
|
||||||
qpdf_offset_t offset,
|
qpdf_offset_t offset,
|
||||||
size_t length,
|
size_t length,
|
||||||
QPDFObjectHandle local_dict);
|
QPDFObjectHandle local_dict);
|
||||||
@ -982,8 +978,7 @@ class QPDF
|
|||||||
private:
|
private:
|
||||||
std::shared_ptr<EncryptionParameters> encp;
|
std::shared_ptr<EncryptionParameters> encp;
|
||||||
std::shared_ptr<InputSource> file;
|
std::shared_ptr<InputSource> file;
|
||||||
int foreign_objid;
|
QPDFObjGen foreign_og;
|
||||||
int foreign_generation;
|
|
||||||
qpdf_offset_t offset;
|
qpdf_offset_t offset;
|
||||||
size_t length;
|
size_t length;
|
||||||
QPDFObjectHandle local_dict;
|
QPDFObjectHandle local_dict;
|
||||||
@ -995,8 +990,7 @@ class QPDF
|
|||||||
CopiedStreamDataProvider(QPDF& destination_qpdf);
|
CopiedStreamDataProvider(QPDF& destination_qpdf);
|
||||||
virtual ~CopiedStreamDataProvider() = default;
|
virtual ~CopiedStreamDataProvider() = default;
|
||||||
virtual bool provideStreamData(
|
virtual bool provideStreamData(
|
||||||
int objid,
|
QPDFObjGen const& og,
|
||||||
int generation,
|
|
||||||
Pipeline* pipeline,
|
Pipeline* pipeline,
|
||||||
bool suppress_warnings,
|
bool suppress_warnings,
|
||||||
bool will_retry) override;
|
bool will_retry) override;
|
||||||
@ -1017,14 +1011,13 @@ class QPDF
|
|||||||
friend class QPDF;
|
friend class QPDF;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
StringDecrypter(QPDF* qpdf, int objid, int gen);
|
StringDecrypter(QPDF* qpdf, QPDFObjGen const& og);
|
||||||
virtual ~StringDecrypter() = default;
|
virtual ~StringDecrypter() = default;
|
||||||
virtual void decryptString(std::string& val);
|
virtual void decryptString(std::string& val);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QPDF* qpdf;
|
QPDF* qpdf;
|
||||||
int objid;
|
QPDFObjGen og;
|
||||||
int gen;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class ResolveRecorder
|
class ResolveRecorder
|
||||||
@ -1127,17 +1120,15 @@ class QPDF
|
|||||||
void insertXrefEntry(
|
void insertXrefEntry(
|
||||||
int obj, int f0, qpdf_offset_t f1, int f2, bool overwrite = false);
|
int obj, int f0, qpdf_offset_t f1, int f2, bool overwrite = false);
|
||||||
void setLastObjectDescription(
|
void setLastObjectDescription(
|
||||||
std::string const& description, int objid, int generation);
|
std::string const& description, QPDFObjGen const& og);
|
||||||
QPDFObjectHandle readObject(
|
QPDFObjectHandle readObject(
|
||||||
std::shared_ptr<InputSource>,
|
std::shared_ptr<InputSource>,
|
||||||
std::string const& description,
|
std::string const& description,
|
||||||
int objid,
|
QPDFObjGen const& og,
|
||||||
int generation,
|
|
||||||
bool in_object_stream);
|
bool in_object_stream);
|
||||||
size_t recoverStreamLength(
|
size_t recoverStreamLength(
|
||||||
std::shared_ptr<InputSource> input,
|
std::shared_ptr<InputSource> input,
|
||||||
int objid,
|
QPDFObjGen const& og,
|
||||||
int generation,
|
|
||||||
qpdf_offset_t stream_offset);
|
qpdf_offset_t stream_offset);
|
||||||
QPDFTokenizer::Token
|
QPDFTokenizer::Token
|
||||||
readToken(std::shared_ptr<InputSource>, size_t max_len = 0);
|
readToken(std::shared_ptr<InputSource>, size_t max_len = 0);
|
||||||
@ -1146,21 +1137,18 @@ class QPDF
|
|||||||
bool attempt_recovery,
|
bool attempt_recovery,
|
||||||
qpdf_offset_t offset,
|
qpdf_offset_t offset,
|
||||||
std::string const& description,
|
std::string const& description,
|
||||||
int exp_objid,
|
QPDFObjGen const& exp_og,
|
||||||
int exp_generation,
|
QPDFObjGen& og);
|
||||||
int& act_objid,
|
|
||||||
int& act_generation);
|
|
||||||
bool objectChanged(QPDFObjGen const& og, std::shared_ptr<QPDFObject>& oph);
|
bool objectChanged(QPDFObjGen const& og, std::shared_ptr<QPDFObject>& oph);
|
||||||
std::shared_ptr<QPDFObject> resolve(int objid, int generation);
|
std::shared_ptr<QPDFObject> resolve(QPDFObjGen const& og);
|
||||||
void resolveObjectsInStream(int obj_stream_number);
|
void resolveObjectsInStream(int obj_stream_number);
|
||||||
void stopOnError(std::string const& message);
|
void stopOnError(std::string const& message);
|
||||||
QPDFObjectHandle reserveObjectIfNotExists(int objid, int gen);
|
QPDFObjectHandle reserveObjectIfNotExists(QPDFObjGen const& og);
|
||||||
QPDFObjectHandle reserveStream(int objid, int gen);
|
QPDFObjectHandle reserveStream(QPDFObjGen const& og);
|
||||||
|
|
||||||
// Calls finish() on the pipeline when done but does not delete it
|
// Calls finish() on the pipeline when done but does not delete it
|
||||||
bool pipeStreamData(
|
bool pipeStreamData(
|
||||||
int objid,
|
QPDFObjGen const& og,
|
||||||
int generation,
|
|
||||||
qpdf_offset_t offset,
|
qpdf_offset_t offset,
|
||||||
size_t length,
|
size_t length,
|
||||||
QPDFObjectHandle dict,
|
QPDFObjectHandle dict,
|
||||||
@ -1176,8 +1164,7 @@ class QPDF
|
|||||||
std::shared_ptr<QPDF::EncryptionParameters> encp,
|
std::shared_ptr<QPDF::EncryptionParameters> encp,
|
||||||
std::shared_ptr<InputSource> file,
|
std::shared_ptr<InputSource> file,
|
||||||
QPDF& qpdf_for_warning,
|
QPDF& qpdf_for_warning,
|
||||||
int objid,
|
QPDFObjGen const& og,
|
||||||
int generation,
|
|
||||||
qpdf_offset_t offset,
|
qpdf_offset_t offset,
|
||||||
size_t length,
|
size_t length,
|
||||||
QPDFObjectHandle dict,
|
QPDFObjectHandle dict,
|
||||||
@ -1230,10 +1217,9 @@ class QPDF
|
|||||||
void initializeEncryption();
|
void initializeEncryption();
|
||||||
static std::string getKeyForObject(
|
static std::string getKeyForObject(
|
||||||
std::shared_ptr<EncryptionParameters> encp,
|
std::shared_ptr<EncryptionParameters> encp,
|
||||||
int objid,
|
QPDFObjGen const& og,
|
||||||
int generation,
|
|
||||||
bool use_aes);
|
bool use_aes);
|
||||||
void decryptString(std::string&, int objid, int generation);
|
void decryptString(std::string&, QPDFObjGen const& og);
|
||||||
static std::string compute_encryption_key_from_password(
|
static std::string compute_encryption_key_from_password(
|
||||||
std::string const& password, EncryptionData const& data);
|
std::string const& password, EncryptionData const& data);
|
||||||
static std::string recover_encryption_key_with_password(
|
static std::string recover_encryption_key_with_password(
|
||||||
@ -1247,8 +1233,7 @@ class QPDF
|
|||||||
std::shared_ptr<InputSource> file,
|
std::shared_ptr<InputSource> file,
|
||||||
QPDF& qpdf_for_warning,
|
QPDF& qpdf_for_warning,
|
||||||
Pipeline*& pipeline,
|
Pipeline*& pipeline,
|
||||||
int objid,
|
QPDFObjGen const& og,
|
||||||
int generation,
|
|
||||||
QPDFObjectHandle& stream_dict,
|
QPDFObjectHandle& stream_dict,
|
||||||
std::vector<std::shared_ptr<Pipeline>>& heap);
|
std::vector<std::shared_ptr<Pipeline>>& heap);
|
||||||
|
|
||||||
@ -1571,7 +1556,6 @@ class QPDF
|
|||||||
void dumpHSharedObject();
|
void dumpHSharedObject();
|
||||||
void dumpHGeneric(HGeneric&);
|
void dumpHGeneric(HGeneric&);
|
||||||
qpdf_offset_t adjusted_offset(qpdf_offset_t offset);
|
qpdf_offset_t adjusted_offset(qpdf_offset_t offset);
|
||||||
QPDFObjectHandle objGenToIndirect(QPDFObjGen const&);
|
|
||||||
void
|
void
|
||||||
calculateLinearizationData(std::map<int, int> const& object_stream_data);
|
calculateLinearizationData(std::map<int, int> const& object_stream_data);
|
||||||
void pushOutlinesToPart(
|
void pushOutlinesToPart(
|
||||||
|
@ -23,7 +23,6 @@
|
|||||||
#define QPDFOBJGEN_HH
|
#define QPDFOBJGEN_HH
|
||||||
|
|
||||||
#include <qpdf/DLL.h>
|
#include <qpdf/DLL.h>
|
||||||
#include <qpdf/QUtil.hh>
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
// This class represents an object ID and generation pair. It is
|
// This class represents an object ID and generation pair. It is
|
||||||
@ -39,7 +38,7 @@ class QPDFObjGen
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
QPDFObjGen(int obj, int gen) :
|
explicit QPDFObjGen(int obj, int gen) :
|
||||||
obj(obj),
|
obj(obj),
|
||||||
gen(gen)
|
gen(gen)
|
||||||
{
|
{
|
||||||
@ -48,13 +47,19 @@ class QPDFObjGen
|
|||||||
bool
|
bool
|
||||||
operator<(QPDFObjGen const& rhs) const
|
operator<(QPDFObjGen const& rhs) const
|
||||||
{
|
{
|
||||||
return ((obj < rhs.obj) || ((obj == rhs.obj) && (gen < rhs.gen)));
|
return (obj < rhs.obj) || ((obj == rhs.obj) && (gen < rhs.gen));
|
||||||
}
|
}
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
bool
|
bool
|
||||||
operator==(QPDFObjGen const& rhs) const
|
operator==(QPDFObjGen const& rhs) const
|
||||||
{
|
{
|
||||||
return ((obj == rhs.obj) && (gen == rhs.gen));
|
return (obj == rhs.obj) && (gen == rhs.gen);
|
||||||
|
}
|
||||||
|
QPDF_DLL
|
||||||
|
bool
|
||||||
|
operator!=(QPDFObjGen const& rhs) const
|
||||||
|
{
|
||||||
|
return (obj != rhs.obj) || (gen != rhs.gen);
|
||||||
}
|
}
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
int
|
int
|
||||||
@ -69,18 +74,15 @@ class QPDFObjGen
|
|||||||
return gen;
|
return gen;
|
||||||
}
|
}
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
std::string
|
bool
|
||||||
unparse() const
|
isIndirect() const
|
||||||
{
|
{
|
||||||
return QUtil::int_to_string(obj) + "," + QUtil::int_to_string(gen);
|
return obj != 0;
|
||||||
}
|
}
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
friend std::ostream&
|
std::string unparse(char separator = ',') const;
|
||||||
operator<<(std::ostream& os, const QPDFObjGen& og)
|
QPDF_DLL
|
||||||
{
|
friend std::ostream& operator<<(std::ostream& os, const QPDFObjGen& og);
|
||||||
os << og.obj << "," << og.gen;
|
|
||||||
return os;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// This class does not use the Members pattern to avoid a memory
|
// This class does not use the Members pattern to avoid a memory
|
||||||
|
@ -116,9 +116,16 @@ class QPDFObjectHandle
|
|||||||
// indicating whether it ran without errors.
|
// indicating whether it ran without errors.
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
virtual void
|
virtual void
|
||||||
provideStreamData(int objid, int generation, Pipeline* pipeline);
|
provideStreamData(QPDFObjGen const& og, Pipeline* pipeline);
|
||||||
QPDF_DLL
|
QPDF_DLL
|
||||||
virtual bool provideStreamData(
|
virtual bool provideStreamData(
|
||||||
|
QPDFObjGen const& og,
|
||||||
|
Pipeline* pipeline,
|
||||||
|
bool suppress_warnings,
|
||||||
|
bool will_retry);
|
||||||
|
QPDF_DLL virtual void
|
||||||
|
provideStreamData(int objid, int generation, Pipeline* pipeline);
|
||||||
|
QPDF_DLL virtual bool provideStreamData(
|
||||||
int objid,
|
int objid,
|
||||||
int generation,
|
int generation,
|
||||||
Pipeline* pipeline,
|
Pipeline* pipeline,
|
||||||
@ -1429,21 +1436,20 @@ class QPDFObjectHandle
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
static QPDFObjectHandle
|
static QPDFObjectHandle
|
||||||
newIndirect(QPDF* qpdf, int objid, int generation)
|
newIndirect(QPDF* qpdf, QPDFObjGen const& og)
|
||||||
{
|
{
|
||||||
return QPDFObjectHandle::newIndirect(qpdf, objid, generation);
|
return QPDFObjectHandle::newIndirect(qpdf, og);
|
||||||
}
|
}
|
||||||
static QPDFObjectHandle
|
static QPDFObjectHandle
|
||||||
newStream(
|
newStream(
|
||||||
QPDF* qpdf,
|
QPDF* qpdf,
|
||||||
int objid,
|
QPDFObjGen const& og,
|
||||||
int generation,
|
|
||||||
QPDFObjectHandle stream_dict,
|
QPDFObjectHandle stream_dict,
|
||||||
qpdf_offset_t offset,
|
qpdf_offset_t offset,
|
||||||
size_t length)
|
size_t length)
|
||||||
{
|
{
|
||||||
return QPDFObjectHandle::newStream(
|
return QPDFObjectHandle::newStream(
|
||||||
qpdf, objid, generation, stream_dict, offset, length);
|
qpdf, og, stream_dict, offset, length);
|
||||||
}
|
}
|
||||||
// Reserve an object with a specific ID
|
// Reserve an object with a specific ID
|
||||||
static QPDFObjectHandle
|
static QPDFObjectHandle
|
||||||
@ -1550,7 +1556,7 @@ class QPDFObjectHandle
|
|||||||
bool isImage(bool exclude_imagemask = true);
|
bool isImage(bool exclude_imagemask = true);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QPDFObjectHandle(QPDF*, int objid, int generation);
|
QPDFObjectHandle(QPDF*, QPDFObjGen const& og);
|
||||||
QPDFObjectHandle(std::shared_ptr<QPDFObject> const&);
|
QPDFObjectHandle(std::shared_ptr<QPDFObject> const&);
|
||||||
|
|
||||||
enum parser_state_e {
|
enum parser_state_e {
|
||||||
@ -1563,11 +1569,10 @@ class QPDFObjectHandle
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Private object factory methods
|
// Private object factory methods
|
||||||
static QPDFObjectHandle newIndirect(QPDF*, int objid, int generation);
|
static QPDFObjectHandle newIndirect(QPDF*, QPDFObjGen const& og);
|
||||||
static QPDFObjectHandle newStream(
|
static QPDFObjectHandle newStream(
|
||||||
QPDF* qpdf,
|
QPDF* qpdf,
|
||||||
int objid,
|
QPDFObjGen const& og,
|
||||||
int generation,
|
|
||||||
QPDFObjectHandle stream_dict,
|
QPDFObjectHandle stream_dict,
|
||||||
qpdf_offset_t offset,
|
qpdf_offset_t offset,
|
||||||
size_t length);
|
size_t length);
|
||||||
@ -1584,7 +1589,6 @@ class QPDFObjectHandle
|
|||||||
bool stop_at_streams);
|
bool stop_at_streams);
|
||||||
void shallowCopyInternal(QPDFObjectHandle& oh, bool first_level_only);
|
void shallowCopyInternal(QPDFObjectHandle& oh, bool first_level_only);
|
||||||
void releaseResolved();
|
void releaseResolved();
|
||||||
std::string getObjGenAsStr() const;
|
|
||||||
static void setObjectDescriptionFromInput(
|
static void setObjectDescriptionFromInput(
|
||||||
QPDFObjectHandle,
|
QPDFObjectHandle,
|
||||||
QPDF*,
|
QPDF*,
|
||||||
@ -1618,8 +1622,7 @@ class QPDFObjectHandle
|
|||||||
// a substantial performance penalty since QPDFObjectHandle
|
// a substantial performance penalty since QPDFObjectHandle
|
||||||
// objects are copied around so frequently.
|
// objects are copied around so frequently.
|
||||||
QPDF* qpdf;
|
QPDF* qpdf;
|
||||||
int objid; // 0 for direct object
|
QPDFObjGen og;
|
||||||
int generation;
|
|
||||||
std::shared_ptr<QPDFObject> obj;
|
std::shared_ptr<QPDFObject> obj;
|
||||||
bool reserved;
|
bool reserved;
|
||||||
};
|
};
|
||||||
|
@ -74,6 +74,7 @@ set(libqpdf_SOURCES
|
|||||||
QPDFNumberTreeObjectHelper.cc
|
QPDFNumberTreeObjectHelper.cc
|
||||||
QPDFObject.cc
|
QPDFObject.cc
|
||||||
QPDFObjectHandle.cc
|
QPDFObjectHandle.cc
|
||||||
|
QPDFObjGen.cc
|
||||||
QPDFOutlineDocumentHelper.cc
|
QPDFOutlineDocumentHelper.cc
|
||||||
QPDFOutlineObjectHelper.cc
|
QPDFOutlineObjectHelper.cc
|
||||||
QPDFPageDocumentHelper.cc
|
QPDFPageDocumentHelper.cc
|
||||||
|
232
libqpdf/QPDF.cc
232
libqpdf/QPDF.cc
@ -113,15 +113,13 @@ namespace
|
|||||||
QPDF::ForeignStreamData::ForeignStreamData(
|
QPDF::ForeignStreamData::ForeignStreamData(
|
||||||
std::shared_ptr<EncryptionParameters> encp,
|
std::shared_ptr<EncryptionParameters> encp,
|
||||||
std::shared_ptr<InputSource> file,
|
std::shared_ptr<InputSource> file,
|
||||||
int foreign_objid,
|
QPDFObjGen const& foreign_og,
|
||||||
int foreign_generation,
|
|
||||||
qpdf_offset_t offset,
|
qpdf_offset_t offset,
|
||||||
size_t length,
|
size_t length,
|
||||||
QPDFObjectHandle local_dict) :
|
QPDFObjectHandle local_dict) :
|
||||||
encp(encp),
|
encp(encp),
|
||||||
file(file),
|
file(file),
|
||||||
foreign_objid(foreign_objid),
|
foreign_og(foreign_og),
|
||||||
foreign_generation(foreign_generation),
|
|
||||||
offset(offset),
|
offset(offset),
|
||||||
length(length),
|
length(length),
|
||||||
local_dict(local_dict)
|
local_dict(local_dict)
|
||||||
@ -137,22 +135,19 @@ QPDF::CopiedStreamDataProvider::CopiedStreamDataProvider(
|
|||||||
|
|
||||||
bool
|
bool
|
||||||
QPDF::CopiedStreamDataProvider::provideStreamData(
|
QPDF::CopiedStreamDataProvider::provideStreamData(
|
||||||
int objid,
|
QPDFObjGen const& og,
|
||||||
int generation,
|
|
||||||
Pipeline* pipeline,
|
Pipeline* pipeline,
|
||||||
bool suppress_warnings,
|
bool suppress_warnings,
|
||||||
bool will_retry)
|
bool will_retry)
|
||||||
{
|
{
|
||||||
std::shared_ptr<ForeignStreamData> foreign_data =
|
std::shared_ptr<ForeignStreamData> foreign_data = foreign_stream_data[og];
|
||||||
this->foreign_stream_data[QPDFObjGen(objid, generation)];
|
|
||||||
bool result = false;
|
bool result = false;
|
||||||
if (foreign_data.get()) {
|
if (foreign_data.get()) {
|
||||||
result = destination_qpdf.pipeForeignStreamData(
|
result = destination_qpdf.pipeForeignStreamData(
|
||||||
foreign_data, pipeline, suppress_warnings, will_retry);
|
foreign_data, pipeline, suppress_warnings, will_retry);
|
||||||
QTC::TC("qpdf", "QPDF copy foreign with data", result ? 0 : 1);
|
QTC::TC("qpdf", "QPDF copy foreign with data", result ? 0 : 1);
|
||||||
} else {
|
} else {
|
||||||
QPDFObjectHandle foreign_stream =
|
auto foreign_stream = foreign_streams[og];
|
||||||
this->foreign_streams[QPDFObjGen(objid, generation)];
|
|
||||||
result = foreign_stream.pipeStreamData(
|
result = foreign_stream.pipeStreamData(
|
||||||
pipeline, nullptr, 0, qpdf_dl_none, suppress_warnings, will_retry);
|
pipeline, nullptr, 0, qpdf_dl_none, suppress_warnings, will_retry);
|
||||||
QTC::TC(
|
QTC::TC(
|
||||||
@ -176,17 +171,16 @@ QPDF::CopiedStreamDataProvider::registerForeignStream(
|
|||||||
this->foreign_stream_data[local_og] = foreign_stream;
|
this->foreign_stream_data[local_og] = foreign_stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
QPDF::StringDecrypter::StringDecrypter(QPDF* qpdf, int objid, int gen) :
|
QPDF::StringDecrypter::StringDecrypter(QPDF* qpdf, QPDFObjGen const& og) :
|
||||||
qpdf(qpdf),
|
qpdf(qpdf),
|
||||||
objid(objid),
|
og(og)
|
||||||
gen(gen)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
QPDF::StringDecrypter::decryptString(std::string& val)
|
QPDF::StringDecrypter::decryptString(std::string& val)
|
||||||
{
|
{
|
||||||
qpdf->decryptString(val, objid, gen);
|
qpdf->decryptString(val, og);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string const&
|
std::string const&
|
||||||
@ -205,8 +199,6 @@ QPDF::EncryptionParameters::EncryptionParameters() :
|
|||||||
cf_stream(e_none),
|
cf_stream(e_none),
|
||||||
cf_string(e_none),
|
cf_string(e_none),
|
||||||
cf_file(e_none),
|
cf_file(e_none),
|
||||||
cached_key_objid(0),
|
|
||||||
cached_key_generation(0),
|
|
||||||
user_password_matched(false),
|
user_password_matched(false),
|
||||||
owner_password_matched(false)
|
owner_password_matched(false)
|
||||||
{
|
{
|
||||||
@ -631,7 +623,7 @@ QPDF::reconstruct_xref(QPDFExc& e)
|
|||||||
(!this->m->trailer.isInitialized()) &&
|
(!this->m->trailer.isInitialized()) &&
|
||||||
(t1 == QPDFTokenizer::Token(QPDFTokenizer::tt_word, "trailer"))) {
|
(t1 == QPDFTokenizer::Token(QPDFTokenizer::tt_word, "trailer"))) {
|
||||||
QPDFObjectHandle t =
|
QPDFObjectHandle t =
|
||||||
readObject(this->m->file, "trailer", 0, 0, false);
|
readObject(this->m->file, "trailer", QPDFObjGen(), false);
|
||||||
if (!t.isDictionary()) {
|
if (!t.isDictionary()) {
|
||||||
// Oh well. It was worth a try.
|
// Oh well. It was worth a try.
|
||||||
} else {
|
} else {
|
||||||
@ -969,7 +961,7 @@ QPDF::read_xrefTable(qpdf_offset_t xref_offset)
|
|||||||
|
|
||||||
// Set offset to previous xref table if any
|
// Set offset to previous xref table if any
|
||||||
QPDFObjectHandle cur_trailer =
|
QPDFObjectHandle cur_trailer =
|
||||||
readObject(this->m->file, "trailer", 0, 0, false);
|
readObject(this->m->file, "trailer", QPDFObjGen(), false);
|
||||||
if (!cur_trailer.isDictionary()) {
|
if (!cur_trailer.isDictionary()) {
|
||||||
QTC::TC("qpdf", "QPDF missing trailer");
|
QTC::TC("qpdf", "QPDF missing trailer");
|
||||||
throw QPDFExc(
|
throw QPDFExc(
|
||||||
@ -1055,12 +1047,11 @@ QPDF::read_xrefStream(qpdf_offset_t xref_offset)
|
|||||||
{
|
{
|
||||||
bool found = false;
|
bool found = false;
|
||||||
if (!this->m->ignore_xref_streams) {
|
if (!this->m->ignore_xref_streams) {
|
||||||
int xobj;
|
QPDFObjGen x_og;
|
||||||
int xgen;
|
|
||||||
QPDFObjectHandle xref_obj;
|
QPDFObjectHandle xref_obj;
|
||||||
try {
|
try {
|
||||||
xref_obj = readObjectAtOffset(
|
xref_obj = readObjectAtOffset(
|
||||||
false, xref_offset, "xref stream", 0, 0, xobj, xgen);
|
false, xref_offset, "xref stream", QPDFObjGen(0, 0), x_og);
|
||||||
} catch (QPDFExc&) {
|
} catch (QPDFExc&) {
|
||||||
// ignore -- report error below
|
// ignore -- report error below
|
||||||
}
|
}
|
||||||
@ -1363,7 +1354,7 @@ QPDF::showXRefTable()
|
|||||||
for (auto const& iter: this->m->xref_table) {
|
for (auto const& iter: this->m->xref_table) {
|
||||||
QPDFObjGen const& og = iter.first;
|
QPDFObjGen const& og = iter.first;
|
||||||
QPDFXRefEntry const& entry = iter.second;
|
QPDFXRefEntry const& entry = iter.second;
|
||||||
cout << og.getObj() << "/" << og.getGen() << ": ";
|
cout << og.unparse('/') << ": ";
|
||||||
switch (entry.getType()) {
|
switch (entry.getType()) {
|
||||||
case 1:
|
case 1:
|
||||||
cout << "uncompressed; offset = " << entry.getOffset();
|
cout << "uncompressed; offset = " << entry.getOffset();
|
||||||
@ -1405,9 +1396,8 @@ QPDF::fixDanglingReferences(bool force)
|
|||||||
// For each non-scalar item to process, put it in the queue.
|
// For each non-scalar item to process, put it in the queue.
|
||||||
std::list<QPDFObjectHandle> queue;
|
std::list<QPDFObjectHandle> queue;
|
||||||
queue.push_back(this->m->trailer);
|
queue.push_back(this->m->trailer);
|
||||||
for (auto const& iter: to_process) {
|
for (auto const& og: to_process) {
|
||||||
QPDFObjectHandle obj = QPDFObjectHandle::Factory::newIndirect(
|
QPDFObjectHandle obj = QPDFObjectHandle::Factory::newIndirect(this, og);
|
||||||
this, iter.getObj(), iter.getGen());
|
|
||||||
if (obj.isDictionary() || obj.isArray()) {
|
if (obj.isDictionary() || obj.isArray()) {
|
||||||
queue.push_back(obj);
|
queue.push_back(obj);
|
||||||
} else if (obj.isStream()) {
|
} else if (obj.isStream()) {
|
||||||
@ -1473,29 +1463,24 @@ QPDF::getAllObjects()
|
|||||||
std::vector<QPDFObjectHandle> result;
|
std::vector<QPDFObjectHandle> result;
|
||||||
for (auto const& iter: this->m->obj_cache) {
|
for (auto const& iter: this->m->obj_cache) {
|
||||||
QPDFObjGen const& og = iter.first;
|
QPDFObjGen const& og = iter.first;
|
||||||
result.push_back(
|
result.push_back(QPDFObjectHandle::Factory::newIndirect(this, og));
|
||||||
// line-break
|
|
||||||
QPDFObjectHandle::Factory::newIndirect(
|
|
||||||
this, og.getObj(), og.getGen()));
|
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
QPDF::setLastObjectDescription(
|
QPDF::setLastObjectDescription(
|
||||||
std::string const& description, int objid, int generation)
|
std::string const& description, QPDFObjGen const& og)
|
||||||
{
|
{
|
||||||
this->m->last_object_description.clear();
|
this->m->last_object_description.clear();
|
||||||
if (!description.empty()) {
|
if (!description.empty()) {
|
||||||
this->m->last_object_description += description;
|
this->m->last_object_description += description;
|
||||||
if (objid > 0) {
|
if (og.isIndirect()) {
|
||||||
this->m->last_object_description += ": ";
|
this->m->last_object_description += ": ";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (objid > 0) {
|
if (og.isIndirect()) {
|
||||||
this->m->last_object_description += "object " +
|
this->m->last_object_description += "object " + og.unparse(' ');
|
||||||
QUtil::int_to_string(objid) + " " +
|
|
||||||
QUtil::int_to_string(generation);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1503,19 +1488,17 @@ QPDFObjectHandle
|
|||||||
QPDF::readObject(
|
QPDF::readObject(
|
||||||
std::shared_ptr<InputSource> input,
|
std::shared_ptr<InputSource> input,
|
||||||
std::string const& description,
|
std::string const& description,
|
||||||
int objid,
|
QPDFObjGen const& og,
|
||||||
int generation,
|
|
||||||
bool in_object_stream)
|
bool in_object_stream)
|
||||||
{
|
{
|
||||||
setLastObjectDescription(description, objid, generation);
|
setLastObjectDescription(description, og);
|
||||||
qpdf_offset_t offset = input->tell();
|
qpdf_offset_t offset = input->tell();
|
||||||
|
|
||||||
bool empty = false;
|
bool empty = false;
|
||||||
std::shared_ptr<StringDecrypter> decrypter_ph;
|
std::shared_ptr<StringDecrypter> decrypter_ph;
|
||||||
StringDecrypter* decrypter = 0;
|
StringDecrypter* decrypter = 0;
|
||||||
if (this->m->encp->encrypted && (!in_object_stream)) {
|
if (this->m->encp->encrypted && (!in_object_stream)) {
|
||||||
decrypter_ph =
|
decrypter_ph = std::make_shared<StringDecrypter>(this, og);
|
||||||
std::make_shared<StringDecrypter>(this, objid, generation);
|
|
||||||
decrypter = decrypter_ph.get();
|
decrypter = decrypter_ph.get();
|
||||||
}
|
}
|
||||||
QPDFObjectHandle object = QPDFObjectHandle::parse(
|
QPDFObjectHandle object = QPDFObjectHandle::parse(
|
||||||
@ -1657,14 +1640,13 @@ QPDF::readObject(
|
|||||||
} catch (QPDFExc& e) {
|
} catch (QPDFExc& e) {
|
||||||
if (this->m->attempt_recovery) {
|
if (this->m->attempt_recovery) {
|
||||||
warn(e);
|
warn(e);
|
||||||
length = recoverStreamLength(
|
length = recoverStreamLength(input, og, stream_offset);
|
||||||
input, objid, generation, stream_offset);
|
|
||||||
} else {
|
} else {
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
object = QPDFObjectHandle::Factory::newStream(
|
object = QPDFObjectHandle::Factory::newStream(
|
||||||
this, objid, generation, object, stream_offset, length);
|
this, og, object, stream_offset, length);
|
||||||
} else {
|
} else {
|
||||||
input->seek(cur_offset, SEEK_SET);
|
input->seek(cur_offset, SEEK_SET);
|
||||||
}
|
}
|
||||||
@ -1692,8 +1674,7 @@ QPDF::findEndstream()
|
|||||||
size_t
|
size_t
|
||||||
QPDF::recoverStreamLength(
|
QPDF::recoverStreamLength(
|
||||||
std::shared_ptr<InputSource> input,
|
std::shared_ptr<InputSource> input,
|
||||||
int objid,
|
QPDFObjGen const& og,
|
||||||
int generation,
|
|
||||||
qpdf_offset_t stream_offset)
|
qpdf_offset_t stream_offset)
|
||||||
{
|
{
|
||||||
// Try to reconstruct stream length by looking for
|
// Try to reconstruct stream length by looking for
|
||||||
@ -1718,11 +1699,10 @@ QPDF::recoverStreamLength(
|
|||||||
|
|
||||||
if (length) {
|
if (length) {
|
||||||
qpdf_offset_t this_obj_offset = 0;
|
qpdf_offset_t this_obj_offset = 0;
|
||||||
QPDFObjGen this_obj(0, 0);
|
QPDFObjGen this_og;
|
||||||
|
|
||||||
// Make sure this is inside this object
|
// Make sure this is inside this object
|
||||||
for (auto const& iter: this->m->xref_table) {
|
for (auto const& iter: this->m->xref_table) {
|
||||||
QPDFObjGen const& og = iter.first;
|
|
||||||
QPDFXRefEntry const& entry = iter.second;
|
QPDFXRefEntry const& entry = iter.second;
|
||||||
if (entry.getType() == 1) {
|
if (entry.getType() == 1) {
|
||||||
qpdf_offset_t obj_offset = entry.getOffset();
|
qpdf_offset_t obj_offset = entry.getOffset();
|
||||||
@ -1730,12 +1710,11 @@ QPDF::recoverStreamLength(
|
|||||||
((this_obj_offset == 0) ||
|
((this_obj_offset == 0) ||
|
||||||
(this_obj_offset > obj_offset))) {
|
(this_obj_offset > obj_offset))) {
|
||||||
this_obj_offset = obj_offset;
|
this_obj_offset = obj_offset;
|
||||||
this_obj = og;
|
this_og = iter.first;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (this_obj_offset && (this_obj.getObj() == objid) &&
|
if (this_obj_offset && (this_og == og)) {
|
||||||
(this_obj.getGen() == generation)) {
|
|
||||||
// Well, we found endstream\nendobj within the space
|
// Well, we found endstream\nendobj within the space
|
||||||
// allowed for this object, so we're probably in good
|
// allowed for this object, so we're probably in good
|
||||||
// shape.
|
// shape.
|
||||||
@ -1777,13 +1756,11 @@ QPDF::readObjectAtOffset(
|
|||||||
bool try_recovery,
|
bool try_recovery,
|
||||||
qpdf_offset_t offset,
|
qpdf_offset_t offset,
|
||||||
std::string const& description,
|
std::string const& description,
|
||||||
int exp_objid,
|
QPDFObjGen const& exp_og,
|
||||||
int exp_generation,
|
QPDFObjGen& og)
|
||||||
int& objid,
|
|
||||||
int& generation)
|
|
||||||
{
|
{
|
||||||
bool check_og = true;
|
bool check_og = true;
|
||||||
if (exp_objid == 0) {
|
if (exp_og.getObj() == 0) {
|
||||||
// This method uses an expect object ID of 0 to indicate that
|
// This method uses an expect object ID of 0 to indicate that
|
||||||
// we don't know or don't care what the actual object ID is at
|
// we don't know or don't care what the actual object ID is at
|
||||||
// this offset. This is true when we read the xref stream and
|
// this offset. This is true when we read the xref stream and
|
||||||
@ -1795,7 +1772,7 @@ QPDF::readObjectAtOffset(
|
|||||||
check_og = false;
|
check_og = false;
|
||||||
try_recovery = false;
|
try_recovery = false;
|
||||||
} else {
|
} else {
|
||||||
setLastObjectDescription(description, exp_objid, exp_generation);
|
setLastObjectDescription(description, exp_og);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this->m->attempt_recovery) {
|
if (!this->m->attempt_recovery) {
|
||||||
@ -1841,9 +1818,9 @@ QPDF::readObjectAtOffset(
|
|||||||
offset,
|
offset,
|
||||||
"expected n n obj");
|
"expected n n obj");
|
||||||
}
|
}
|
||||||
objid = QUtil::string_to_int(tobjid.getValue().c_str());
|
int objid = QUtil::string_to_int(tobjid.getValue().c_str());
|
||||||
generation = QUtil::string_to_int(tgen.getValue().c_str());
|
int generation = QUtil::string_to_int(tgen.getValue().c_str());
|
||||||
|
og = QPDFObjGen(objid, generation);
|
||||||
if (objid == 0) {
|
if (objid == 0) {
|
||||||
QTC::TC("qpdf", "QPDF object id 0");
|
QTC::TC("qpdf", "QPDF object id 0");
|
||||||
throw QPDFExc(
|
throw QPDFExc(
|
||||||
@ -1853,17 +1830,14 @@ QPDF::readObjectAtOffset(
|
|||||||
offset,
|
offset,
|
||||||
"object with ID 0");
|
"object with ID 0");
|
||||||
}
|
}
|
||||||
|
if (check_og && (exp_og != og)) {
|
||||||
if (check_og &&
|
|
||||||
(!((objid == exp_objid) && (generation == exp_generation)))) {
|
|
||||||
QTC::TC("qpdf", "QPDF err wrong objid/generation");
|
QTC::TC("qpdf", "QPDF err wrong objid/generation");
|
||||||
QPDFExc e(
|
QPDFExc e(
|
||||||
qpdf_e_damaged_pdf,
|
qpdf_e_damaged_pdf,
|
||||||
this->m->file->getName(),
|
this->m->file->getName(),
|
||||||
this->m->last_object_description,
|
this->m->last_object_description,
|
||||||
offset,
|
offset,
|
||||||
(std::string("expected ") + QUtil::int_to_string(exp_objid) +
|
(std::string("expected ") + exp_og.unparse(' ') + " obj"));
|
||||||
" " + QUtil::int_to_string(exp_generation) + " obj"));
|
|
||||||
if (try_recovery) {
|
if (try_recovery) {
|
||||||
// Will be retried below
|
// Will be retried below
|
||||||
throw e;
|
throw e;
|
||||||
@ -1877,18 +1851,12 @@ QPDF::readObjectAtOffset(
|
|||||||
if (try_recovery) {
|
if (try_recovery) {
|
||||||
// Try again after reconstructing xref table
|
// Try again after reconstructing xref table
|
||||||
reconstruct_xref(e);
|
reconstruct_xref(e);
|
||||||
QPDFObjGen og(exp_objid, exp_generation);
|
if (this->m->xref_table.count(exp_og) &&
|
||||||
if (this->m->xref_table.count(og) &&
|
(this->m->xref_table[exp_og].getType() == 1)) {
|
||||||
(this->m->xref_table[og].getType() == 1)) {
|
qpdf_offset_t new_offset =
|
||||||
qpdf_offset_t new_offset = this->m->xref_table[og].getOffset();
|
this->m->xref_table[exp_og].getOffset();
|
||||||
QPDFObjectHandle result = readObjectAtOffset(
|
QPDFObjectHandle result = readObjectAtOffset(
|
||||||
false,
|
false, new_offset, description, exp_og, og);
|
||||||
new_offset,
|
|
||||||
description,
|
|
||||||
exp_objid,
|
|
||||||
exp_generation,
|
|
||||||
objid,
|
|
||||||
generation);
|
|
||||||
QTC::TC("qpdf", "QPDF recovered in readObjectAtOffset");
|
QTC::TC("qpdf", "QPDF recovered in readObjectAtOffset");
|
||||||
return result;
|
return result;
|
||||||
} else {
|
} else {
|
||||||
@ -1898,8 +1866,7 @@ QPDF::readObjectAtOffset(
|
|||||||
"",
|
"",
|
||||||
0,
|
0,
|
||||||
std::string(
|
std::string(
|
||||||
"object " + QUtil::int_to_string(exp_objid) + " " +
|
"object " + exp_og.unparse(' ') +
|
||||||
QUtil::int_to_string(exp_generation) +
|
|
||||||
" not found in file after regenerating"
|
" not found in file after regenerating"
|
||||||
" cross reference table"));
|
" cross reference table"));
|
||||||
return QPDFObjectHandle::newNull();
|
return QPDFObjectHandle::newNull();
|
||||||
@ -1909,8 +1876,7 @@ QPDF::readObjectAtOffset(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QPDFObjectHandle oh =
|
QPDFObjectHandle oh = readObject(this->m->file, description, og, false);
|
||||||
readObject(this->m->file, description, objid, generation, false);
|
|
||||||
|
|
||||||
if (!(readToken(this->m->file) ==
|
if (!(readToken(this->m->file) ==
|
||||||
QPDFTokenizer::Token(QPDFTokenizer::tt_word, "endobj"))) {
|
QPDFTokenizer::Token(QPDFTokenizer::tt_word, "endobj"))) {
|
||||||
@ -1922,7 +1888,6 @@ QPDF::readObjectAtOffset(
|
|||||||
"expected endobj");
|
"expected endobj");
|
||||||
}
|
}
|
||||||
|
|
||||||
QPDFObjGen og(objid, generation);
|
|
||||||
if (!this->m->obj_cache.count(og)) {
|
if (!this->m->obj_cache.count(og)) {
|
||||||
// Store the object in the cache here so it gets cached
|
// Store the object in the cache here so it gets cached
|
||||||
// whether we first know the offset or whether we first know
|
// whether we first know the offset or whether we first know
|
||||||
@ -1987,12 +1952,11 @@ QPDF::objectChanged(QPDFObjGen const& og, std::shared_ptr<QPDFObject>& oph)
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<QPDFObject>
|
std::shared_ptr<QPDFObject>
|
||||||
QPDF::resolve(int objid, int generation)
|
QPDF::resolve(QPDFObjGen const& og)
|
||||||
{
|
{
|
||||||
// Check object cache before checking xref table. This allows us
|
// Check object cache before checking xref table. This allows us
|
||||||
// to insert things into the object cache that don't actually
|
// to insert things into the object cache that don't actually
|
||||||
// exist in the file.
|
// exist in the file.
|
||||||
QPDFObjGen og(objid, generation);
|
|
||||||
if (this->m->resolving.count(og)) {
|
if (this->m->resolving.count(og)) {
|
||||||
// This can happen if an object references itself directly or
|
// This can happen if an object references itself directly or
|
||||||
// indirectly in some key that has to be resolved during
|
// indirectly in some key that has to be resolved during
|
||||||
@ -2002,8 +1966,7 @@ QPDF::resolve(int objid, int generation)
|
|||||||
qpdf_e_damaged_pdf,
|
qpdf_e_damaged_pdf,
|
||||||
"",
|
"",
|
||||||
this->m->file->getLastOffset(),
|
this->m->file->getLastOffset(),
|
||||||
("loop detected resolving object " + QUtil::int_to_string(objid) +
|
("loop detected resolving object " + og.unparse(' ')));
|
||||||
" " + QUtil::int_to_string(generation)));
|
|
||||||
return QPDF_Null::create();
|
return QPDF_Null::create();
|
||||||
}
|
}
|
||||||
ResolveRecorder rr(this, og);
|
ResolveRecorder rr(this, og);
|
||||||
@ -2016,16 +1979,9 @@ QPDF::resolve(int objid, int generation)
|
|||||||
{
|
{
|
||||||
qpdf_offset_t offset = entry.getOffset();
|
qpdf_offset_t offset = entry.getOffset();
|
||||||
// Object stored in cache by readObjectAtOffset
|
// Object stored in cache by readObjectAtOffset
|
||||||
int aobjid;
|
QPDFObjGen a_og;
|
||||||
int ageneration;
|
QPDFObjectHandle oh =
|
||||||
QPDFObjectHandle oh = readObjectAtOffset(
|
readObjectAtOffset(true, offset, "", og, a_og);
|
||||||
true,
|
|
||||||
offset,
|
|
||||||
"",
|
|
||||||
objid,
|
|
||||||
generation,
|
|
||||||
aobjid,
|
|
||||||
ageneration);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -2039,8 +1995,7 @@ QPDF::resolve(int objid, int generation)
|
|||||||
this->m->file->getName(),
|
this->m->file->getName(),
|
||||||
"",
|
"",
|
||||||
0,
|
0,
|
||||||
("object " + QUtil::int_to_string(objid) + "/" +
|
("object " + og.unparse('/') +
|
||||||
QUtil::int_to_string(generation) +
|
|
||||||
" has unexpected xref entry type"));
|
" has unexpected xref entry type"));
|
||||||
}
|
}
|
||||||
} catch (QPDFExc& e) {
|
} catch (QPDFExc& e) {
|
||||||
@ -2050,8 +2005,7 @@ QPDF::resolve(int objid, int generation)
|
|||||||
qpdf_e_damaged_pdf,
|
qpdf_e_damaged_pdf,
|
||||||
"",
|
"",
|
||||||
0,
|
0,
|
||||||
("object " + QUtil::int_to_string(objid) + "/" +
|
("object " + og.unparse('/') +
|
||||||
QUtil::int_to_string(generation) +
|
|
||||||
": error reading object: " + e.what()));
|
": error reading object: " + e.what()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2065,10 +2019,7 @@ QPDF::resolve(int objid, int generation)
|
|||||||
|
|
||||||
std::shared_ptr<QPDFObject> result(this->m->obj_cache[og].object);
|
std::shared_ptr<QPDFObject> result(this->m->obj_cache[og].object);
|
||||||
if (!result->hasDescription()) {
|
if (!result->hasDescription()) {
|
||||||
result->setDescription(
|
result->setDescription(this, ("object " + og.unparse(' ')));
|
||||||
this,
|
|
||||||
("object " + QUtil::int_to_string(objid) + " " +
|
|
||||||
QUtil::int_to_string(generation)));
|
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -2165,7 +2116,7 @@ QPDF::resolveObjectsInStream(int obj_stream_number)
|
|||||||
(entry.getObjStreamNumber() == obj_stream_number)) {
|
(entry.getObjStreamNumber() == obj_stream_number)) {
|
||||||
int offset = iter.second;
|
int offset = iter.second;
|
||||||
input->seek(offset, SEEK_SET);
|
input->seek(offset, SEEK_SET);
|
||||||
QPDFObjectHandle oh = readObject(input, "", obj, 0, true);
|
QPDFObjectHandle oh = readObject(input, "", og, true);
|
||||||
this->m->obj_cache[og] = ObjCache(
|
this->m->obj_cache[og] = ObjCache(
|
||||||
QPDFObjectHandle::ObjAccessor::getObject(oh),
|
QPDFObjectHandle::ObjAccessor::getObject(oh),
|
||||||
end_before_space,
|
end_before_space,
|
||||||
@ -2187,48 +2138,46 @@ QPDF::makeIndirectObject(QPDFObjectHandle oh)
|
|||||||
QPDFObjGen next(max_objid + 1, 0);
|
QPDFObjGen next(max_objid + 1, 0);
|
||||||
this->m->obj_cache[next] =
|
this->m->obj_cache[next] =
|
||||||
ObjCache(QPDFObjectHandle::ObjAccessor::getObject(oh), -1, -1);
|
ObjCache(QPDFObjectHandle::ObjAccessor::getObject(oh), -1, -1);
|
||||||
return QPDFObjectHandle::Factory::newIndirect(
|
return QPDFObjectHandle::Factory::newIndirect(this, next);
|
||||||
this, next.getObj(), next.getGen());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QPDFObjectHandle
|
QPDFObjectHandle
|
||||||
QPDF::reserveObjectIfNotExists(int objid, int gen)
|
QPDF::reserveObjectIfNotExists(QPDFObjGen const& og)
|
||||||
{
|
{
|
||||||
QPDFObjGen og(objid, gen);
|
|
||||||
if ((!this->m->obj_cache.count(og)) && (!this->m->xref_table.count(og))) {
|
if ((!this->m->obj_cache.count(og)) && (!this->m->xref_table.count(og))) {
|
||||||
resolve(objid, gen);
|
resolve(og);
|
||||||
replaceObject(objid, gen, QPDFObjectHandle::Factory::makeReserved());
|
replaceObject(og, QPDFObjectHandle::Factory::makeReserved());
|
||||||
}
|
}
|
||||||
return getObjectByID(objid, gen);
|
return getObjectByObjGen(og);
|
||||||
}
|
}
|
||||||
|
|
||||||
QPDFObjectHandle
|
QPDFObjectHandle
|
||||||
QPDF::reserveStream(int objid, int gen)
|
QPDF::reserveStream(QPDFObjGen const& og)
|
||||||
{
|
{
|
||||||
return QPDFObjectHandle::Factory::newStream(
|
return QPDFObjectHandle::Factory::newStream(
|
||||||
this, objid, gen, QPDFObjectHandle::newDictionary(), 0, 0);
|
this, og, QPDFObjectHandle::newDictionary(), 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
QPDFObjectHandle
|
QPDFObjectHandle
|
||||||
QPDF::getObjectByObjGen(QPDFObjGen const& og)
|
QPDF::getObjectByObjGen(QPDFObjGen const& og)
|
||||||
{
|
{
|
||||||
return getObjectByID(og.getObj(), og.getGen());
|
return QPDFObjectHandle::Factory::newIndirect(this, og);
|
||||||
}
|
}
|
||||||
|
|
||||||
QPDFObjectHandle
|
QPDFObjectHandle
|
||||||
QPDF::getObjectByID(int objid, int generation)
|
QPDF::getObjectByID(int objid, int generation)
|
||||||
{
|
{
|
||||||
return QPDFObjectHandle::Factory::newIndirect(this, objid, generation);
|
return getObjectByObjGen(QPDFObjGen(objid, generation));
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
QPDF::replaceObject(QPDFObjGen const& og, QPDFObjectHandle oh)
|
|
||||||
{
|
|
||||||
replaceObject(og.getObj(), og.getGen(), oh);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
QPDF::replaceObject(int objid, int generation, QPDFObjectHandle oh)
|
QPDF::replaceObject(int objid, int generation, QPDFObjectHandle oh)
|
||||||
|
{
|
||||||
|
replaceObject(QPDFObjGen(objid, generation), oh);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
QPDF::replaceObject(QPDFObjGen const& og, QPDFObjectHandle oh)
|
||||||
{
|
{
|
||||||
if (oh.isIndirect()) {
|
if (oh.isIndirect()) {
|
||||||
QTC::TC("qpdf", "QPDF replaceObject called with indirect object");
|
QTC::TC("qpdf", "QPDF replaceObject called with indirect object");
|
||||||
@ -2237,10 +2186,9 @@ QPDF::replaceObject(int objid, int generation, QPDFObjectHandle oh)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Force new object to appear in the cache
|
// Force new object to appear in the cache
|
||||||
resolve(objid, generation);
|
resolve(og);
|
||||||
|
|
||||||
// Replace the object in the object cache
|
// Replace the object in the object cache
|
||||||
QPDFObjGen og(objid, generation);
|
|
||||||
this->m->ever_replaced_objects = true;
|
this->m->ever_replaced_objects = true;
|
||||||
this->m->obj_cache[og] =
|
this->m->obj_cache[og] =
|
||||||
ObjCache(QPDFObjectHandle::ObjAccessor::getObject(oh), -1, -1);
|
ObjCache(QPDFObjectHandle::ObjAccessor::getObject(oh), -1, -1);
|
||||||
@ -2540,8 +2488,7 @@ QPDF::copyStreamData(QPDFObjectHandle result, QPDFObjectHandle foreign)
|
|||||||
auto foreign_stream_data = std::make_shared<ForeignStreamData>(
|
auto foreign_stream_data = std::make_shared<ForeignStreamData>(
|
||||||
foreign_stream_qpdf->m->encp,
|
foreign_stream_qpdf->m->encp,
|
||||||
foreign_stream_qpdf->m->file,
|
foreign_stream_qpdf->m->file,
|
||||||
foreign.getObjectID(),
|
foreign.getObjGen(),
|
||||||
foreign.getGeneration(),
|
|
||||||
stream->getOffset(),
|
stream->getOffset(),
|
||||||
stream->getLength(),
|
stream->getLength(),
|
||||||
dict);
|
dict);
|
||||||
@ -2555,20 +2502,19 @@ QPDF::copyStreamData(QPDFObjectHandle result, QPDFObjectHandle foreign)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
QPDF::swapObjects(QPDFObjGen const& og1, QPDFObjGen const& og2)
|
QPDF::swapObjects(int objid1, int generation1, int objid2, int generation2)
|
||||||
{
|
{
|
||||||
swapObjects(og1.getObj(), og1.getGen(), og2.getObj(), og2.getGen());
|
swapObjects(
|
||||||
|
QPDFObjGen(objid1, generation1), QPDFObjGen(objid2, generation2));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
QPDF::swapObjects(int objid1, int generation1, int objid2, int generation2)
|
QPDF::swapObjects(QPDFObjGen const& og1, QPDFObjGen const& og2)
|
||||||
{
|
{
|
||||||
// Force objects to be loaded into cache; then swap them in the
|
// Force objects to be loaded into cache; then swap them in the
|
||||||
// cache.
|
// cache.
|
||||||
resolve(objid1, generation1);
|
resolve(og1);
|
||||||
resolve(objid2, generation2);
|
resolve(og2);
|
||||||
QPDFObjGen og1(objid1, generation1);
|
|
||||||
QPDFObjGen og2(objid2, generation2);
|
|
||||||
ObjCache t = this->m->obj_cache[og1];
|
ObjCache t = this->m->obj_cache[og1];
|
||||||
this->m->ever_replaced_objects = true;
|
this->m->ever_replaced_objects = true;
|
||||||
this->m->obj_cache[og1] = this->m->obj_cache[og2];
|
this->m->obj_cache[og1] = this->m->obj_cache[og2];
|
||||||
@ -2752,8 +2698,7 @@ QPDF::pipeStreamData(
|
|||||||
std::shared_ptr<EncryptionParameters> encp,
|
std::shared_ptr<EncryptionParameters> encp,
|
||||||
std::shared_ptr<InputSource> file,
|
std::shared_ptr<InputSource> file,
|
||||||
QPDF& qpdf_for_warning,
|
QPDF& qpdf_for_warning,
|
||||||
int objid,
|
QPDFObjGen const& og,
|
||||||
int generation,
|
|
||||||
qpdf_offset_t offset,
|
qpdf_offset_t offset,
|
||||||
size_t length,
|
size_t length,
|
||||||
QPDFObjectHandle stream_dict,
|
QPDFObjectHandle stream_dict,
|
||||||
@ -2764,14 +2709,7 @@ QPDF::pipeStreamData(
|
|||||||
std::vector<std::shared_ptr<Pipeline>> to_delete;
|
std::vector<std::shared_ptr<Pipeline>> to_delete;
|
||||||
if (encp->encrypted) {
|
if (encp->encrypted) {
|
||||||
decryptStream(
|
decryptStream(
|
||||||
encp,
|
encp, file, qpdf_for_warning, pipeline, og, stream_dict, to_delete);
|
||||||
file,
|
|
||||||
qpdf_for_warning,
|
|
||||||
pipeline,
|
|
||||||
objid,
|
|
||||||
generation,
|
|
||||||
stream_dict,
|
|
||||||
to_delete);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool success = false;
|
bool success = false;
|
||||||
@ -2809,8 +2747,7 @@ QPDF::pipeStreamData(
|
|||||||
"",
|
"",
|
||||||
file->getLastOffset(),
|
file->getLastOffset(),
|
||||||
("error decoding stream data for object " +
|
("error decoding stream data for object " +
|
||||||
QUtil::int_to_string(objid) + " " +
|
og.unparse(' ') + ": " + e.what())));
|
||||||
QUtil::int_to_string(generation) + ": " + e.what())));
|
|
||||||
if (will_retry) {
|
if (will_retry) {
|
||||||
qpdf_for_warning.warn(
|
qpdf_for_warning.warn(
|
||||||
// line-break
|
// line-break
|
||||||
@ -2836,8 +2773,7 @@ QPDF::pipeStreamData(
|
|||||||
|
|
||||||
bool
|
bool
|
||||||
QPDF::pipeStreamData(
|
QPDF::pipeStreamData(
|
||||||
int objid,
|
QPDFObjGen const& og,
|
||||||
int generation,
|
|
||||||
qpdf_offset_t offset,
|
qpdf_offset_t offset,
|
||||||
size_t length,
|
size_t length,
|
||||||
QPDFObjectHandle stream_dict,
|
QPDFObjectHandle stream_dict,
|
||||||
@ -2849,8 +2785,7 @@ QPDF::pipeStreamData(
|
|||||||
this->m->encp,
|
this->m->encp,
|
||||||
this->m->file,
|
this->m->file,
|
||||||
*this,
|
*this,
|
||||||
objid,
|
og,
|
||||||
generation,
|
|
||||||
offset,
|
offset,
|
||||||
length,
|
length,
|
||||||
stream_dict,
|
stream_dict,
|
||||||
@ -2873,8 +2808,7 @@ QPDF::pipeForeignStreamData(
|
|||||||
foreign->encp,
|
foreign->encp,
|
||||||
foreign->file,
|
foreign->file,
|
||||||
*this,
|
*this,
|
||||||
foreign->foreign_objid,
|
foreign->foreign_og,
|
||||||
foreign->foreign_generation,
|
|
||||||
foreign->offset,
|
foreign->offset,
|
||||||
foreign->length,
|
foreign->length,
|
||||||
foreign->local_dict,
|
foreign->local_dict,
|
||||||
|
@ -991,8 +991,8 @@ QPDFAcroFormDocumentHelper::transformAnnotations(
|
|||||||
} else {
|
} else {
|
||||||
parent.warnIfPossible(
|
parent.warnIfPossible(
|
||||||
"while traversing field " +
|
"while traversing field " +
|
||||||
obj.getObjGen().unparse() + ", found parent (" +
|
obj.getObjGen().unparse(',') + ", found parent (" +
|
||||||
parent_og.unparse() +
|
parent_og.unparse(',') +
|
||||||
") that had not been seen, indicating likely"
|
") that had not been seen, indicating likely"
|
||||||
" invalid field structure");
|
" invalid field structure");
|
||||||
}
|
}
|
||||||
|
@ -49,8 +49,7 @@ namespace
|
|||||||
size_t oi_min_area,
|
size_t oi_min_area,
|
||||||
QPDFObjectHandle& image);
|
QPDFObjectHandle& image);
|
||||||
virtual ~ImageOptimizer() = default;
|
virtual ~ImageOptimizer() = default;
|
||||||
virtual void
|
virtual void provideStreamData(QPDFObjGen const&, Pipeline* pipeline);
|
||||||
provideStreamData(int objid, int generation, Pipeline* pipeline);
|
|
||||||
std::shared_ptr<Pipeline>
|
std::shared_ptr<Pipeline>
|
||||||
makePipeline(std::string const& description, Pipeline* next);
|
makePipeline(std::string const& description, Pipeline* next);
|
||||||
bool evaluate(std::string const& description);
|
bool evaluate(std::string const& description);
|
||||||
@ -250,7 +249,7 @@ ImageOptimizer::evaluate(std::string const& description)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ImageOptimizer::provideStreamData(int, int, Pipeline* pipeline)
|
ImageOptimizer::provideStreamData(QPDFObjGen const&, Pipeline* pipeline)
|
||||||
{
|
{
|
||||||
std::shared_ptr<Pipeline> p = makePipeline("", pipeline);
|
std::shared_ptr<Pipeline> p = makePipeline("", pipeline);
|
||||||
if (p.get() == nullptr) {
|
if (p.get() == nullptr) {
|
||||||
@ -947,7 +946,7 @@ QPDFJob::doShowObj(QPDF& pdf)
|
|||||||
}
|
}
|
||||||
if (error) {
|
if (error) {
|
||||||
throw std::runtime_error(
|
throw std::runtime_error(
|
||||||
"unable to get object " + obj.getObjGen().unparse());
|
"unable to get object " + obj.getObjGen().unparse(','));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -995,7 +994,8 @@ QPDFJob::doListAttachments(QPDF& pdf)
|
|||||||
auto efoh = i.second;
|
auto efoh = i.second;
|
||||||
*this->m->log->getInfo()
|
*this->m->log->getInfo()
|
||||||
<< key << " -> "
|
<< key << " -> "
|
||||||
<< efoh->getEmbeddedFileStream().getObjGen().unparse() << "\n";
|
<< efoh->getEmbeddedFileStream().getObjGen().unparse(',')
|
||||||
|
<< "\n";
|
||||||
doIfVerbose([&](Pipeline& v, std::string const& prefix) {
|
doIfVerbose([&](Pipeline& v, std::string const& prefix) {
|
||||||
auto desc = efoh->getDescription();
|
auto desc = efoh->getDescription();
|
||||||
if (!desc.empty()) {
|
if (!desc.empty()) {
|
||||||
@ -1010,7 +1010,7 @@ QPDFJob::doListAttachments(QPDF& pdf)
|
|||||||
for (auto i2: efoh->getEmbeddedFileStreams().ditems()) {
|
for (auto i2: efoh->getEmbeddedFileStreams().ditems()) {
|
||||||
auto efs = QPDFEFStreamObjectHelper(i2.second);
|
auto efs = QPDFEFStreamObjectHelper(i2.second);
|
||||||
v << " " << i2.first << " -> "
|
v << " " << i2.first << " -> "
|
||||||
<< efs.getObjectHandle().getObjGen().unparse() << "\n";
|
<< efs.getObjectHandle().getObjGen().unparse(',') << "\n";
|
||||||
v << " creation date: " << efs.getCreationDate()
|
v << " creation date: " << efs.getCreationDate()
|
||||||
<< "\n"
|
<< "\n"
|
||||||
<< " modification date: " << efs.getModDate() << "\n"
|
<< " modification date: " << efs.getModDate() << "\n"
|
||||||
@ -2463,7 +2463,7 @@ QPDFJob::shouldRemoveUnreferencedResources(QPDF& pdf)
|
|||||||
QTC::TC("qpdf", "QPDFJob found resources in non-leaf");
|
QTC::TC("qpdf", "QPDFJob found resources in non-leaf");
|
||||||
doIfVerbose([&](Pipeline& v, std::string const& prefix) {
|
doIfVerbose([&](Pipeline& v, std::string const& prefix) {
|
||||||
v << " found resources in non-leaf page node "
|
v << " found resources in non-leaf page node "
|
||||||
<< og.getObj() << " " << og.getGen() << "\n";
|
<< og.unparse(' ') << "\n";
|
||||||
});
|
});
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -2480,9 +2480,8 @@ QPDFJob::shouldRemoveUnreferencedResources(QPDF& pdf)
|
|||||||
QTC::TC("qpdf", "QPDFJob found shared resources in leaf");
|
QTC::TC("qpdf", "QPDFJob found shared resources in leaf");
|
||||||
doIfVerbose([&](Pipeline& v, std::string const& prefix) {
|
doIfVerbose([&](Pipeline& v, std::string const& prefix) {
|
||||||
v << " found shared resources in leaf node "
|
v << " found shared resources in leaf node "
|
||||||
<< og.getObj() << " " << og.getGen() << ": "
|
<< og.unparse(' ') << ": "
|
||||||
<< resources_og.getObj() << " "
|
<< resources_og.unparse(' ') << "\n";
|
||||||
<< resources_og.getGen() << "\n";
|
|
||||||
});
|
});
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -2497,8 +2496,7 @@ QPDFJob::shouldRemoveUnreferencedResources(QPDF& pdf)
|
|||||||
QTC::TC("qpdf", "QPDFJob found shared xobject in leaf");
|
QTC::TC("qpdf", "QPDFJob found shared xobject in leaf");
|
||||||
doIfVerbose([&](Pipeline& v, std::string const& prefix) {
|
doIfVerbose([&](Pipeline& v, std::string const& prefix) {
|
||||||
v << " found shared xobject in leaf node "
|
v << " found shared xobject in leaf node "
|
||||||
<< og.getObj() << " " << og.getGen() << ": "
|
<< og.unparse(' ') << ": " << xobject_og.unparse(' ')
|
||||||
<< xobject_og.getObj() << " " << xobject_og.getGen()
|
|
||||||
<< "\n";
|
<< "\n";
|
||||||
});
|
});
|
||||||
return true;
|
return true;
|
||||||
@ -3375,7 +3373,7 @@ QPDFJob::writeJSON(QPDF& pdf)
|
|||||||
auto wanted = getWantedJSONObjects();
|
auto wanted = getWantedJSONObjects();
|
||||||
for (auto const& og: wanted) {
|
for (auto const& og: wanted) {
|
||||||
std::ostringstream s;
|
std::ostringstream s;
|
||||||
s << "obj:" << og.getObj() << " " << og.getGen() << " R";
|
s << "obj:" << og.unparse(' ') << " R";
|
||||||
json_objects.insert(s.str());
|
json_objects.insert(s.str());
|
||||||
}
|
}
|
||||||
pdf.writeJSON(
|
pdf.writeJSON(
|
||||||
|
17
libqpdf/QPDFObjGen.cc
Normal file
17
libqpdf/QPDFObjGen.cc
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#include <qpdf/QPDFObjGen.hh>
|
||||||
|
|
||||||
|
#include <qpdf/QUtil.hh>
|
||||||
|
|
||||||
|
std::ostream&
|
||||||
|
operator<<(std::ostream& os, const QPDFObjGen& og)
|
||||||
|
{
|
||||||
|
os << og.obj << "," << og.gen;
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string
|
||||||
|
QPDFObjGen::unparse(char separator) const
|
||||||
|
{
|
||||||
|
return QUtil::int_to_string(this->obj) + separator +
|
||||||
|
QUtil::int_to_string(this->gen);
|
||||||
|
}
|
@ -51,6 +51,24 @@ QPDFObjectHandle::StreamDataProvider::~StreamDataProvider()
|
|||||||
// README-maintainer
|
// README-maintainer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
QPDFObjectHandle::StreamDataProvider::provideStreamData(
|
||||||
|
QPDFObjGen const& og, Pipeline* pipeline)
|
||||||
|
{
|
||||||
|
return provideStreamData(og.getObj(), og.getGen(), pipeline);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
QPDFObjectHandle::StreamDataProvider::provideStreamData(
|
||||||
|
QPDFObjGen const& og,
|
||||||
|
Pipeline* pipeline,
|
||||||
|
bool suppress_warnings,
|
||||||
|
bool will_retry)
|
||||||
|
{
|
||||||
|
return provideStreamData(
|
||||||
|
og.getObj(), og.getGen(), pipeline, suppress_warnings, will_retry);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
QPDFObjectHandle::StreamDataProvider::provideStreamData(
|
QPDFObjectHandle::StreamDataProvider::provideStreamData(
|
||||||
int objid, int generation, Pipeline* pipeline)
|
int objid, int generation, Pipeline* pipeline)
|
||||||
@ -90,8 +108,7 @@ namespace
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
virtual ~CoalesceProvider() = default;
|
virtual ~CoalesceProvider() = default;
|
||||||
virtual void
|
virtual void provideStreamData(QPDFObjGen const&, Pipeline* pipeline);
|
||||||
provideStreamData(int objid, int generation, Pipeline* pipeline);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QPDFObjectHandle containing_page;
|
QPDFObjectHandle containing_page;
|
||||||
@ -100,12 +117,11 @@ namespace
|
|||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
void
|
void
|
||||||
CoalesceProvider::provideStreamData(int, int, Pipeline* p)
|
CoalesceProvider::provideStreamData(QPDFObjGen const&, Pipeline* p)
|
||||||
{
|
{
|
||||||
QTC::TC("qpdf", "QPDFObjectHandle coalesce provide stream data");
|
QTC::TC("qpdf", "QPDFObjectHandle coalesce provide stream data");
|
||||||
std::string description = "page object " +
|
std::string description =
|
||||||
QUtil::int_to_string(containing_page.getObjectID()) + " " +
|
"page object " + containing_page.getObjGen().unparse(' ');
|
||||||
QUtil::int_to_string(containing_page.getGeneration());
|
|
||||||
std::string all_description;
|
std::string all_description;
|
||||||
old_contents.pipeContentStreams(p, description, all_description);
|
old_contents.pipeContentStreams(p, description, all_description);
|
||||||
}
|
}
|
||||||
@ -219,27 +235,22 @@ LastChar::getLastChar()
|
|||||||
|
|
||||||
QPDFObjectHandle::QPDFObjectHandle() :
|
QPDFObjectHandle::QPDFObjectHandle() :
|
||||||
initialized(false),
|
initialized(false),
|
||||||
qpdf(0),
|
qpdf(nullptr),
|
||||||
objid(0),
|
|
||||||
generation(0),
|
|
||||||
reserved(false)
|
reserved(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
QPDFObjectHandle::QPDFObjectHandle(QPDF* qpdf, int objid, int generation) :
|
QPDFObjectHandle::QPDFObjectHandle(QPDF* qpdf, QPDFObjGen const& og) :
|
||||||
initialized(true),
|
initialized(true),
|
||||||
qpdf(qpdf),
|
qpdf(qpdf),
|
||||||
objid(objid),
|
og(og),
|
||||||
generation(generation),
|
|
||||||
reserved(false)
|
reserved(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
QPDFObjectHandle::QPDFObjectHandle(std::shared_ptr<QPDFObject> const& data) :
|
QPDFObjectHandle::QPDFObjectHandle(std::shared_ptr<QPDFObject> const& data) :
|
||||||
initialized(true),
|
initialized(true),
|
||||||
qpdf(0),
|
qpdf(nullptr),
|
||||||
objid(0),
|
|
||||||
generation(0),
|
|
||||||
obj(data),
|
obj(data),
|
||||||
reserved(false)
|
reserved(false)
|
||||||
{
|
{
|
||||||
@ -1431,15 +1442,14 @@ namespace
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual void
|
virtual void
|
||||||
provideStreamData(int, int, Pipeline* pipeline) override
|
provideStreamData(QPDFObjGen const&, Pipeline* pipeline) override
|
||||||
{
|
{
|
||||||
p1(pipeline);
|
p1(pipeline);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool
|
virtual bool
|
||||||
provideStreamData(
|
provideStreamData(
|
||||||
int,
|
QPDFObjGen const&,
|
||||||
int,
|
|
||||||
Pipeline* pipeline,
|
Pipeline* pipeline,
|
||||||
bool suppress_warnings,
|
bool suppress_warnings,
|
||||||
bool will_retry) override
|
bool will_retry) override
|
||||||
@ -1482,26 +1492,19 @@ QPDFObjectHandle::replaceStreamData(
|
|||||||
QPDFObjGen
|
QPDFObjGen
|
||||||
QPDFObjectHandle::getObjGen() const
|
QPDFObjectHandle::getObjGen() const
|
||||||
{
|
{
|
||||||
return QPDFObjGen(this->objid, this->generation);
|
return og;
|
||||||
}
|
|
||||||
|
|
||||||
std::string
|
|
||||||
QPDFObjectHandle::getObjGenAsStr() const
|
|
||||||
{
|
|
||||||
return QUtil::int_to_string(this->objid) + " " +
|
|
||||||
QUtil::int_to_string(this->generation);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
QPDFObjectHandle::getObjectID() const
|
QPDFObjectHandle::getObjectID() const
|
||||||
{
|
{
|
||||||
return this->objid;
|
return og.getObj();
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
QPDFObjectHandle::getGeneration() const
|
QPDFObjectHandle::getGeneration() const
|
||||||
{
|
{
|
||||||
return this->generation;
|
return og.getGen();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<std::string, QPDFObjectHandle>
|
std::map<std::string, QPDFObjectHandle>
|
||||||
@ -1556,7 +1559,7 @@ QPDFObjectHandle::arrayOrStreamToStreamArray(
|
|||||||
} else {
|
} else {
|
||||||
all_description += ",";
|
all_description += ",";
|
||||||
}
|
}
|
||||||
all_description += " stream " + item.getObjGenAsStr();
|
all_description += " stream " + item.getObjGen().unparse(' ');
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@ -1565,7 +1568,7 @@ QPDFObjectHandle::arrayOrStreamToStreamArray(
|
|||||||
std::vector<QPDFObjectHandle>
|
std::vector<QPDFObjectHandle>
|
||||||
QPDFObjectHandle::getPageContents()
|
QPDFObjectHandle::getPageContents()
|
||||||
{
|
{
|
||||||
std::string description = "page object " + getObjGenAsStr();
|
std::string description = "page object " + getObjGen().unparse(' ');
|
||||||
std::string all_description;
|
std::string all_description;
|
||||||
return this->getKey("/Contents")
|
return this->getKey("/Contents")
|
||||||
.arrayOrStreamToStreamArray(description, all_description);
|
.arrayOrStreamToStreamArray(description, all_description);
|
||||||
@ -1674,7 +1677,7 @@ QPDFObjectHandle::unparse()
|
|||||||
{
|
{
|
||||||
std::string result;
|
std::string result;
|
||||||
if (this->isIndirect()) {
|
if (this->isIndirect()) {
|
||||||
result = getObjGenAsStr() + " R";
|
result = getObjGen().unparse(' ') + " R";
|
||||||
} else {
|
} else {
|
||||||
result = unparseResolved();
|
result = unparseResolved();
|
||||||
}
|
}
|
||||||
@ -1789,7 +1792,7 @@ QPDFObjectHandle::parse(
|
|||||||
void
|
void
|
||||||
QPDFObjectHandle::pipePageContents(Pipeline* p)
|
QPDFObjectHandle::pipePageContents(Pipeline* p)
|
||||||
{
|
{
|
||||||
std::string description = "page object " + getObjGenAsStr();
|
std::string description = "page object " + getObjGen().unparse(' ');
|
||||||
std::string all_description;
|
std::string all_description;
|
||||||
this->getKey("/Contents")
|
this->getKey("/Contents")
|
||||||
.pipeContentStreams(p, description, all_description);
|
.pipeContentStreams(p, description, all_description);
|
||||||
@ -1813,7 +1816,7 @@ QPDFObjectHandle::pipeContentStreams(
|
|||||||
throw QPDFExc(
|
throw QPDFExc(
|
||||||
qpdf_e_damaged_pdf,
|
qpdf_e_damaged_pdf,
|
||||||
"content stream",
|
"content stream",
|
||||||
"content stream object " + stream.getObjGenAsStr(),
|
"content stream object " + stream.getObjGen().unparse(' '),
|
||||||
0,
|
0,
|
||||||
"errors while decoding content stream");
|
"errors while decoding content stream");
|
||||||
}
|
}
|
||||||
@ -1829,7 +1832,7 @@ QPDFObjectHandle::pipeContentStreams(
|
|||||||
void
|
void
|
||||||
QPDFObjectHandle::parsePageContents(ParserCallbacks* callbacks)
|
QPDFObjectHandle::parsePageContents(ParserCallbacks* callbacks)
|
||||||
{
|
{
|
||||||
std::string description = "page object " + getObjGenAsStr();
|
std::string description = "page object " + getObjGen().unparse(' ');
|
||||||
this->getKey("/Contents")
|
this->getKey("/Contents")
|
||||||
.parseContentStream_internal(description, callbacks);
|
.parseContentStream_internal(description, callbacks);
|
||||||
}
|
}
|
||||||
@ -1837,14 +1840,15 @@ QPDFObjectHandle::parsePageContents(ParserCallbacks* callbacks)
|
|||||||
void
|
void
|
||||||
QPDFObjectHandle::parseAsContents(ParserCallbacks* callbacks)
|
QPDFObjectHandle::parseAsContents(ParserCallbacks* callbacks)
|
||||||
{
|
{
|
||||||
std::string description = "object " + getObjGenAsStr();
|
std::string description = "object " + getObjGen().unparse(' ');
|
||||||
this->parseContentStream_internal(description, callbacks);
|
this->parseContentStream_internal(description, callbacks);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
QPDFObjectHandle::filterPageContents(TokenFilter* filter, Pipeline* next)
|
QPDFObjectHandle::filterPageContents(TokenFilter* filter, Pipeline* next)
|
||||||
{
|
{
|
||||||
auto description = "token filter for page object " + getObjGenAsStr();
|
auto description =
|
||||||
|
"token filter for page object " + getObjGen().unparse(' ');
|
||||||
Pl_QPDFTokenizer token_pipeline(description.c_str(), filter, next);
|
Pl_QPDFTokenizer token_pipeline(description.c_str(), filter, next);
|
||||||
this->pipePageContents(&token_pipeline);
|
this->pipePageContents(&token_pipeline);
|
||||||
}
|
}
|
||||||
@ -1852,7 +1856,7 @@ QPDFObjectHandle::filterPageContents(TokenFilter* filter, Pipeline* next)
|
|||||||
void
|
void
|
||||||
QPDFObjectHandle::filterAsContents(TokenFilter* filter, Pipeline* next)
|
QPDFObjectHandle::filterAsContents(TokenFilter* filter, Pipeline* next)
|
||||||
{
|
{
|
||||||
auto description = "token filter for object " + getObjGenAsStr();
|
auto description = "token filter for object " + getObjGen().unparse(' ');
|
||||||
Pl_QPDFTokenizer token_pipeline(description.c_str(), filter, next);
|
Pl_QPDFTokenizer token_pipeline(description.c_str(), filter, next);
|
||||||
this->pipeStreamData(&token_pipeline, 0, qpdf_dl_specialized);
|
this->pipeStreamData(&token_pipeline, 0, qpdf_dl_specialized);
|
||||||
}
|
}
|
||||||
@ -2192,8 +2196,9 @@ QPDFObjectHandle::parseInternal(
|
|||||||
// Try to resolve indirect objects
|
// Try to resolve indirect objects
|
||||||
object = newIndirect(
|
object = newIndirect(
|
||||||
context,
|
context,
|
||||||
olist.at(olist.size() - 2).getIntValueAsInt(),
|
QPDFObjGen(
|
||||||
olist.at(olist.size() - 1).getIntValueAsInt());
|
olist.at(olist.size() - 2).getIntValueAsInt(),
|
||||||
|
olist.at(olist.size() - 1).getIntValueAsInt()));
|
||||||
olist.remove_last();
|
olist.remove_last();
|
||||||
olist.remove_last();
|
olist.remove_last();
|
||||||
} else if ((value == "endobj") && (state == st_top)) {
|
} else if ((value == "endobj") && (state == st_top)) {
|
||||||
@ -2481,9 +2486,9 @@ QPDFObjectHandle::setParsedOffset(qpdf_offset_t offset)
|
|||||||
}
|
}
|
||||||
|
|
||||||
QPDFObjectHandle
|
QPDFObjectHandle
|
||||||
QPDFObjectHandle::newIndirect(QPDF* qpdf, int objid, int generation)
|
QPDFObjectHandle::newIndirect(QPDF* qpdf, QPDFObjGen const& og)
|
||||||
{
|
{
|
||||||
if (objid == 0) {
|
if (!og.isIndirect()) {
|
||||||
// Special case: QPDF uses objid 0 as a sentinel for direct
|
// Special case: QPDF uses objid 0 as a sentinel for direct
|
||||||
// objects, and the PDF specification doesn't allow for object
|
// objects, and the PDF specification doesn't allow for object
|
||||||
// 0. Treat indirect references to object 0 as null so that we
|
// 0. Treat indirect references to object 0 as null so that we
|
||||||
@ -2492,7 +2497,7 @@ QPDFObjectHandle::newIndirect(QPDF* qpdf, int objid, int generation)
|
|||||||
return newNull();
|
return newNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
return QPDFObjectHandle(qpdf, objid, generation);
|
return QPDFObjectHandle(qpdf, og);
|
||||||
}
|
}
|
||||||
|
|
||||||
QPDFObjectHandle
|
QPDFObjectHandle
|
||||||
@ -2640,14 +2645,13 @@ QPDFObjectHandle::newDictionary(
|
|||||||
QPDFObjectHandle
|
QPDFObjectHandle
|
||||||
QPDFObjectHandle::newStream(
|
QPDFObjectHandle::newStream(
|
||||||
QPDF* qpdf,
|
QPDF* qpdf,
|
||||||
int objid,
|
QPDFObjGen const& og,
|
||||||
int generation,
|
|
||||||
QPDFObjectHandle stream_dict,
|
QPDFObjectHandle stream_dict,
|
||||||
qpdf_offset_t offset,
|
qpdf_offset_t offset,
|
||||||
size_t length)
|
size_t length)
|
||||||
{
|
{
|
||||||
QPDFObjectHandle result = QPDFObjectHandle(QPDF_Stream::create(
|
QPDFObjectHandle result = QPDFObjectHandle(
|
||||||
qpdf, objid, generation, stream_dict, offset, length));
|
QPDF_Stream::create(qpdf, og, stream_dict, offset, length));
|
||||||
if (offset) {
|
if (offset) {
|
||||||
result.setParsedOffset(offset);
|
result.setParsedOffset(offset);
|
||||||
}
|
}
|
||||||
@ -2663,11 +2667,11 @@ QPDFObjectHandle::newStream(QPDF* qpdf)
|
|||||||
}
|
}
|
||||||
QTC::TC("qpdf", "QPDFObjectHandle newStream");
|
QTC::TC("qpdf", "QPDFObjectHandle newStream");
|
||||||
QPDFObjectHandle stream_dict = newDictionary();
|
QPDFObjectHandle stream_dict = newDictionary();
|
||||||
QPDFObjectHandle result = qpdf->makeIndirectObject(
|
QPDFObjectHandle result = qpdf->makeIndirectObject(QPDFObjectHandle(
|
||||||
QPDFObjectHandle(QPDF_Stream::create(qpdf, 0, 0, stream_dict, 0, 0)));
|
QPDF_Stream::create(qpdf, QPDFObjGen(), stream_dict, 0, 0)));
|
||||||
result.dereference();
|
result.dereference();
|
||||||
QPDF_Stream* stream = dynamic_cast<QPDF_Stream*>(result.obj.get());
|
QPDF_Stream* stream = dynamic_cast<QPDF_Stream*>(result.obj.get());
|
||||||
stream->setObjGen(result.getObjectID(), result.getGeneration());
|
stream->setObjGen(result.getObjGen());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2695,8 +2699,7 @@ QPDFObjectHandle::newReserved(QPDF* qpdf)
|
|||||||
// Reserve a spot for this object by assigning it an object
|
// Reserve a spot for this object by assigning it an object
|
||||||
// number, but then return an unresolved handle to the object.
|
// number, but then return an unresolved handle to the object.
|
||||||
QPDFObjectHandle reserved = qpdf->makeIndirectObject(makeReserved());
|
QPDFObjectHandle reserved = qpdf->makeIndirectObject(makeReserved());
|
||||||
QPDFObjectHandle result =
|
QPDFObjectHandle result = newIndirect(qpdf, reserved.getObjGen());
|
||||||
newIndirect(qpdf, reserved.objid, reserved.generation);
|
|
||||||
result.reserved = true;
|
result.reserved = true;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -2796,9 +2799,8 @@ QPDFObjectHandle::copyObject(
|
|||||||
" reserved object handle direct");
|
" reserved object handle direct");
|
||||||
}
|
}
|
||||||
|
|
||||||
this->qpdf = 0;
|
qpdf = nullptr;
|
||||||
this->objid = 0;
|
og = QPDFObjGen();
|
||||||
this->generation = 0;
|
|
||||||
|
|
||||||
std::shared_ptr<QPDFObject> new_obj;
|
std::shared_ptr<QPDFObject> new_obj;
|
||||||
|
|
||||||
@ -3112,7 +3114,7 @@ QPDFObjectHandle::dereference()
|
|||||||
}
|
}
|
||||||
if (this->obj.get() == 0) {
|
if (this->obj.get() == 0) {
|
||||||
std::shared_ptr<QPDFObject> obj =
|
std::shared_ptr<QPDFObject> obj =
|
||||||
QPDF::Resolver::resolve(this->qpdf, getObjectID(), getGeneration());
|
QPDF::Resolver::resolve(this->qpdf, getObjGen());
|
||||||
if (obj.get() == 0) {
|
if (obj.get() == 0) {
|
||||||
// QPDF::resolve never returns an uninitialized object, but
|
// QPDF::resolve never returns an uninitialized object, but
|
||||||
// check just in case.
|
// check just in case.
|
||||||
|
@ -21,8 +21,7 @@ namespace
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
virtual ~ContentProvider() = default;
|
virtual ~ContentProvider() = default;
|
||||||
virtual void
|
virtual void provideStreamData(QPDFObjGen const&, Pipeline* pipeline);
|
||||||
provideStreamData(int objid, int generation, Pipeline* pipeline);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QPDFObjectHandle from_page;
|
QPDFObjectHandle from_page;
|
||||||
@ -30,12 +29,11 @@ namespace
|
|||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
void
|
void
|
||||||
ContentProvider::provideStreamData(int, int, Pipeline* p)
|
ContentProvider::provideStreamData(QPDFObjGen const&, Pipeline* p)
|
||||||
{
|
{
|
||||||
Pl_Concatenate concat("concatenate", p);
|
Pl_Concatenate concat("concatenate", p);
|
||||||
std::string description = "contents from page object " +
|
std::string description =
|
||||||
QUtil::int_to_string(from_page.getObjectID()) + " " +
|
"contents from page object " + from_page.getObjGen().unparse(' ');
|
||||||
QUtil::int_to_string(from_page.getGeneration());
|
|
||||||
std::string all_description;
|
std::string all_description;
|
||||||
from_page.getKey("/Contents")
|
from_page.getKey("/Contents")
|
||||||
.pipeContentStreams(&concat, description, all_description);
|
.pipeContentStreams(&concat, description, all_description);
|
||||||
|
@ -1990,9 +1990,8 @@ QPDFWriter::writeObject(QPDFObjectHandle object, int object_stream_index)
|
|||||||
if (object_stream_index == -1) {
|
if (object_stream_index == -1) {
|
||||||
if (this->m->qdf_mode && (!this->m->suppress_original_object_ids)) {
|
if (this->m->qdf_mode && (!this->m->suppress_original_object_ids)) {
|
||||||
writeString(
|
writeString(
|
||||||
"%% Original object ID: " +
|
"%% Original object ID: " + object.getObjGen().unparse(' ') +
|
||||||
QUtil::int_to_string(object.getObjectID()) + " " +
|
"\n");
|
||||||
QUtil::int_to_string(object.getGeneration()) + "\n");
|
|
||||||
}
|
}
|
||||||
openObject(new_id);
|
openObject(new_id);
|
||||||
setDataKey(new_id);
|
setDataKey(new_id);
|
||||||
|
@ -110,14 +110,12 @@ StreamBlobProvider::operator()(Pipeline* p)
|
|||||||
|
|
||||||
QPDF_Stream::QPDF_Stream(
|
QPDF_Stream::QPDF_Stream(
|
||||||
QPDF* qpdf,
|
QPDF* qpdf,
|
||||||
int objid,
|
QPDFObjGen const& og,
|
||||||
int generation,
|
|
||||||
QPDFObjectHandle stream_dict,
|
QPDFObjectHandle stream_dict,
|
||||||
qpdf_offset_t offset,
|
qpdf_offset_t offset,
|
||||||
size_t length) :
|
size_t length) :
|
||||||
qpdf(qpdf),
|
qpdf(qpdf),
|
||||||
objid(objid),
|
og(og),
|
||||||
generation(generation),
|
|
||||||
filter_on_write(true),
|
filter_on_write(true),
|
||||||
stream_dict(stream_dict),
|
stream_dict(stream_dict),
|
||||||
offset(offset),
|
offset(offset),
|
||||||
@ -128,23 +126,18 @@ QPDF_Stream::QPDF_Stream(
|
|||||||
"object for dictionary");
|
"object for dictionary");
|
||||||
}
|
}
|
||||||
setDescription(
|
setDescription(
|
||||||
this->qpdf,
|
qpdf, qpdf->getFilename() + ", stream object " + og.unparse(' '));
|
||||||
this->qpdf->getFilename() + ", stream object " +
|
|
||||||
QUtil::int_to_string(this->objid) + " " +
|
|
||||||
QUtil::int_to_string(this->generation));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<QPDFObject>
|
std::shared_ptr<QPDFObject>
|
||||||
QPDF_Stream::create(
|
QPDF_Stream::create(
|
||||||
QPDF* qpdf,
|
QPDF* qpdf,
|
||||||
int objid,
|
QPDFObjGen const& og,
|
||||||
int generation,
|
|
||||||
QPDFObjectHandle stream_dict,
|
QPDFObjectHandle stream_dict,
|
||||||
qpdf_offset_t offset,
|
qpdf_offset_t offset,
|
||||||
size_t length)
|
size_t length)
|
||||||
{
|
{
|
||||||
return do_create(
|
return do_create(new QPDF_Stream(qpdf, og, stream_dict, offset, length));
|
||||||
new QPDF_Stream(qpdf, objid, generation, stream_dict, offset, length));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<QPDFObject>
|
std::shared_ptr<QPDFObject>
|
||||||
@ -181,23 +174,21 @@ QPDF_Stream::releaseResolved()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
QPDF_Stream::setObjGen(int objid, int generation)
|
QPDF_Stream::setObjGen(QPDFObjGen const& og)
|
||||||
{
|
{
|
||||||
if (!((this->objid == 0) && (this->generation == 0))) {
|
if (this->og.isIndirect()) {
|
||||||
throw std::logic_error(
|
throw std::logic_error(
|
||||||
"attempt to set object ID and generation of a stream"
|
"attempt to set object ID and generation of a stream"
|
||||||
" that already has them");
|
" that already has them");
|
||||||
}
|
}
|
||||||
this->objid = objid;
|
this->og = og;
|
||||||
this->generation = generation;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string
|
std::string
|
||||||
QPDF_Stream::unparse()
|
QPDF_Stream::unparse()
|
||||||
{
|
{
|
||||||
// Unparse stream objects as indirect references
|
// Unparse stream objects as indirect references
|
||||||
return QUtil::int_to_string(this->objid) + " " +
|
return og.unparse(' ') + " R";
|
||||||
QUtil::int_to_string(this->generation) + " R";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JSON
|
JSON
|
||||||
@ -619,17 +610,12 @@ QPDF_Stream::pipeStreamData(
|
|||||||
Pl_Count count("stream provider count", pipeline);
|
Pl_Count count("stream provider count", pipeline);
|
||||||
if (this->stream_provider->supportsRetry()) {
|
if (this->stream_provider->supportsRetry()) {
|
||||||
if (!this->stream_provider->provideStreamData(
|
if (!this->stream_provider->provideStreamData(
|
||||||
this->objid,
|
og, &count, suppress_warnings, will_retry)) {
|
||||||
this->generation,
|
|
||||||
&count,
|
|
||||||
suppress_warnings,
|
|
||||||
will_retry)) {
|
|
||||||
filter = false;
|
filter = false;
|
||||||
success = false;
|
success = false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this->stream_provider->provideStreamData(
|
this->stream_provider->provideStreamData(og, &count);
|
||||||
this->objid, this->generation, &count);
|
|
||||||
}
|
}
|
||||||
qpdf_offset_t actual_length = count.getCount();
|
qpdf_offset_t actual_length = count.getCount();
|
||||||
qpdf_offset_t desired_length = 0;
|
qpdf_offset_t desired_length = 0;
|
||||||
@ -642,10 +628,8 @@ QPDF_Stream::pipeStreamData(
|
|||||||
// This would be caused by programmer error on the
|
// This would be caused by programmer error on the
|
||||||
// part of a library user, not by invalid input data.
|
// part of a library user, not by invalid input data.
|
||||||
throw std::runtime_error(
|
throw std::runtime_error(
|
||||||
"stream data provider for " +
|
"stream data provider for " + og.unparse(' ') +
|
||||||
QUtil::int_to_string(this->objid) + " " +
|
" provided " + QUtil::int_to_string(actual_length) +
|
||||||
QUtil::int_to_string(this->generation) + " provided " +
|
|
||||||
QUtil::int_to_string(actual_length) +
|
|
||||||
" bytes instead of expected " +
|
" bytes instead of expected " +
|
||||||
QUtil::int_to_string(desired_length) + " bytes");
|
QUtil::int_to_string(desired_length) + " bytes");
|
||||||
}
|
}
|
||||||
@ -661,8 +645,7 @@ QPDF_Stream::pipeStreamData(
|
|||||||
QTC::TC("qpdf", "QPDF_Stream pipe original stream data");
|
QTC::TC("qpdf", "QPDF_Stream pipe original stream data");
|
||||||
if (!QPDF::Pipe::pipeStreamData(
|
if (!QPDF::Pipe::pipeStreamData(
|
||||||
this->qpdf,
|
this->qpdf,
|
||||||
this->objid,
|
og,
|
||||||
this->generation,
|
|
||||||
this->offset,
|
this->offset,
|
||||||
this->length,
|
this->length,
|
||||||
this->stream_dict,
|
this->stream_dict,
|
||||||
|
@ -1075,8 +1075,7 @@ QPDF::initializeEncryption()
|
|||||||
std::string
|
std::string
|
||||||
QPDF::getKeyForObject(
|
QPDF::getKeyForObject(
|
||||||
std::shared_ptr<EncryptionParameters> encp,
|
std::shared_ptr<EncryptionParameters> encp,
|
||||||
int objid,
|
QPDFObjGen const& og,
|
||||||
int generation,
|
|
||||||
bool use_aes)
|
bool use_aes)
|
||||||
{
|
{
|
||||||
if (!encp->encrypted) {
|
if (!encp->encrypted) {
|
||||||
@ -1084,26 +1083,24 @@ QPDF::getKeyForObject(
|
|||||||
"request for encryption key in non-encrypted PDF");
|
"request for encryption key in non-encrypted PDF");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!((objid == encp->cached_key_objid) &&
|
if (og != encp->cached_key_og) {
|
||||||
(generation == encp->cached_key_generation))) {
|
|
||||||
encp->cached_object_encryption_key = compute_data_key(
|
encp->cached_object_encryption_key = compute_data_key(
|
||||||
encp->encryption_key,
|
encp->encryption_key,
|
||||||
objid,
|
og.getObj(),
|
||||||
generation,
|
og.getGen(),
|
||||||
use_aes,
|
use_aes,
|
||||||
encp->encryption_V,
|
encp->encryption_V,
|
||||||
encp->encryption_R);
|
encp->encryption_R);
|
||||||
encp->cached_key_objid = objid;
|
encp->cached_key_og = og;
|
||||||
encp->cached_key_generation = generation;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return encp->cached_object_encryption_key;
|
return encp->cached_object_encryption_key;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
QPDF::decryptString(std::string& str, int objid, int generation)
|
QPDF::decryptString(std::string& str, QPDFObjGen const& og)
|
||||||
{
|
{
|
||||||
if (objid == 0) {
|
if (!og.isIndirect()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
bool use_aes = false;
|
bool use_aes = false;
|
||||||
@ -1139,8 +1136,7 @@ QPDF::decryptString(std::string& str, int objid, int generation)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string key =
|
std::string key = getKeyForObject(this->m->encp, og, use_aes);
|
||||||
getKeyForObject(this->m->encp, objid, generation, use_aes);
|
|
||||||
try {
|
try {
|
||||||
if (use_aes) {
|
if (use_aes) {
|
||||||
QTC::TC("qpdf", "QPDF_encryption aes decode string");
|
QTC::TC("qpdf", "QPDF_encryption aes decode string");
|
||||||
@ -1175,9 +1171,8 @@ QPDF::decryptString(std::string& str, int objid, int generation)
|
|||||||
this->m->file->getName(),
|
this->m->file->getName(),
|
||||||
this->m->last_object_description,
|
this->m->last_object_description,
|
||||||
this->m->file->getLastOffset(),
|
this->m->file->getLastOffset(),
|
||||||
"error decrypting string for object " +
|
"error decrypting string for object " + og.unparse() + ": " +
|
||||||
QUtil::int_to_string(objid) + " " +
|
e.what());
|
||||||
QUtil::int_to_string(generation) + ": " + e.what());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1187,8 +1182,7 @@ QPDF::decryptStream(
|
|||||||
std::shared_ptr<InputSource> file,
|
std::shared_ptr<InputSource> file,
|
||||||
QPDF& qpdf_for_warning,
|
QPDF& qpdf_for_warning,
|
||||||
Pipeline*& pipeline,
|
Pipeline*& pipeline,
|
||||||
int objid,
|
QPDFObjGen const& og,
|
||||||
int generation,
|
|
||||||
QPDFObjectHandle& stream_dict,
|
QPDFObjectHandle& stream_dict,
|
||||||
std::vector<std::shared_ptr<Pipeline>>& heap)
|
std::vector<std::shared_ptr<Pipeline>>& heap)
|
||||||
{
|
{
|
||||||
@ -1283,7 +1277,7 @@ QPDF::decryptStream(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::string key = getKeyForObject(encp, objid, generation, use_aes);
|
std::string key = getKeyForObject(encp, og, use_aes);
|
||||||
std::shared_ptr<Pipeline> new_pipeline;
|
std::shared_ptr<Pipeline> new_pipeline;
|
||||||
if (use_aes) {
|
if (use_aes) {
|
||||||
QTC::TC("qpdf", "QPDF_encryption aes decode stream");
|
QTC::TC("qpdf", "QPDF_encryption aes decode stream");
|
||||||
|
@ -371,9 +371,10 @@ QPDF::JSONReactor::containerEnd(JSON const& value)
|
|||||||
QPDFObjectHandle
|
QPDFObjectHandle
|
||||||
QPDF::JSONReactor::reserveObject(int obj, int gen)
|
QPDF::JSONReactor::reserveObject(int obj, int gen)
|
||||||
{
|
{
|
||||||
auto oh = pdf.reserveObjectIfNotExists(obj, gen);
|
QPDFObjGen og(obj, gen);
|
||||||
|
auto oh = pdf.reserveObjectIfNotExists(og);
|
||||||
if (oh.isReserved()) {
|
if (oh.isReserved()) {
|
||||||
this->reserved.insert(QPDFObjGen(obj, gen));
|
this->reserved.insert(og);
|
||||||
}
|
}
|
||||||
return oh;
|
return oh;
|
||||||
}
|
}
|
||||||
@ -495,8 +496,7 @@ QPDF::JSONReactor::dictionaryItem(std::string const& key, JSON const& value)
|
|||||||
QTC::TC("qpdf", "QPDF_json updating existing stream");
|
QTC::TC("qpdf", "QPDF_json updating existing stream");
|
||||||
} else {
|
} else {
|
||||||
this->this_stream_needs_data = true;
|
this->this_stream_needs_data = true;
|
||||||
replacement =
|
replacement = pdf.reserveStream(tos.getObjGen());
|
||||||
pdf.reserveStream(tos.getObjectID(), tos.getGeneration());
|
|
||||||
replaceObject(tos, replacement, value);
|
replaceObject(tos, replacement, value);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -137,8 +137,8 @@ QPDF::isLinearized()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
QPDFObjectHandle candidate =
|
QPDFObjectHandle candidate = QPDFObjectHandle::Factory::newIndirect(
|
||||||
QPDFObjectHandle::Factory::newIndirect(this, lindict_obj, 0);
|
this, QPDFObjGen(lindict_obj, 0));
|
||||||
if (!candidate.isDictionary()) {
|
if (!candidate.isDictionary()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -325,11 +325,10 @@ QPDF::readLinearizationData()
|
|||||||
QPDFObjectHandle
|
QPDFObjectHandle
|
||||||
QPDF::readHintStream(Pipeline& pl, qpdf_offset_t offset, size_t length)
|
QPDF::readHintStream(Pipeline& pl, qpdf_offset_t offset, size_t length)
|
||||||
{
|
{
|
||||||
int obj;
|
QPDFObjGen og;
|
||||||
int gen;
|
|
||||||
QPDFObjectHandle H = readObjectAtOffset(
|
QPDFObjectHandle H = readObjectAtOffset(
|
||||||
false, offset, "linearization hint stream", 0, 0, obj, gen);
|
false, offset, "linearization hint stream", QPDFObjGen(0, 0), og);
|
||||||
ObjCache& oc = this->m->obj_cache[QPDFObjGen(obj, gen)];
|
ObjCache& oc = this->m->obj_cache[og];
|
||||||
qpdf_offset_t min_end_offset = oc.end_before_space;
|
qpdf_offset_t min_end_offset = oc.end_before_space;
|
||||||
qpdf_offset_t max_end_offset = oc.end_after_space;
|
qpdf_offset_t max_end_offset = oc.end_after_space;
|
||||||
if (!H.isStream()) {
|
if (!H.isStream()) {
|
||||||
@ -707,7 +706,7 @@ QPDF::getUncompressedObject(
|
|||||||
return obj;
|
return obj;
|
||||||
} else {
|
} else {
|
||||||
int repl = (*(object_stream_data.find(obj.getObjectID()))).second;
|
int repl = (*(object_stream_data.find(obj.getObjectID()))).second;
|
||||||
return objGenToIndirect(QPDFObjGen(repl, 0));
|
return getObjectByObjGen(QPDFObjGen(repl, 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1144,12 +1143,6 @@ QPDF::dumpHGeneric(HGeneric& t)
|
|||||||
<< "group_length: " << t.group_length << "\n";
|
<< "group_length: " << t.group_length << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
QPDFObjectHandle
|
|
||||||
QPDF::objGenToIndirect(QPDFObjGen const& og)
|
|
||||||
{
|
|
||||||
return getObjectByID(og.getObj(), og.getGen());
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
QPDF::calculateLinearizationData(std::map<int, int> const& object_stream_data)
|
QPDF::calculateLinearizationData(std::map<int, int> const& object_stream_data)
|
||||||
{
|
{
|
||||||
@ -1388,9 +1381,9 @@ QPDF::calculateLinearizationData(std::map<int, int> const& object_stream_data)
|
|||||||
stopOnError("found other than one root while"
|
stopOnError("found other than one root while"
|
||||||
" calculating linearization data");
|
" calculating linearization data");
|
||||||
}
|
}
|
||||||
this->m->part4.push_back(objGenToIndirect(*(lc_root.begin())));
|
this->m->part4.push_back(getObjectByObjGen(*(lc_root.begin())));
|
||||||
for (auto const& og: lc_open_document) {
|
for (auto const& og: lc_open_document) {
|
||||||
this->m->part4.push_back(objGenToIndirect(og));
|
this->m->part4.push_back(getObjectByObjGen(og));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Part 6: first page objects. Note: implementation note 124
|
// Part 6: first page objects. Note: implementation note 124
|
||||||
@ -1419,11 +1412,11 @@ QPDF::calculateLinearizationData(std::map<int, int> const& object_stream_data)
|
|||||||
// hint tables.
|
// hint tables.
|
||||||
|
|
||||||
for (auto const& og: lc_first_page_private) {
|
for (auto const& og: lc_first_page_private) {
|
||||||
this->m->part6.push_back(objGenToIndirect(og));
|
this->m->part6.push_back(getObjectByObjGen(og));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto const& og: lc_first_page_shared) {
|
for (auto const& og: lc_first_page_shared) {
|
||||||
this->m->part6.push_back(objGenToIndirect(og));
|
this->m->part6.push_back(getObjectByObjGen(og));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Place the outline dictionary if it goes in the first page section.
|
// Place the outline dictionary if it goes in the first page section.
|
||||||
@ -1469,7 +1462,7 @@ QPDF::calculateLinearizationData(std::map<int, int> const& object_stream_data)
|
|||||||
for (auto const& og: this->m->obj_user_to_objects[ou]) {
|
for (auto const& og: this->m->obj_user_to_objects[ou]) {
|
||||||
if (lc_other_page_private.count(og)) {
|
if (lc_other_page_private.count(og)) {
|
||||||
lc_other_page_private.erase(og);
|
lc_other_page_private.erase(og);
|
||||||
this->m->part7.push_back(objGenToIndirect(og));
|
this->m->part7.push_back(getObjectByObjGen(og));
|
||||||
++this->m->c_page_offset_data.entries.at(i).nobjects;
|
++this->m->c_page_offset_data.entries.at(i).nobjects;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1486,7 +1479,7 @@ QPDF::calculateLinearizationData(std::map<int, int> const& object_stream_data)
|
|||||||
|
|
||||||
// Order is unimportant.
|
// Order is unimportant.
|
||||||
for (auto const& og: lc_other_page_shared) {
|
for (auto const& og: lc_other_page_shared) {
|
||||||
this->m->part8.push_back(objGenToIndirect(og));
|
this->m->part8.push_back(getObjectByObjGen(og));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Part 9: other objects
|
// Part 9: other objects
|
||||||
@ -1508,7 +1501,7 @@ QPDF::calculateLinearizationData(std::map<int, int> const& object_stream_data)
|
|||||||
for (auto const& og: pages_ogs) {
|
for (auto const& og: pages_ogs) {
|
||||||
if (lc_other.count(og)) {
|
if (lc_other.count(og)) {
|
||||||
lc_other.erase(og);
|
lc_other.erase(og);
|
||||||
this->m->part9.push_back(objGenToIndirect(og));
|
this->m->part9.push_back(getObjectByObjGen(og));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1538,7 +1531,7 @@ QPDF::calculateLinearizationData(std::map<int, int> const& object_stream_data)
|
|||||||
for (auto const& og: ogs) {
|
for (auto const& og: ogs) {
|
||||||
if (lc_thumbnail_private.count(og)) {
|
if (lc_thumbnail_private.count(og)) {
|
||||||
lc_thumbnail_private.erase(og);
|
lc_thumbnail_private.erase(og);
|
||||||
this->m->part9.push_back(objGenToIndirect(og));
|
this->m->part9.push_back(getObjectByObjGen(og));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1551,7 +1544,7 @@ QPDF::calculateLinearizationData(std::map<int, int> const& object_stream_data)
|
|||||||
|
|
||||||
// Place shared thumbnail objects
|
// Place shared thumbnail objects
|
||||||
for (auto const& og: lc_thumbnail_shared) {
|
for (auto const& og: lc_thumbnail_shared) {
|
||||||
this->m->part9.push_back(objGenToIndirect(og));
|
this->m->part9.push_back(getObjectByObjGen(og));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Place outlines unless in first page
|
// Place outlines unless in first page
|
||||||
@ -1561,7 +1554,7 @@ QPDF::calculateLinearizationData(std::map<int, int> const& object_stream_data)
|
|||||||
|
|
||||||
// Place all remaining objects
|
// Place all remaining objects
|
||||||
for (auto const& og: lc_other) {
|
for (auto const& og: lc_other) {
|
||||||
this->m->part9.push_back(objGenToIndirect(og));
|
this->m->part9.push_back(getObjectByObjGen(og));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure we got everything exactly once.
|
// Make sure we got everything exactly once.
|
||||||
@ -1663,7 +1656,7 @@ QPDF::pushOutlinesToPart(
|
|||||||
lc_outlines.erase(outlines_og);
|
lc_outlines.erase(outlines_og);
|
||||||
part.push_back(outlines);
|
part.push_back(outlines);
|
||||||
for (auto const& og: lc_outlines) {
|
for (auto const& og: lc_outlines) {
|
||||||
part.push_back(objGenToIndirect(og));
|
part.push_back(getObjectByObjGen(og));
|
||||||
++this->m->c_outline_data.nobjects;
|
++this->m->c_outline_data.nobjects;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -252,9 +252,7 @@ QPDF::pushInheritedAttributesToPageInternal(
|
|||||||
if ((warn_skipped_keys) && (cur_pages.hasKey("/Parent"))) {
|
if ((warn_skipped_keys) && (cur_pages.hasKey("/Parent"))) {
|
||||||
QTC::TC("qpdf", "QPDF unknown key not inherited");
|
QTC::TC("qpdf", "QPDF unknown key not inherited");
|
||||||
setLastObjectDescription(
|
setLastObjectDescription(
|
||||||
"Pages object",
|
"Pages object", cur_pages.getObjGen());
|
||||||
cur_pages.getObjectID(),
|
|
||||||
cur_pages.getGeneration());
|
|
||||||
warn(
|
warn(
|
||||||
qpdf_e_pages,
|
qpdf_e_pages,
|
||||||
this->m->last_object_description,
|
this->m->last_object_description,
|
||||||
|
@ -207,8 +207,7 @@ QPDF::insertPageobjToPage(
|
|||||||
// that causes this to happen.
|
// that causes this to happen.
|
||||||
setLastObjectDescription(
|
setLastObjectDescription(
|
||||||
"page " + QUtil::int_to_string(pos) + " (numbered from zero)",
|
"page " + QUtil::int_to_string(pos) + " (numbered from zero)",
|
||||||
og.getObj(),
|
og);
|
||||||
og.getGen());
|
|
||||||
throw QPDFExc(
|
throw QPDFExc(
|
||||||
qpdf_e_pages,
|
qpdf_e_pages,
|
||||||
this->m->file->getName(),
|
this->m->file->getName(),
|
||||||
@ -334,7 +333,7 @@ QPDF::findPage(QPDFObjGen const& og)
|
|||||||
auto it = this->m->pageobj_to_pages_pos.find(og);
|
auto it = this->m->pageobj_to_pages_pos.find(og);
|
||||||
if (it == this->m->pageobj_to_pages_pos.end()) {
|
if (it == this->m->pageobj_to_pages_pos.end()) {
|
||||||
QTC::TC("qpdf", "QPDF_pages findPage not found");
|
QTC::TC("qpdf", "QPDF_pages findPage not found");
|
||||||
setLastObjectDescription("page object", og.getObj(), og.getGen());
|
setLastObjectDescription("page object", og);
|
||||||
throw QPDFExc(
|
throw QPDFExc(
|
||||||
qpdf_e_pages,
|
qpdf_e_pages,
|
||||||
this->m->file->getName(),
|
this->m->file->getName(),
|
||||||
|
@ -19,8 +19,7 @@ class QPDF_Stream: public QPDFObject
|
|||||||
virtual ~QPDF_Stream() = default;
|
virtual ~QPDF_Stream() = default;
|
||||||
static std::shared_ptr<QPDFObject> create(
|
static std::shared_ptr<QPDFObject> create(
|
||||||
QPDF*,
|
QPDF*,
|
||||||
int objid,
|
QPDFObjGen const& og,
|
||||||
int generation,
|
|
||||||
QPDFObjectHandle stream_dict,
|
QPDFObjectHandle stream_dict,
|
||||||
qpdf_offset_t offset,
|
qpdf_offset_t offset,
|
||||||
size_t length);
|
size_t length);
|
||||||
@ -78,7 +77,7 @@ class QPDF_Stream: public QPDFObject
|
|||||||
// Replace object ID and generation. This may only be called if
|
// Replace object ID and generation. This may only be called if
|
||||||
// object ID and generation are 0. It is used by QPDFObjectHandle
|
// object ID and generation are 0. It is used by QPDFObjectHandle
|
||||||
// when adding streams to files.
|
// when adding streams to files.
|
||||||
void setObjGen(int objid, int generation);
|
void setObjGen(QPDFObjGen const& og);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void releaseResolved();
|
virtual void releaseResolved();
|
||||||
@ -86,8 +85,7 @@ class QPDF_Stream: public QPDFObject
|
|||||||
private:
|
private:
|
||||||
QPDF_Stream(
|
QPDF_Stream(
|
||||||
QPDF*,
|
QPDF*,
|
||||||
int objid,
|
QPDFObjGen const& og,
|
||||||
int generation,
|
|
||||||
QPDFObjectHandle stream_dict,
|
QPDFObjectHandle stream_dict,
|
||||||
qpdf_offset_t offset,
|
qpdf_offset_t offset,
|
||||||
size_t length);
|
size_t length);
|
||||||
@ -111,8 +109,7 @@ class QPDF_Stream: public QPDFObject
|
|||||||
void setDictDescription();
|
void setDictDescription();
|
||||||
|
|
||||||
QPDF* qpdf;
|
QPDF* qpdf;
|
||||||
int objid;
|
QPDFObjGen og;
|
||||||
int generation;
|
|
||||||
bool filter_on_write;
|
bool filter_on_write;
|
||||||
QPDFObjectHandle stream_dict;
|
QPDFObjectHandle stream_dict;
|
||||||
qpdf_offset_t offset;
|
qpdf_offset_t offset;
|
||||||
|
@ -56,6 +56,8 @@ class Provider: public QPDFObjectHandle::StreamDataProvider
|
|||||||
virtual void
|
virtual void
|
||||||
provideStreamData(int objid, int generation, Pipeline* p)
|
provideStreamData(int objid, int generation, Pipeline* p)
|
||||||
{
|
{
|
||||||
|
// Don't change signature to use QPDFObjGen const& to detect
|
||||||
|
// problems forwarding to legacy implementations.
|
||||||
p->write(b->getBuffer(), b->getSize());
|
p->write(b->getBuffer(), b->getSize());
|
||||||
if (this->bad_length) {
|
if (this->bad_length) {
|
||||||
unsigned char ch = ' ';
|
unsigned char ch = ' ';
|
||||||
|
Loading…
x
Reference in New Issue
Block a user