Clang-format in pngchunk_int.cpp

main
Luis Díaz Más 3 years ago
parent ddf5645c5d
commit 240a72468e

@ -22,28 +22,28 @@
#include "config.h" #include "config.h"
#ifdef EXV_HAVE_LIBZ #ifdef EXV_HAVE_LIBZ
#include "pngchunk_int.hpp"
#include "tiffimage.hpp"
#include "jpgimage.hpp"
#include "exif.hpp"
#include "iptc.hpp"
#include "image.hpp"
#include "error.hpp"
#include "enforce.hpp" #include "enforce.hpp"
#include "error.hpp"
#include "exif.hpp"
#include "helper_functions.hpp" #include "helper_functions.hpp"
#include "image.hpp"
#include "iptc.hpp"
#include "jpgimage.hpp"
#include "pngchunk_int.hpp"
#include "safe_op.hpp" #include "safe_op.hpp"
#include "tiffimage.hpp"
// + standard includes #include <zlib.h> // To uncompress or compress text chunk
#include <sstream>
#include <iomanip> // standard includes
#include <string> #include <algorithm>
#include <cstring>
#include <iostream>
#include <cassert> #include <cassert>
#include <cstdio> #include <cstdio>
#include <algorithm> #include <cstring>
#include <iomanip>
#include <zlib.h> // To uncompress or compress text chunk #include <iostream>
#include <sstream>
#include <string>
/* /*
@ -54,18 +54,18 @@ iTXt chunk : http://www.vias.org/pngguide/chapter11_05.html
PNG tags : http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/PNG.html#TextualData PNG tags : http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/PNG.html#TextualData
*/ */
namespace { namespace
constexpr int nullSeparators = 2; {
constexpr int nullSeparators = 2;
} }
// ***************************************************************************** // *****************************************************************************
// class member definitions // class member definitions
namespace Exiv2 { namespace Exiv2
namespace Internal { {
namespace Internal
void PngChunk::decodeIHDRChunk(const DataBuf& data, {
int* outWidth, void PngChunk::decodeIHDRChunk(const DataBuf& data, int* outWidth, int* outHeight)
int* outHeight)
{ {
assert(data.size() >= 8); assert(data.size() >= 8);
@ -73,35 +73,29 @@ namespace Exiv2 {
*outWidth = data.read_uint32(0, bigEndian); *outWidth = data.read_uint32(0, bigEndian);
*outHeight = data.read_uint32(4, bigEndian); *outHeight = data.read_uint32(4, bigEndian);
} }
void PngChunk::decodeTXTChunk(Image* pImage, void PngChunk::decodeTXTChunk(Image* pImage, const DataBuf& data, TxtChunkType type)
const DataBuf& data,
TxtChunkType type)
{ {
DataBuf key = keyTXTChunk(data); DataBuf key = keyTXTChunk(data);
DataBuf arr = parseTXTChunk(data, key.size(), type); DataBuf arr = parseTXTChunk(data, key.size(), type);
#ifdef EXIV2_DEBUG_MESSAGES #ifdef EXIV2_DEBUG_MESSAGES
std::cout << "Exiv2::PngChunk::decodeTXTChunk: TXT chunk data: " std::cout << "Exiv2::PngChunk::decodeTXTChunk: TXT chunk data: " << std::string(arr.c_str(), arr.size())
<< std::string(arr.c_str(), arr.size()) << std::endl; << std::endl;
#endif #endif
parseChunkContent(pImage, key.c_data(), key.size(), arr); parseChunkContent(pImage, key.c_data(), key.size(), arr);
} }
DataBuf PngChunk::decodeTXTChunk(const DataBuf& data, DataBuf PngChunk::decodeTXTChunk(const DataBuf& data, TxtChunkType type)
TxtChunkType type)
{ {
DataBuf key = keyTXTChunk(data); DataBuf key = keyTXTChunk(data);
#ifdef EXIV2_DEBUG_MESSAGES #ifdef EXIV2_DEBUG_MESSAGES
std::cout << "Exiv2::PngChunk::decodeTXTChunk: TXT chunk key: " std::cout << "Exiv2::PngChunk::decodeTXTChunk: TXT chunk key: " << std::string(key.c_str(), key.size())
<< std::string(key.c_str(), key.size()) << std::endl; << std::endl;
#endif #endif
return parseTXTChunk(data, key.size(), type); return parseTXTChunk(data, key.size(), type);
} }
DataBuf PngChunk::keyTXTChunk(const DataBuf& data, bool stripHeader) DataBuf PngChunk::keyTXTChunk(const DataBuf& data, bool stripHeader)
@ -113,7 +107,7 @@ namespace Exiv2 {
// Search for null char until the end of the DataBuf // Search for null char until the end of the DataBuf
const byte* dataPtr = data.c_data(); const byte* dataPtr = data.c_data();
int keysize=offset; int keysize = offset;
while (dataPtr[keysize] != 0 && keysize < data.size()) { while (dataPtr[keysize] != 0 && keysize < data.size()) {
keysize++; keysize++;
} }
@ -121,25 +115,21 @@ namespace Exiv2 {
if (keysize == data.size()) if (keysize == data.size())
throw Error(kerFailedToReadImageData); throw Error(kerFailedToReadImageData);
return DataBuf(dataPtr+offset, keysize-offset); return DataBuf(dataPtr + offset, keysize - offset);
} }
DataBuf PngChunk::parseTXTChunk(const DataBuf& data, DataBuf PngChunk::parseTXTChunk(const DataBuf& data, int keysize, TxtChunkType type)
int keysize,
TxtChunkType type)
{ {
DataBuf arr; DataBuf arr;
if(type == zTXt_Chunk) if (type == zTXt_Chunk) {
{
enforce(data.size() >= Safe::add(keysize, nullSeparators), Exiv2::kerCorruptedMetadata); enforce(data.size() >= Safe::add(keysize, nullSeparators), Exiv2::kerCorruptedMetadata);
// Extract a deflate compressed Latin-1 text chunk // Extract a deflate compressed Latin-1 text chunk
// we get the compression method after the key // we get the compression method after the key
const byte* compressionMethod = data.c_data(keysize + 1); const byte* compressionMethod = data.c_data(keysize + 1);
if ( *compressionMethod != 0x00 ) if (*compressionMethod != 0x00) {
{
// then it isn't zlib compressed and we are sunk // then it isn't zlib compressed and we are sunk
#ifdef EXIV2_DEBUG_MESSAGES #ifdef EXIV2_DEBUG_MESSAGES
std::cerr << "Exiv2::PngChunk::parseTXTChunk: Non-standard zTXt compression method.\n"; std::cerr << "Exiv2::PngChunk::parseTXTChunk: Non-standard zTXt compression method.\n";
@ -153,9 +143,7 @@ namespace Exiv2 {
enforce(compressedTextSize < data.size(), kerCorruptedMetadata); enforce(compressedTextSize < data.size(), kerCorruptedMetadata);
zlibUncompress(compressedText, compressedTextSize, arr); zlibUncompress(compressedText, compressedTextSize, arr);
} } else if (type == tEXt_Chunk) {
else if(type == tEXt_Chunk)
{
enforce(data.size() >= Safe::add(keysize, 1), Exiv2::kerCorruptedMetadata); enforce(data.size() >= Safe::add(keysize, 1), Exiv2::kerCorruptedMetadata);
// Extract a non-compressed Latin-1 text chunk // Extract a non-compressed Latin-1 text chunk
@ -164,11 +152,9 @@ namespace Exiv2 {
long textsize = data.size() - keysize - 1; long textsize = data.size() - keysize - 1;
arr = DataBuf(text, textsize); arr = DataBuf(text, textsize);
} } else if (type == iTXt_Chunk) {
else if(type == iTXt_Chunk)
{
enforce(data.size() >= Safe::add(keysize, 3), Exiv2::kerCorruptedMetadata); enforce(data.size() >= Safe::add(keysize, 3), Exiv2::kerCorruptedMetadata);
const size_t nullCount = std::count(data.c_data(keysize+3), data.c_data(data.size()), '\0'); const size_t nullCount = std::count(data.c_data(keysize + 3), data.c_data(data.size()), '\0');
enforce(nullCount >= nullSeparators, Exiv2::kerCorruptedMetadata); enforce(nullCount >= nullSeparators, Exiv2::kerCorruptedMetadata);
// Extract a deflate compressed or uncompressed UTF-8 text chunk // Extract a deflate compressed or uncompressed UTF-8 text chunk
@ -183,8 +169,8 @@ namespace Exiv2 {
// language description string after the compression technique spec // language description string after the compression technique spec
const size_t languageTextMaxSize = data.size() - keysize - 3; const size_t languageTextMaxSize = data.size() - keysize - 3;
std::string languageText = string_from_unterminated( std::string languageText =
data.c_str(Safe::add(keysize, 3)), languageTextMaxSize); string_from_unterminated(data.c_str(Safe::add(keysize, 3)), languageTextMaxSize);
const size_t languageTextSize = languageText.size(); const size_t languageTextSize = languageText.size();
enforce(static_cast<unsigned long>(data.size()) >= enforce(static_cast<unsigned long>(data.size()) >=
@ -192,8 +178,7 @@ namespace Exiv2 {
Exiv2::kerCorruptedMetadata); Exiv2::kerCorruptedMetadata);
// translated keyword string after the language description // translated keyword string after the language description
std::string translatedKeyText = string_from_unterminated( std::string translatedKeyText = string_from_unterminated(
data.c_str(keysize + 3 + languageTextSize + 1), data.c_str(keysize + 3 + languageTextSize + 1), data.size() - (keysize + 3 + languageTextSize + 1));
data.size() - (keysize + 3 + languageTextSize + 1));
const auto translatedKeyTextSize = static_cast<unsigned int>(translatedKeyText.size()); const auto translatedKeyTextSize = static_cast<unsigned int>(translatedKeyText.size());
if ((compressionFlag == 0x00) || (compressionFlag == 0x01 && compressionMethod == 0x00)) { if ((compressionFlag == 0x00) || (compressionFlag == 0x01 && compressionMethod == 0x00)) {
@ -202,7 +187,8 @@ namespace Exiv2 {
Exiv2::kerCorruptedMetadata); Exiv2::kerCorruptedMetadata);
const byte* text = data.c_data(keysize + 3 + languageTextSize + 1 + translatedKeyTextSize + 1); const byte* text = data.c_data(keysize + 3 + languageTextSize + 1 + translatedKeyTextSize + 1);
const long textsize = static_cast<long>(data.size() - (keysize + 3 + languageTextSize + 1 + translatedKeyTextSize + 1)); const long textsize = static_cast<long>(
data.size() - (keysize + 3 + languageTextSize + 1 + translatedKeyTextSize + 1));
if (compressionFlag == 0x00) { if (compressionFlag == 0x00) {
// then it's an uncompressed iTXt chunk // then it's an uncompressed iTXt chunk
@ -228,9 +214,7 @@ namespace Exiv2 {
#endif #endif
throw Error(kerFailedToReadImageData); throw Error(kerFailedToReadImageData);
} }
} } else {
else
{
#ifdef DEBUG #ifdef DEBUG
std::cerr << "Exiv2::PngChunk::parseTXTChunk: We found a field, not expected though\n"; std::cerr << "Exiv2::PngChunk::parseTXTChunk: We found a field, not expected though\n";
#endif #endif
@ -244,24 +228,20 @@ namespace Exiv2 {
{ {
// We look if an ImageMagick EXIF raw profile exist. // We look if an ImageMagick EXIF raw profile exist.
if ( keySize >= 21 if (keySize >= 21 &&
&& ( memcmp("Raw profile type exif", key, 21) == 0 (memcmp("Raw profile type exif", key, 21) == 0 || memcmp("Raw profile type APP1", key, 21) == 0) &&
|| memcmp("Raw profile type APP1", key, 21) == 0) pImage->exifData().empty()) {
&& pImage->exifData().empty()) DataBuf exifData = readRawProfile(arr, false);
{
DataBuf exifData = readRawProfile(arr,false);
long length = exifData.size(); long length = exifData.size();
if (length > 0) if (length > 0) {
{
// Find the position of Exif header in bytes array. // Find the position of Exif header in bytes array.
const byte exifHeader[] = { 0x45, 0x78, 0x69, 0x66, 0x00, 0x00 }; const byte exifHeader[] = {0x45, 0x78, 0x69, 0x66, 0x00, 0x00};
long pos = -1; long pos = -1;
for (long i = 0; i < length - static_cast<long>(sizeof(exifHeader)); i++) { for (long i = 0; i < length - static_cast<long>(sizeof(exifHeader)); i++) {
if (exifData.cmpBytes(i, exifHeader, sizeof(exifHeader)) == 0) if (exifData.cmpBytes(i, exifHeader, sizeof(exifHeader)) == 0) {
{
pos = i; pos = i;
break; break;
} }
@ -269,21 +249,16 @@ namespace Exiv2 {
// If found it, store only these data at from this place. // If found it, store only these data at from this place.
if (pos !=-1) if (pos != -1) {
{
#ifdef EXIV2_DEBUG_MESSAGES #ifdef EXIV2_DEBUG_MESSAGES
std::cout << "Exiv2::PngChunk::parseChunkContent: Exif header found at position " << pos << "\n"; std::cout << "Exiv2::PngChunk::parseChunkContent: Exif header found at position " << pos
<< "\n";
#endif #endif
pos = pos + sizeof(exifHeader); pos = pos + sizeof(exifHeader);
ByteOrder bo = TiffParser::decode(pImage->exifData(), ByteOrder bo = TiffParser::decode(pImage->exifData(), pImage->iptcData(), pImage->xmpData(),
pImage->iptcData(), exifData.c_data(pos), length - pos);
pImage->xmpData(),
exifData.c_data(pos),
length - pos);
pImage->setByteOrder(bo); pImage->setByteOrder(bo);
} } else {
else
{
#ifndef SUPPRESS_WARNINGS #ifndef SUPPRESS_WARNINGS
EXV_WARNING << "Failed to decode Exif metadata.\n"; EXV_WARNING << "Failed to decode Exif metadata.\n";
#endif #endif
@ -294,10 +269,8 @@ namespace Exiv2 {
// We look if an ImageMagick IPTC raw profile exist. // We look if an ImageMagick IPTC raw profile exist.
if ( keySize >= 21 if (keySize >= 21 && memcmp("Raw profile type iptc", key, 21) == 0 && pImage->iptcData().empty()) {
&& memcmp("Raw profile type iptc", key, 21) == 0 DataBuf psData = readRawProfile(arr, false);
&& pImage->iptcData().empty()) {
DataBuf psData = readRawProfile(arr,false);
if (psData.size() > 0) { if (psData.size() > 0) {
Blob iptcBlob; Blob iptcBlob;
const byte* record = nullptr; const byte* record = nullptr;
@ -306,12 +279,8 @@ namespace Exiv2 {
const byte* pEnd = psData.c_data(psData.size()); const byte* pEnd = psData.c_data(psData.size());
const byte* pCur = psData.c_data(); const byte* pCur = psData.c_data();
while ( pCur < pEnd while (pCur < pEnd && 0 == Photoshop::locateIptcIrb(pCur, static_cast<long>(pEnd - pCur), &record,
&& 0 == Photoshop::locateIptcIrb(pCur, &sizeHdr, &sizeIptc)) {
static_cast<long>(pEnd - pCur),
&record,
&sizeHdr,
&sizeIptc)) {
if (sizeIptc) { if (sizeIptc) {
#ifdef EXIV2_DEBUG_MESSAGES #ifdef EXIV2_DEBUG_MESSAGES
std::cerr << "Found IPTC IRB, size = " << sizeIptc << "\n"; std::cerr << "Found IPTC IRB, size = " << sizeIptc << "\n";
@ -329,10 +298,7 @@ namespace Exiv2 {
pImage->clearIptcData(); pImage->clearIptcData();
} }
// If there is no IRB, try to decode the complete chunk data // If there is no IRB, try to decode the complete chunk data
if ( iptcBlob.empty() if (iptcBlob.empty() && IptcParser::decode(pImage->iptcData(), psData.c_data(), psData.size())) {
&& IptcParser::decode(pImage->iptcData(),
psData.c_data(),
psData.size())) {
#ifndef SUPPRESS_WARNINGS #ifndef SUPPRESS_WARNINGS
EXV_WARNING << "Failed to decode IPTC metadata.\n"; EXV_WARNING << "Failed to decode IPTC metadata.\n";
#endif #endif
@ -343,28 +309,21 @@ namespace Exiv2 {
// We look if an ImageMagick XMP raw profile exist. // We look if an ImageMagick XMP raw profile exist.
if ( keySize >= 20 if (keySize >= 20 && memcmp("Raw profile type xmp", key, 20) == 0 && pImage->xmpData().empty()) {
&& memcmp("Raw profile type xmp", key, 20) == 0 DataBuf xmpBuf = readRawProfile(arr, false);
&& pImage->xmpData().empty())
{
DataBuf xmpBuf = readRawProfile(arr,false);
long length = xmpBuf.size(); long length = xmpBuf.size();
if (length > 0) if (length > 0) {
{
std::string& xmpPacket = pImage->xmpPacket(); std::string& xmpPacket = pImage->xmpPacket();
xmpPacket.assign(xmpBuf.c_str(), length); xmpPacket.assign(xmpBuf.c_str(), length);
std::string::size_type idx = xmpPacket.find_first_of('<'); std::string::size_type idx = xmpPacket.find_first_of('<');
if (idx != std::string::npos && idx > 0) if (idx != std::string::npos && idx > 0) {
{
#ifndef SUPPRESS_WARNINGS #ifndef SUPPRESS_WARNINGS
EXV_WARNING << "Removing " << idx EXV_WARNING << "Removing " << idx << " characters from the beginning of the XMP packet\n";
<< " characters from the beginning of the XMP packet\n";
#endif #endif
xmpPacket = xmpPacket.substr(idx); xmpPacket = xmpPacket.substr(idx);
} }
if (XmpParser::decode(pImage->xmpData(), xmpPacket)) if (XmpParser::decode(pImage->xmpData(), xmpPacket)) {
{
#ifndef SUPPRESS_WARNINGS #ifndef SUPPRESS_WARNINGS
EXV_WARNING << "Failed to decode XMP metadata.\n"; EXV_WARNING << "Failed to decode XMP metadata.\n";
#endif #endif
@ -374,25 +333,19 @@ namespace Exiv2 {
// We look if an Adobe XMP string exist. // We look if an Adobe XMP string exist.
if ( keySize >= 17 if (keySize >= 17 && memcmp("XML:com.adobe.xmp", key, 17) == 0 && pImage->xmpData().empty()) {
&& memcmp("XML:com.adobe.xmp", key, 17) == 0 if (arr.size() > 0) {
&& pImage->xmpData().empty())
{
if (arr.size() > 0)
{
std::string& xmpPacket = pImage->xmpPacket(); std::string& xmpPacket = pImage->xmpPacket();
xmpPacket.assign(arr.c_str(), arr.size()); xmpPacket.assign(arr.c_str(), arr.size());
std::string::size_type idx = xmpPacket.find_first_of('<'); std::string::size_type idx = xmpPacket.find_first_of('<');
if (idx != std::string::npos && idx > 0) if (idx != std::string::npos && idx > 0) {
{
#ifndef SUPPRESS_WARNINGS #ifndef SUPPRESS_WARNINGS
EXV_WARNING << "Removing " << idx << " characters " EXV_WARNING << "Removing " << idx << " characters "
<< "from the beginning of the XMP packet\n"; << "from the beginning of the XMP packet\n";
#endif #endif
xmpPacket = xmpPacket.substr(idx); xmpPacket = xmpPacket.substr(idx);
} }
if (XmpParser::decode(pImage->xmpData(), xmpPacket)) if (XmpParser::decode(pImage->xmpData(), xmpPacket)) {
{
#ifndef SUPPRESS_WARNINGS #ifndef SUPPRESS_WARNINGS
EXV_WARNING << "Failed to decode XMP metadata.\n"; EXV_WARNING << "Failed to decode XMP metadata.\n";
#endif #endif
@ -403,17 +356,13 @@ namespace Exiv2 {
// We look if a comments string exist. Note than we use only 'Description' keyword which // We look if a comments string exist. Note than we use only 'Description' keyword which
// is dedicaced to store long comments. 'Comment' keyword is ignored. // is dedicaced to store long comments. 'Comment' keyword is ignored.
if ( keySize >= 11 if (keySize >= 11 && memcmp("Description", key, 11) == 0 && pImage->comment().empty()) {
&& memcmp("Description", key, 11) == 0
&& pImage->comment().empty())
{
pImage->setComment(std::string(arr.c_str(), arr.size())); pImage->setComment(std::string(arr.c_str(), arr.size()));
} }
} // PngChunk::parseChunkContent } // PngChunk::parseChunkContent
std::string PngChunk::makeMetadataChunk(const std::string& metadata, std::string PngChunk::makeMetadataChunk(const std::string& metadata, MetadataId type)
MetadataId type)
{ {
std::string chunk; std::string chunk;
std::string rawProfile; std::string rawProfile;
@ -443,9 +392,7 @@ namespace Exiv2 {
} // PngChunk::makeMetadataChunk } // PngChunk::makeMetadataChunk
void PngChunk::zlibUncompress(const byte* compressedText, void PngChunk::zlibUncompress(const byte* compressedText, unsigned int compressedTextSize, DataBuf& arr)
unsigned int compressedTextSize,
DataBuf& arr)
{ {
uLongf uncompressedLen = compressedTextSize * 2; // just a starting point uLongf uncompressedLen = compressedTextSize * 2; // just a starting point
int zlibResult; int zlibResult;
@ -453,29 +400,24 @@ namespace Exiv2 {
do { do {
arr.alloc(uncompressedLen); arr.alloc(uncompressedLen);
zlibResult = uncompress(arr.data(), zlibResult = uncompress(arr.data(), &uncompressedLen, compressedText, compressedTextSize);
&uncompressedLen,
compressedText,
compressedTextSize);
if (zlibResult == Z_OK) { if (zlibResult == Z_OK) {
assert((uLongf)arr.size() >= uncompressedLen); assert((uLongf)arr.size() >= uncompressedLen);
arr.resize(uncompressedLen); arr.resize(uncompressedLen);
} } else if (zlibResult == Z_BUF_ERROR) {
else if (zlibResult == Z_BUF_ERROR) {
// the uncompressedArray needs to be larger // the uncompressedArray needs to be larger
uncompressedLen *= 2; uncompressedLen *= 2;
// DoS protection. can't be bigger than 64k // DoS protection. can't be bigger than 64k
if (uncompressedLen > 131072) { if (uncompressedLen > 131072) {
if (++dos > 1) break; if (++dos > 1)
break;
uncompressedLen = 131072; uncompressedLen = 131072;
} }
} } else {
else {
// something bad happened // something bad happened
throw Error(kerFailedToReadImageData); throw Error(kerFailedToReadImageData);
} }
} } while (zlibResult == Z_BUF_ERROR);
while (zlibResult == Z_BUF_ERROR);
if (zlibResult != Z_OK) { if (zlibResult != Z_OK) {
throw Error(kerFailedToReadImageData); throw Error(kerFailedToReadImageData);
@ -505,7 +447,8 @@ namespace Exiv2 {
#endif #endif
compressedLen *= 2; compressedLen *= 2;
// DoS protection. Cap max compressed size // DoS protection. Cap max compressed size
if ( compressedLen > 131072 ) throw Error(kerFailedToReadImageData); if (compressedLen > 131072)
throw Error(kerFailedToReadImageData);
break; break;
default: default:
// Something bad happened // Something bad happened
@ -517,9 +460,7 @@ namespace Exiv2 {
} // PngChunk::zlibCompress } // PngChunk::zlibCompress
std::string PngChunk::makeAsciiTxtChunk(const std::string& keyword, std::string PngChunk::makeAsciiTxtChunk(const std::string& keyword, const std::string& text, bool compress)
const std::string& text,
bool compress)
{ {
// Chunk structure: length (4 bytes) + chunk type + chunk data + CRC (4 bytes) // Chunk structure: length (4 bytes) + chunk type + chunk data + CRC (4 bytes)
// Length is the size of the chunk data // Length is the size of the chunk data
@ -537,8 +478,7 @@ namespace Exiv2 {
if (compress) { if (compress) {
chunkData += '\0' + zlibCompress(text); chunkData += '\0' + zlibCompress(text);
chunkType = "zTXt"; chunkType = "zTXt";
} } else {
else {
chunkData += text; chunkData += text;
chunkType = "tEXt"; chunkType = "tEXt";
} }
@ -557,9 +497,7 @@ namespace Exiv2 {
} // PngChunk::makeAsciiTxtChunk } // PngChunk::makeAsciiTxtChunk
std::string PngChunk::makeUtf8TxtChunk(const std::string& keyword, std::string PngChunk::makeUtf8TxtChunk(const std::string& keyword, const std::string& text, bool compress)
const std::string& text,
bool compress)
{ {
// Chunk structure: length (4 bytes) + chunk type + chunk data + CRC (4 bytes) // Chunk structure: length (4 bytes) + chunk type + chunk data + CRC (4 bytes)
// Length is the size of the chunk data // Length is the size of the chunk data
@ -572,11 +510,10 @@ namespace Exiv2 {
// Build chunk data, determine chunk type // Build chunk data, determine chunk type
std::string chunkData = keyword; std::string chunkData = keyword;
if (compress) { if (compress) {
static const char flags[] = { 0x00, 0x01, 0x00, 0x00, 0x00 }; static const char flags[] = {0x00, 0x01, 0x00, 0x00, 0x00};
chunkData += std::string(flags, 5) + zlibCompress(text); chunkData += std::string(flags, 5) + zlibCompress(text);
} } else {
else { static const char flags[] = {0x00, 0x00, 0x00, 0x00, 0x00};
static const char flags[] = { 0x00, 0x00, 0x00, 0x00, 0x00 };
chunkData += std::string(flags, 5) + text; chunkData += std::string(flags, 5) + text;
} }
// Determine length of the chunk data // Determine length of the chunk data
@ -595,20 +532,19 @@ namespace Exiv2 {
} // PngChunk::makeUtf8TxtChunk } // PngChunk::makeUtf8TxtChunk
DataBuf PngChunk::readRawProfile(const DataBuf& text,bool iTXt) DataBuf PngChunk::readRawProfile(const DataBuf& text, bool iTXt)
{ {
DataBuf info; DataBuf info;
unsigned char unhex[103]={0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, unsigned char unhex[103] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0,0,0,0,0,0,0,0,0,1, 2,3,4,5,6,7,8,9,0,0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0,
0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,10,11,12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 11, 12, 13, 14, 15};
13,14,15};
if (text.size() == 0) { if (text.size() == 0) {
return DataBuf(); return DataBuf();
} }
if ( iTXt ) { if (iTXt) {
info.alloc(text.size()); info.alloc(text.size());
info.copyBytes(0, text.c_data(), text.size()); info.copyBytes(0, text.c_data(), text.size());
return info; return info;
@ -622,33 +558,28 @@ namespace Exiv2 {
} }
// Look for newline // Look for newline
while (*sp != '\n') while (*sp != '\n') {
{
sp++; sp++;
if ( sp == eot ) if (sp == eot) {
{
return DataBuf(); return DataBuf();
} }
} }
sp++ ; // step over '\n' sp++; // step over '\n'
if (sp == eot) { if (sp == eot) {
return DataBuf(); return DataBuf();
} }
// Look for length // Look for length
while (*sp == '\0' || *sp == ' ' || *sp == '\n') while (*sp == '\0' || *sp == ' ' || *sp == '\n') {
{
sp++; sp++;
if (sp == eot ) if (sp == eot) {
{
return DataBuf(); return DataBuf();
} }
} }
// Parse the length. // Parse the length.
long length = 0; long length = 0;
while ('0' <= *sp && *sp <= '9') while ('0' <= *sp && *sp <= '9') {
{
// Compute the new length using unsigned long, so that we can // Compute the new length using unsigned long, so that we can
// check for overflow. // check for overflow.
const unsigned long newlength = (10 * static_cast<unsigned long>(length)) + (*sp - '0'); const unsigned long newlength = (10 * static_cast<unsigned long>(length)) + (*sp - '0');
@ -657,28 +588,25 @@ namespace Exiv2 {
} }
length = static_cast<long>(newlength); length = static_cast<long>(newlength);
sp++; sp++;
if (sp == eot ) if (sp == eot) {
{
return DataBuf(); return DataBuf();
} }
} }
sp++ ; // step over '\n' sp++; // step over '\n'
if (sp == eot) { if (sp == eot) {
return DataBuf(); return DataBuf();
} }
enforce(length <= (eot - sp)/2, Exiv2::kerCorruptedMetadata); enforce(length <= (eot - sp) / 2, Exiv2::kerCorruptedMetadata);
// Allocate space // Allocate space
if (length == 0) if (length == 0) {
{
#ifdef EXIV2_DEBUG_MESSAGES #ifdef EXIV2_DEBUG_MESSAGES
std::cerr << "Exiv2::PngChunk::readRawProfile: Unable To Copy Raw Profile: invalid profile length\n"; std::cerr << "Exiv2::PngChunk::readRawProfile: Unable To Copy Raw Profile: invalid profile length\n";
#endif #endif
} }
info.alloc(length); info.alloc(length);
if (info.size() != length) if (info.size() != length) {
{
#ifdef EXIV2_DEBUG_MESSAGES #ifdef EXIV2_DEBUG_MESSAGES
std::cerr << "Exiv2::PngChunk::readRawProfile: Unable To Copy Raw Profile: cannot allocate memory\n"; std::cerr << "Exiv2::PngChunk::readRawProfile: Unable To Copy Raw Profile: cannot allocate memory\n";
#endif #endif
@ -687,15 +615,13 @@ namespace Exiv2 {
// Copy profile, skipping white space and column 1 "=" signs // Copy profile, skipping white space and column 1 "=" signs
unsigned char *dp = info.data(); // decode pointer unsigned char* dp = info.data(); // decode pointer
unsigned int nibbles = length * 2; unsigned int nibbles = length * 2;
for (long i = 0; i < static_cast<long>(nibbles); i++) { for (long i = 0; i < static_cast<long>(nibbles); i++) {
enforce(sp < eot, Exiv2::kerCorruptedMetadata); enforce(sp < eot, Exiv2::kerCorruptedMetadata);
while (*sp < '0' || (*sp > '9' && *sp < 'a') || *sp > 'f') while (*sp < '0' || (*sp > '9' && *sp < 'a') || *sp > 'f') {
{ if (*sp == '\0') {
if (*sp == '\0')
{
#ifdef EXIV2_DEBUG_MESSAGES #ifdef EXIV2_DEBUG_MESSAGES
std::cerr << "Exiv2::PngChunk::readRawProfile: Unable To Copy Raw Profile: ran out of data\n"; std::cerr << "Exiv2::PngChunk::readRawProfile: Unable To Copy Raw Profile: ran out of data\n";
#endif #endif
@ -706,7 +632,7 @@ namespace Exiv2 {
enforce(sp < eot, Exiv2::kerCorruptedMetadata); enforce(sp < eot, Exiv2::kerCorruptedMetadata);
} }
if (i%2 == 0) if (i % 2 == 0)
*dp = static_cast<unsigned char>(16 * unhex[static_cast<int>(*sp++)]); *dp = static_cast<unsigned char>(16 * unhex[static_cast<int>(*sp++)]);
else else
(*dp++) += unhex[static_cast<int>(*sp++)]; (*dp++) += unhex[static_cast<int>(*sp++)];
@ -716,16 +642,16 @@ namespace Exiv2 {
} // PngChunk::readRawProfile } // PngChunk::readRawProfile
std::string PngChunk::writeRawProfile(const std::string& profileData, std::string PngChunk::writeRawProfile(const std::string& profileData, const char* profileType)
const char* profileType)
{ {
static byte hex[16] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'}; static byte hex[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
std::ostringstream oss; std::ostringstream oss;
oss << '\n' << profileType << '\n' << std::setw(8) << profileData.size(); oss << '\n' << profileType << '\n' << std::setw(8) << profileData.size();
const char* sp = profileData.data(); const char* sp = profileData.data();
for (std::string::size_type i = 0; i < profileData.size(); ++i) { for (std::string::size_type i = 0; i < profileData.size(); ++i) {
if (i % 36 == 0) oss << '\n'; if (i % 36 == 0)
oss << '\n';
oss << hex[((*sp >> 4) & 0x0f)]; oss << hex[((*sp >> 4) & 0x0f)];
oss << hex[((*sp++) & 0x0f)]; oss << hex[((*sp++) & 0x0f)];
} }
@ -737,4 +663,3 @@ namespace Exiv2 {
} // namespace Internal } // namespace Internal
} // namespace Exiv2 } // namespace Exiv2
#endif // ifdef EXV_HAVE_LIBZ #endif // ifdef EXV_HAVE_LIBZ

Loading…
Cancel
Save