2
1
mirror of https://github.com/qpdf/qpdf.git synced 2024-05-29 00:10:54 +00:00

add QPDF::processMemoryFile and API additions to support it

git-svn-id: svn+q:///qpdf/trunk@1034 71b93d88-0707-0410-a8cf-f5a4172ac649
This commit is contained in:
Jay Berkenbilt 2010-10-01 10:20:38 +00:00
parent 359999a59c
commit 9f444ffef3
7 changed files with 121 additions and 57 deletions

View File

@ -1,3 +1,8 @@
2010-10-01 Jay Berkenbilt <ejb@ql.org>
* include/qpdf/QPDF.hh: Add processMemoryFile method for
processing a PDF file from a memory buffer instead of a file.
2010-09-24 Jay Berkenbilt <ejb@ql.org> 2010-09-24 Jay Berkenbilt <ejb@ql.org>
* libqpdf/QPDF.cc: change private "file" method to be a * libqpdf/QPDF.cc: change private "file" method to be a

38
TODO
View File

@ -1,41 +1,3 @@
2.2.1
=====
Add interface for working with in-memory PDF files. Here's some code
to work with.
Pl_Buffer b("b");
FILE* f = QUtil::fopen_wrapper(std::string("open ") + filename,
fopen(filename, "rb"));
unsigned char buf[1024];
size_t bytes_read = 0;
while (true)
{
size_t len = fread(buf, 1, sizeof(buf), f);
if (len == 0)
{
if (ferror(f))
{
throw QPDFExc(qpdf_e_system,
filename, "",
0,
"read");
}
else
{
b.finish();
break;
}
}
else
{
b.write(buf, len);
bytes_read += len;
}
}
fclose(f);
this->file = new BufferInputSource(filename, b.getBuffer());
General General
======= =======

View File

@ -15,8 +15,17 @@ class Buffer
public: public:
QPDF_DLL QPDF_DLL
Buffer(); Buffer();
// Create a Buffer object whose memory is owned by the class and
// will be freed when the Buffer object is destroyed.
QPDF_DLL QPDF_DLL
Buffer(unsigned long size); Buffer(unsigned long size);
// Create a Buffer object whose memory is owned by the caller and
// will not be freed when the Buffer is destroyed.
QPDF_DLL
Buffer(unsigned char* buf, unsigned long size);
QPDF_DLL QPDF_DLL
Buffer(Buffer const&); Buffer(Buffer const&);
QPDF_DLL QPDF_DLL
@ -31,10 +40,11 @@ class Buffer
unsigned char* getBuffer(); unsigned char* getBuffer();
private: private:
void init(unsigned long size); void init(unsigned long size, unsigned char* buf, bool own_memory);
void copy(Buffer const&); void copy(Buffer const&);
void destroy(); void destroy();
bool own_memory;
unsigned long size; unsigned long size;
unsigned char* buf; unsigned char* buf;
}; };

View File

@ -50,6 +50,15 @@ class QPDF
QPDF_DLL QPDF_DLL
void processFile(char const* filename, char const* password = 0); void processFile(char const* filename, char const* password = 0);
// Parse a PDF file loaded into a memory buffer. This works
// exactly like processFile except that the PDF file is in memory
// instead of on disk. The description appears in any warning or
// error message in place of the file name.
QPDF_DLL
void processMemoryFile(char const* description,
char const* buf, size_t length,
char const* password = 0);
// Parameter settings // Parameter settings
// If true, ignore any cross-reference streams in a hybrid file // If true, ignore any cross-reference streams in a hybrid file
@ -362,7 +371,8 @@ class QPDF
class BufferInputSource: public InputSource class BufferInputSource: public InputSource
{ {
public: public:
BufferInputSource(std::string const& description, Buffer* buf); BufferInputSource(std::string const& description, Buffer* buf,
bool own_memory = false);
virtual ~BufferInputSource(); virtual ~BufferInputSource();
virtual std::string const& getName() const; virtual std::string const& getName() const;
virtual off_t tell(); virtual off_t tell();
@ -372,6 +382,7 @@ class QPDF
virtual void unreadCh(char ch); virtual void unreadCh(char ch);
private: private:
bool own_memory;
std::string description; std::string description;
Buffer* buf; Buffer* buf;
off_t cur_offset; off_t cur_offset;
@ -410,7 +421,7 @@ class QPDF
off_t end_after_space; off_t end_after_space;
}; };
void parse(); void parse(char const* password);
void warn(QPDFExc const& e); void warn(QPDFExc const& e);
void setTrailer(QPDFObjectHandle obj); void setTrailer(QPDFObjectHandle obj);
void read_xref(off_t offset); void read_xref(off_t offset);

View File

@ -4,17 +4,22 @@
Buffer::Buffer() Buffer::Buffer()
{ {
init(0); init(0, 0, true);
} }
Buffer::Buffer(unsigned long size) Buffer::Buffer(unsigned long size)
{ {
init(size); init(size, 0, true);
}
Buffer::Buffer(unsigned char* buf, unsigned long size)
{
init(size, buf, false);
} }
Buffer::Buffer(Buffer const& rhs) Buffer::Buffer(Buffer const& rhs)
{ {
init(0); init(0, 0, true);
copy(rhs); copy(rhs);
} }
@ -31,10 +36,18 @@ Buffer::~Buffer()
} }
void void
Buffer::init(unsigned long size) Buffer::init(unsigned long size, unsigned char* buf, bool own_memory)
{ {
this->own_memory = own_memory;
this->size = size; this->size = size;
this->buf = (size ? new unsigned char[size] : 0); if (own_memory)
{
this->buf = (size ? new unsigned char[size] : 0);
}
else
{
this->buf = buf;
}
} }
void void
@ -43,7 +56,7 @@ Buffer::copy(Buffer const& rhs)
if (this != &rhs) if (this != &rhs)
{ {
this->destroy(); this->destroy();
this->init(rhs.size); this->init(rhs.size, 0, true);
if (this->size) if (this->size)
{ {
memcpy(this->buf, rhs.buf, this->size); memcpy(this->buf, rhs.buf, this->size);
@ -54,7 +67,10 @@ Buffer::copy(Buffer const& rhs)
void void
Buffer::destroy() Buffer::destroy()
{ {
delete [] this->buf; if (this->own_memory)
{
delete [] this->buf;
}
this->size = 0; this->size = 0;
this->buf = 0; this->buf = 0;
} }

View File

@ -159,7 +159,8 @@ QPDF::FileInputSource::unreadCh(char ch)
} }
QPDF::BufferInputSource::BufferInputSource(std::string const& description, QPDF::BufferInputSource::BufferInputSource(std::string const& description,
Buffer* buf) : Buffer* buf, bool own_memory) :
own_memory(own_memory),
description(description), description(description),
buf(buf), buf(buf),
cur_offset(0) cur_offset(0)
@ -168,6 +169,10 @@ QPDF::BufferInputSource::BufferInputSource(std::string const& description,
QPDF::BufferInputSource::~BufferInputSource() QPDF::BufferInputSource::~BufferInputSource()
{ {
if (own_memory)
{
delete this->buf;
}
} }
std::string const& std::string const&
@ -192,7 +197,7 @@ QPDF::BufferInputSource::seek(off_t offset, int whence)
break; break;
case SEEK_END: case SEEK_END:
this->cur_offset = this->buf->getSize() - offset; this->cur_offset = this->buf->getSize() + offset;
break; break;
case SEEK_CUR: case SEEK_CUR:
@ -306,11 +311,19 @@ QPDF::processFile(char const* filename, char const* password)
FileInputSource* fi = new FileInputSource(); FileInputSource* fi = new FileInputSource();
this->file = fi; this->file = fi;
fi->setFilename(filename); fi->setFilename(filename);
if (password) parse(password);
{ }
this->provided_password = password;
} void
parse(); QPDF::processMemoryFile(char const* description,
char const* buf, size_t length,
char const* password)
{
this->file =
new BufferInputSource(description,
new Buffer((unsigned char*)buf, length),
true);
parse(password);
} }
void void
@ -340,11 +353,16 @@ QPDF::getWarnings()
} }
void void
QPDF::parse() QPDF::parse(char const* password)
{ {
static PCRE header_re("^%PDF-(1.\\d+)\\b"); static PCRE header_re("^%PDF-(1.\\d+)\\b");
static PCRE eof_re("(?s:startxref\\s+(\\d+)\\s+%%EOF\\b)"); static PCRE eof_re("(?s:startxref\\s+(\\d+)\\s+%%EOF\\b)");
if (password)
{
this->provided_password = password;
}
std::string line = this->file->readLine(); std::string line = this->file->readLine();
PCRE::Match m1 = header_re.match(line.c_str()); PCRE::Match m1 = header_re.match(line.c_str());
if (m1) if (m1)

View File

@ -58,11 +58,53 @@ class Provider: public QPDFObjectHandle::StreamDataProvider
void runtest(int n, char const* filename) void runtest(int n, char const* filename)
{ {
QPDF pdf; QPDF pdf;
PointerHolder<char> file_buf;
if (n == 0) if (n == 0)
{ {
pdf.setAttemptRecovery(false); pdf.setAttemptRecovery(false);
} }
pdf.processFile(filename); if (n % 2 == 0)
{
pdf.processFile(filename);
}
else
{
// Exercise processMemoryFile
FILE* f = QUtil::fopen_wrapper(std::string("open ") + filename,
fopen(filename, "rb"));
fseek(f, 0, SEEK_END);
size_t size = (size_t) ftell(f);
fseek(f, 0, SEEK_SET);
file_buf = new char[size];
char* buf_p = file_buf.getPointer();
size_t bytes_read = 0;
size_t len = 0;
while ((len = fread(buf_p + bytes_read, 1, size - bytes_read, f)) > 0)
{
bytes_read += len;
}
if (bytes_read != size)
{
if (ferror(f))
{
throw std::runtime_error(
std::string("failure reading file ") + filename +
" into memory: read " +
QUtil::int_to_string(bytes_read) + "; wanted " +
QUtil::int_to_string(size));
}
else
{
throw std::logic_error(
std::string("premature eof reading file ") + filename +
" into memory: read " +
QUtil::int_to_string(bytes_read) + "; wanted " +
QUtil::int_to_string(size));
}
}
fclose(f);
pdf.processMemoryFile(filename, buf_p, size);
}
if ((n == 0) || (n == 1)) if ((n == 0) || (n == 1))
{ {