From d8bbf8a21ddcbbc1a6161194139d517e87032f4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9gory=20Soutad=C3=A9?= Date: Sat, 18 Dec 2021 17:27:35 +0100 Subject: [PATCH] Manage stream data reading (without filter interpretation) --- include/uPDFTypes.h | 26 +++++++++++++++++++++----- src/uPDFTypes.cpp | 45 ++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 65 insertions(+), 6 deletions(-) diff --git a/include/uPDFTypes.h b/include/uPDFTypes.h index b9adf9f..8e94ee3 100644 --- a/include/uPDFTypes.h +++ b/include/uPDFTypes.h @@ -266,15 +266,31 @@ namespace uPDFParser class Stream : public DataType { public: - Stream(int startOffset, int endOffset): - DataType(DataType::TYPE::STREAM), startOffset(startOffset), - endOffset(endOffset) + Stream(Dictionary& dict, int startOffset, int endOffset, unsigned char* data=0, unsigned int dataLength=0, + bool freeData=false, int fd=0): + DataType(DataType::TYPE::STREAM), dict(dict), fd(fd), + startOffset(startOffset), endOffset(endOffset), + _data(data), _dataLength(dataLength), freeData(false) {} - virtual DataType* clone() {return new Stream(startOffset, endOffset);} - virtual std::string str() { return "stream\nendstream\n";} + + ~Stream() { + if (_data && freeData) delete[] _data; + } + + virtual DataType* clone() {return new Stream(dict, startOffset, endOffset, + _data, _dataLength, false, fd);} + virtual std::string str(); + unsigned char* data(); + unsigned int dataLength() {return _dataLength;} + void setData(unsigned char* data, unsigned int dataLength, bool freeData=false); private: + Dictionary& dict; + int fd; int startOffset, endOffset; + unsigned char* _data; + unsigned int _dataLength; + bool freeData; }; class Null : public DataType diff --git a/src/uPDFTypes.cpp b/src/uPDFTypes.cpp index 087e308..a4b6835 100644 --- a/src/uPDFTypes.cpp +++ b/src/uPDFTypes.cpp @@ -17,6 +17,8 @@ along with uPDFParser. If not, see . */ +#include + #include "uPDFTypes.h" #include "uPDFParser_common.h" @@ -71,7 +73,7 @@ namespace uPDFParser res += (*it)->str(); } - return res + std::string("]"); + return res + " ]"; } void Dictionary::addData(const std::string& key, DataType* value) @@ -93,4 +95,45 @@ namespace uPDFParser return res + std::string(">>\n"); } + + std::string Stream::str() + { + std::string res = "stream\n"; + const char* streamData = (const char*)data(); // Force reading if not in memory + res += std::string(streamData, _dataLength); + res += "endstream\n"; + + return res; + } + + unsigned char* Stream::data() + { + if (!_data) + { + if (!fd) + EXCEPTION(INVALID_STREAM, "Accessing data, but no file descriptor supplied"); + + _dataLength = endOffset - startOffset; + _data = new unsigned char[_dataLength]; + freeData = true; + + lseek(fd, startOffset, SEEK_SET); + int ret = ::read(fd, _data, _dataLength); + + if ((unsigned int)ret != _dataLength) + EXCEPTION(INVALID_STREAM, "Not enough data to read (" << ret << ")"); + } + + return _data; + } + + void Stream::setData(unsigned char* data, unsigned int dataLength, bool freeData) + { + if (_data && freeData) + delete[] _data; + + this->_data = data; + this->_dataLength = dataLength; + this->freeData = freeData; + } }