|
Packit Service |
21b5d1 |
#include "bigtiffimage.hpp"
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
#include "safe_op.hpp"
|
|
Packit Service |
21b5d1 |
#include "exif.hpp"
|
|
Packit Service |
21b5d1 |
#include "error.hpp"
|
|
Packit Service |
21b5d1 |
#include "image_int.hpp"
|
|
Packit Service |
21b5d1 |
#include "enforce.hpp"
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
#include <cassert>
|
|
Packit Service |
21b5d1 |
#include <limits>
|
|
Packit Service |
21b5d1 |
#include <iostream>
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
namespace Exiv2
|
|
Packit Service |
21b5d1 |
{
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
namespace
|
|
Packit Service |
21b5d1 |
{
|
|
Packit Service |
21b5d1 |
struct Header
|
|
Packit Service |
21b5d1 |
{
|
|
Packit Service |
21b5d1 |
enum Format
|
|
Packit Service |
21b5d1 |
{
|
|
Packit Service |
21b5d1 |
StandardTiff,
|
|
Packit Service |
21b5d1 |
BigTiff,
|
|
Packit Service |
21b5d1 |
};
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
Header(): byteOrder_(invalidByteOrder), version_(-1), data_size_(0), dir_offset_(0) {}
|
|
Packit Service |
21b5d1 |
Header(const ByteOrder& order, int v, int size, uint64_t offset):
|
|
Packit Service |
21b5d1 |
byteOrder_(order),
|
|
Packit Service |
21b5d1 |
version_(v),
|
|
Packit Service |
21b5d1 |
data_size_(size),
|
|
Packit Service |
21b5d1 |
dir_offset_(offset)
|
|
Packit Service |
21b5d1 |
{
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
bool isValid() const
|
|
Packit Service |
21b5d1 |
{
|
|
Packit Service |
21b5d1 |
return version_ != -1;
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
ByteOrder byteOrder() const
|
|
Packit Service |
21b5d1 |
{
|
|
Packit Service |
21b5d1 |
assert(isValid());
|
|
Packit Service |
21b5d1 |
return byteOrder_;
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
int version() const
|
|
Packit Service |
21b5d1 |
{
|
|
Packit Service |
21b5d1 |
assert(isValid());
|
|
Packit Service |
21b5d1 |
return version_;
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
Format format() const
|
|
Packit Service |
21b5d1 |
{
|
|
Packit Service |
21b5d1 |
assert(isValid());
|
|
Packit Service |
21b5d1 |
return version_ == 0x2A? StandardTiff: BigTiff;
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
int dataSize() const
|
|
Packit Service |
21b5d1 |
{
|
|
Packit Service |
21b5d1 |
assert(isValid());
|
|
Packit Service |
21b5d1 |
return data_size_;
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
uint64_t dirOffset() const
|
|
Packit Service |
21b5d1 |
{
|
|
Packit Service |
21b5d1 |
assert(isValid());
|
|
Packit Service |
21b5d1 |
return dir_offset_;
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
private:
|
|
Packit Service |
21b5d1 |
ByteOrder byteOrder_;
|
|
Packit Service |
21b5d1 |
int version_; // 42 or 43 - regular tiff or big tiff
|
|
Packit Service |
21b5d1 |
int data_size_; // 4 or 8
|
|
Packit Service |
21b5d1 |
uint64_t dir_offset_;
|
|
Packit Service |
21b5d1 |
};
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
Header readHeader(BasicIo& io)
|
|
Packit Service |
21b5d1 |
{
|
|
Packit Service |
21b5d1 |
byte header[2] = {0, 0};
|
|
Packit Service |
21b5d1 |
io.read(header, 2);
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
ByteOrder byteOrder = invalidByteOrder;
|
|
Packit Service |
21b5d1 |
if (header[0] == 'I' && header[1] == 'I')
|
|
Packit Service |
21b5d1 |
byteOrder = littleEndian;
|
|
Packit Service |
21b5d1 |
else if (header[0] == 'M' && header[1] == 'M')
|
|
Packit Service |
21b5d1 |
byteOrder = bigEndian;
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
if (byteOrder == invalidByteOrder)
|
|
Packit Service |
21b5d1 |
return Header();
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
byte version[2] = {0, 0};
|
|
Packit Service |
21b5d1 |
io.read(version, 2);
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
const uint16_t magic = getUShort(version, byteOrder);
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
if (magic != 0x2A && magic != 0x2B)
|
|
Packit Service |
21b5d1 |
return Header();
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
Header result;
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
if (magic == 0x2A)
|
|
Packit Service |
21b5d1 |
{
|
|
Packit Service |
21b5d1 |
byte buffer[4];
|
|
Packit Service |
21b5d1 |
int read = io.read(buffer, 4);
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
if (read < 4)
|
|
Packit Service |
21b5d1 |
throw Exiv2::Error(kerCorruptedMetadata);
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
const uint32_t offset = getULong(buffer, byteOrder);
|
|
Packit Service |
21b5d1 |
result = Header(byteOrder, magic, 4, offset);
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
else
|
|
Packit Service |
21b5d1 |
{
|
|
Packit Service |
21b5d1 |
byte buffer[8] = {0, 0, 0, 0, 0, 0, 0, 0};
|
|
Packit Service |
21b5d1 |
int read = io.read(buffer, 2);
|
|
Packit Service |
21b5d1 |
if (read < 2)
|
|
Packit Service |
21b5d1 |
throw Exiv2::Error(kerCorruptedMetadata);
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
const int size = getUShort(buffer, byteOrder);
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
if (size == 8)
|
|
Packit Service |
21b5d1 |
{
|
|
Packit Service |
21b5d1 |
read = io.read(buffer, 2); // null
|
|
Packit Service |
21b5d1 |
if (read < 2)
|
|
Packit Service |
21b5d1 |
throw Exiv2::Error(kerCorruptedMetadata);
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
read = io.read(buffer, 8);
|
|
Packit Service |
21b5d1 |
if (read < 8)
|
|
Packit Service |
21b5d1 |
throw Exiv2::Error(kerCorruptedMetadata);
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
const uint64_t offset = getULongLong(buffer, byteOrder);
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
if (offset >= io.size())
|
|
Packit Service |
21b5d1 |
throw Exiv2::Error(kerCorruptedMetadata);
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
result = Header(byteOrder, magic, size, offset);
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
else
|
|
Packit Service |
21b5d1 |
throw Exiv2::Error(kerCorruptedMetadata);
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
return result;
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
class BigTiffImage: public Image
|
|
Packit Service |
21b5d1 |
{
|
|
Packit Service |
21b5d1 |
public:
|
|
Packit Service |
21b5d1 |
BigTiffImage(BasicIo::AutoPtr io):
|
|
Packit Service |
21b5d1 |
Image(ImageType::bigtiff, mdExif, io),
|
|
Packit Service |
21b5d1 |
header_(),
|
|
Packit Service |
21b5d1 |
dataSize_(0),
|
|
Packit Service |
21b5d1 |
doSwap_(false)
|
|
Packit Service |
21b5d1 |
{
|
|
Packit Service |
21b5d1 |
header_ = readHeader(Image::io());
|
|
Packit Service |
21b5d1 |
assert(header_.isValid());
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
doSwap_ = (isLittleEndianPlatform() && header_.byteOrder() == bigEndian)
|
|
Packit Service |
21b5d1 |
|| (isBigEndianPlatform() && header_.byteOrder() == littleEndian);
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
dataSize_ = header_.format() == Header::StandardTiff? 4 : 8;
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
virtual ~BigTiffImage() {}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
// overrides
|
|
Packit Service |
21b5d1 |
void readMetadata()
|
|
Packit Service |
21b5d1 |
{
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
void writeMetadata()
|
|
Packit Service |
21b5d1 |
{
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
std::string mimeType() const
|
|
Packit Service |
21b5d1 |
{
|
|
Packit Service |
21b5d1 |
return std::string();
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
void printStructure(std::ostream& os, PrintStructureOption option, int depth)
|
|
Packit Service |
21b5d1 |
{
|
|
Packit Service |
21b5d1 |
printIFD(os, option, header_.dirOffset(), depth - 1);
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
private:
|
|
Packit Service |
21b5d1 |
Header header_;
|
|
Packit Service |
21b5d1 |
int dataSize_;
|
|
Packit Service |
21b5d1 |
bool doSwap_;
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
void printIFD(std::ostream& out, PrintStructureOption option, uint64_t dir_offset, int depth)
|
|
Packit Service |
21b5d1 |
{
|
|
Packit Service |
21b5d1 |
BasicIo& io = Image::io();
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
depth++;
|
|
Packit Service |
21b5d1 |
bool bFirst = true;
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
// buffer
|
|
Packit Service |
21b5d1 |
bool bPrint = true;
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
do
|
|
Packit Service |
21b5d1 |
{
|
|
Packit Service |
21b5d1 |
// Read top of directory
|
|
Packit Service |
21b5d1 |
io.seek(dir_offset, BasicIo::beg);
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
const uint64_t entries = readData(header_.format() == Header::StandardTiff? 2: 8);
|
|
Packit Service |
21b5d1 |
const bool tooBig = entries > 500;
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
if ( bFirst && bPrint )
|
|
Packit Service |
21b5d1 |
{
|
|
Packit Service |
21b5d1 |
out << Internal::indent(depth) << "STRUCTURE OF BIGTIFF FILE " << io.path() << std::endl;
|
|
Packit Service |
21b5d1 |
if (tooBig)
|
|
Packit Service |
21b5d1 |
out << Internal::indent(depth) << "entries = " << entries << std::endl;
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
if (tooBig)
|
|
Packit Service |
21b5d1 |
break;
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
// Read the dictionary
|
|
Packit Service |
21b5d1 |
for ( uint64_t i = 0; i < entries; i ++ )
|
|
Packit Service |
21b5d1 |
{
|
|
Packit Service |
21b5d1 |
if ( bFirst && bPrint )
|
|
Packit Service |
21b5d1 |
out << Internal::indent(depth)
|
|
Packit Service |
21b5d1 |
<< " address | tag | "
|
|
Packit Service |
21b5d1 |
<< " type | count | offset | value\n";
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
bFirst = false;
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
const uint16_t tag = (uint16_t) readData(2);
|
|
Packit Service |
21b5d1 |
const uint16_t type = (uint16_t) readData(2);
|
|
Packit Service |
21b5d1 |
const uint64_t count = readData(dataSize_);
|
|
Packit Service |
21b5d1 |
const DataBuf data = io.read(dataSize_); // Read data as raw value. what should be done about it will be decided depending on type
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
std::string sp = "" ; // output spacer
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
//prepare to print the value
|
|
Packit Service |
21b5d1 |
// TODO: figure out what's going on with kount
|
|
Packit Service |
21b5d1 |
const uint64_t kount = isStringType(type)? (count > 32 ? 32 : count) // restrict long arrays
|
|
Packit Service |
21b5d1 |
: count > 5 ? 5
|
|
Packit Service |
21b5d1 |
: count
|
|
Packit Service |
21b5d1 |
;
|
|
Packit Service |
21b5d1 |
const uint32_t pad = isStringType(type) ? 1 : 0;
|
|
Packit Service |
21b5d1 |
const uint32_t size = isStringType(type) ? 1
|
|
Packit Service |
21b5d1 |
: is2ByteType(type) ? 2
|
|
Packit Service |
21b5d1 |
: is4ByteType(type) ? 4
|
|
Packit Service |
21b5d1 |
: is8ByteType(type) ? 8
|
|
Packit Service |
21b5d1 |
: 1;
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
// #55 and #56 memory allocation crash test/data/POC8
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
// size * count > std::numeric_limits<uint64_t>::max()
|
|
Packit Service |
21b5d1 |
// =>
|
|
Packit Service |
21b5d1 |
// size > std::numeric_limits<uint64_t>::max() / count
|
|
Packit Service |
21b5d1 |
// (don't perform that check when count == 0 => will cause a division by zero exception)
|
|
Packit Service |
21b5d1 |
if (count != 0) {
|
|
Packit Service |
21b5d1 |
if (size > std::numeric_limits<uint64_t>::max() / count) {
|
|
Packit Service |
21b5d1 |
throw Error(kerInvalidMalloc); // we got number bigger than 2^64
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
// more than we can handle
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
if (size * count > std::numeric_limits<uint64_t>::max() - pad)
|
|
Packit Service |
21b5d1 |
throw Error(kerInvalidMalloc); // again more than 2^64
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
const uint64_t allocate = size*count + pad;
|
|
Packit Service |
21b5d1 |
if ( allocate > io.size() ) {
|
|
Packit Service |
21b5d1 |
throw Error(kerInvalidMalloc);
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
DataBuf buf(static_cast<long>(allocate));
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
const uint64_t offset = header_.format() == Header::StandardTiff?
|
|
Packit Service |
21b5d1 |
byteSwap4(data, 0, doSwap_):
|
|
Packit Service |
21b5d1 |
byteSwap8(data, 0, doSwap_);
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
// big data? Use 'data' as pointer to real data
|
|
Packit Service |
21b5d1 |
const bool usePointer = (size_t) count*size > (size_t) dataSize_;
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
if ( usePointer ) // read into buffer
|
|
Packit Service |
21b5d1 |
{
|
|
Packit Service |
21b5d1 |
size_t restore = io.tell(); // save
|
|
Packit Service |
21b5d1 |
io.seek(offset, BasicIo::beg); // position
|
|
Packit Service |
21b5d1 |
io.read(buf.pData_, (long) count * size); // read
|
|
Packit Service |
21b5d1 |
io.seek(restore, BasicIo::beg); // restore
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
else // use 'data' as data :)
|
|
Packit Service |
21b5d1 |
std::memcpy(buf.pData_, data.pData_, (size_t) count * size); // copy data
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
if ( bPrint )
|
|
Packit Service |
21b5d1 |
{
|
|
Packit Service |
21b5d1 |
const uint64_t entrySize = header_.format() == Header::StandardTiff? 12: 20;
|
|
Packit Service |
21b5d1 |
const uint64_t address = dir_offset + 2 + i * entrySize;
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
out << Internal::indent(depth)
|
|
Packit Service |
21b5d1 |
<< Internal::stringFormat("%8u | %#06x %-25s |%10s |%9u |",
|
|
Packit Service |
21b5d1 |
static_cast<size_t>(address), tag, tagName(tag).c_str(), typeName(type), count)
|
|
Packit Service |
21b5d1 |
<<(usePointer ? Internal::stringFormat("%10u | ",(size_t)offset)
|
|
Packit Service |
21b5d1 |
: Internal::stringFormat("%10s | ",""))
|
|
Packit Service |
21b5d1 |
;
|
|
Packit Service |
21b5d1 |
if ( isShortType(type) )
|
|
Packit Service |
21b5d1 |
{
|
|
Packit Service |
21b5d1 |
for ( size_t k = 0 ; k < kount ; k++ )
|
|
Packit Service |
21b5d1 |
{
|
|
Packit Service |
21b5d1 |
out << sp << byteSwap2(buf, k*size, doSwap_);
|
|
Packit Service |
21b5d1 |
sp = " ";
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
else if ( isLongType(type) )
|
|
Packit Service |
21b5d1 |
{
|
|
Packit Service |
21b5d1 |
for ( size_t k = 0 ; k < kount ; k++ )
|
|
Packit Service |
21b5d1 |
{
|
|
Packit Service |
21b5d1 |
out << sp << byteSwap4(buf, k*size, doSwap_);
|
|
Packit Service |
21b5d1 |
sp = " ";
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
else if ( isLongLongType(type) )
|
|
Packit Service |
21b5d1 |
{
|
|
Packit Service |
21b5d1 |
for ( size_t k = 0 ; k < kount ; k++ )
|
|
Packit Service |
21b5d1 |
{
|
|
Packit Service |
21b5d1 |
out << sp << byteSwap8(buf, k*size, doSwap_);
|
|
Packit Service |
21b5d1 |
sp = " ";
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
else if ( isRationalType(type) )
|
|
Packit Service |
21b5d1 |
{
|
|
Packit Service |
21b5d1 |
for ( size_t k = 0 ; k < kount ; k++ )
|
|
Packit Service |
21b5d1 |
{
|
|
Packit Service |
21b5d1 |
uint32_t a = byteSwap4(buf, k*size+0, doSwap_);
|
|
Packit Service |
21b5d1 |
uint32_t b = byteSwap4(buf, k*size+4, doSwap_);
|
|
Packit Service |
21b5d1 |
out << sp << a << "/" << b;
|
|
Packit Service |
21b5d1 |
sp = " ";
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
else if ( isStringType(type) )
|
|
Packit Service |
21b5d1 |
out << sp << Internal::binaryToString(makeSlice(buf, 0, static_cast<size_t>(kount)));
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
sp = kount == count ? "" : " ...";
|
|
Packit Service |
21b5d1 |
out << sp << std::endl;
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
if ( option == kpsRecursive &&
|
|
Packit Service |
21b5d1 |
(tag == 0x8769 /* ExifTag */ || tag == 0x014a/*SubIFDs*/ || type == tiffIfd || type == tiffIfd8) )
|
|
Packit Service |
21b5d1 |
{
|
|
Packit Service |
21b5d1 |
for ( size_t k = 0 ; k < count ; k++ )
|
|
Packit Service |
21b5d1 |
{
|
|
Packit Service |
21b5d1 |
const size_t restore = io.tell();
|
|
Packit Service |
21b5d1 |
const uint64_t ifdOffset = type == tiffIfd8?
|
|
Packit Service |
21b5d1 |
byteSwap8(buf, k*size, doSwap_):
|
|
Packit Service |
21b5d1 |
byteSwap4(buf, k*size, doSwap_);
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
printIFD(out, option, ifdOffset, depth);
|
|
Packit Service |
21b5d1 |
io.seek(restore, BasicIo::beg);
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
else if ( option == kpsRecursive && tag == 0x83bb /* IPTCNAA */ )
|
|
Packit Service |
21b5d1 |
{
|
|
Packit Service |
21b5d1 |
if (Safe::add(count, offset) > io.size()) {
|
|
Packit Service |
21b5d1 |
throw Error(kerCorruptedMetadata);
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
const size_t restore = io.tell();
|
|
Packit Service |
21b5d1 |
io.seek(offset, BasicIo::beg); // position
|
|
Packit Service |
21b5d1 |
std::vector<byte> bytes((size_t)count) ; // allocate memory
|
|
Packit Service |
21b5d1 |
// TODO: once we have C++11 use bytes.data()
|
|
Packit Service |
21b5d1 |
const long read_bytes = io.read(&bytes[0], static_cast<long>(count));
|
|
Packit Service |
21b5d1 |
io.seek(restore, BasicIo::beg);
|
|
Packit Service |
21b5d1 |
// TODO: once we have C++11 use bytes.data()
|
|
Packit Service |
21b5d1 |
IptcData::printStructure(out, makeSliceUntil(&bytes[0], read_bytes), depth);
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
else if ( option == kpsRecursive && tag == 0x927c /* MakerNote */ && count > 10)
|
|
Packit Service |
21b5d1 |
{
|
|
Packit Service |
21b5d1 |
size_t restore = io.tell(); // save
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
long jump= 10 ;
|
|
Packit Service |
21b5d1 |
byte bytes[20] ;
|
|
Packit Service |
21b5d1 |
const char* chars = (const char*) &bytes[0] ;
|
|
Packit Service |
21b5d1 |
io.seek(dir_offset, BasicIo::beg); // position
|
|
Packit Service |
21b5d1 |
io.read(bytes,jump ) ; // read
|
|
Packit Service |
21b5d1 |
bytes[jump]=0 ;
|
|
Packit Service |
21b5d1 |
if ( ::strcmp("Nikon",chars) == 0 )
|
|
Packit Service |
21b5d1 |
{
|
|
Packit Service |
21b5d1 |
// tag is an embedded tiff
|
|
Packit Service |
21b5d1 |
std::vector<byte> nikon_bytes((size_t)(count - jump));
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
io.read(&nikon_bytes.at(0), (long)nikon_bytes.size());
|
|
Packit Service |
21b5d1 |
MemIo memIo(&nikon_bytes.at(0), (long)count - jump); // create a file
|
|
Packit Service |
21b5d1 |
std::cerr << "Nikon makernote" << std::endl;
|
|
Packit Service |
21b5d1 |
// printTiffStructure(memIo,out,option,depth);
|
|
Packit Service |
21b5d1 |
// TODO: fix it
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
else
|
|
Packit Service |
21b5d1 |
{
|
|
Packit Service |
21b5d1 |
// tag is an IFD
|
|
Packit Service |
21b5d1 |
io.seek(0, BasicIo::beg); // position
|
|
Packit Service |
21b5d1 |
std::cerr << "makernote" << std::endl;
|
|
Packit Service |
21b5d1 |
printIFD(out,option,offset,depth);
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
io.seek(restore,BasicIo::beg); // restore
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
const uint64_t nextDirOffset = readData(dataSize_);
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
dir_offset = tooBig ? 0 : nextDirOffset;
|
|
Packit Service |
21b5d1 |
out.flush();
|
|
Packit Service |
21b5d1 |
} while (dir_offset != 0);
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
if ( bPrint )
|
|
Packit Service |
21b5d1 |
out << Internal::indent(depth) << "END " << io.path() << std::endl;
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
depth--;
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
uint64_t readData(int size) const
|
|
Packit Service |
21b5d1 |
{
|
|
Packit Service |
21b5d1 |
const DataBuf data = Image::io().read(size);
|
|
Packit Service |
21b5d1 |
enforce(data.size_ != 0, kerCorruptedMetadata);
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
uint64_t result = 0;
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
if (data.size_ == 1)
|
|
Packit Service |
21b5d1 |
{}
|
|
Packit Service |
21b5d1 |
else if (data.size_ == 2)
|
|
Packit Service |
21b5d1 |
result = byteSwap2(data, 0, doSwap_);
|
|
Packit Service |
21b5d1 |
else if (data.size_ == 4)
|
|
Packit Service |
21b5d1 |
result = byteSwap4(data, 0, doSwap_);
|
|
Packit Service |
21b5d1 |
else if (data.size_ == 8)
|
|
Packit Service |
21b5d1 |
result = byteSwap8(data, 0, doSwap_);
|
|
Packit Service |
21b5d1 |
else
|
|
Packit Service |
21b5d1 |
throw Exiv2::Error(kerCorruptedMetadata);
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
return result;
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
};
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
Image::AutoPtr newBigTiffInstance(BasicIo::AutoPtr io, bool)
|
|
Packit Service |
21b5d1 |
{
|
|
Packit Service |
21b5d1 |
return Image::AutoPtr(new BigTiffImage(io));
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
bool isBigTiffType(BasicIo& io, bool advance)
|
|
Packit Service |
21b5d1 |
{
|
|
Packit Service |
21b5d1 |
const long pos = io.tell();
|
|
Packit Service |
21b5d1 |
const Header header = readHeader(io);
|
|
Packit Service |
21b5d1 |
const bool valid = header.isValid();
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
if (valid == false || advance == false)
|
|
Packit Service |
21b5d1 |
io.seek(pos, BasicIo::beg);
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
return valid;
|
|
Packit Service |
21b5d1 |
}
|
|
Packit Service |
21b5d1 |
|
|
Packit Service |
21b5d1 |
}
|