Improved loading of JPEG data in case of problems. Existing Exif data is not modified until the new IFD0 is read successfully. Improved ExifData::clear()

v0.27.3
Andreas Huggel 19 years ago
parent cc38da116d
commit 592ca5c711

@ -468,27 +468,36 @@ namespace Exiv2 {
if (!buf || len == 0) return -1; if (!buf || len == 0) return -1;
// Copy the data buffer // Copy the data buffer
delete[] pData_; DataBuf tmpData(len);
pData_ = new byte[len]; memcpy(tmpData.pData_, buf, len);
memcpy(pData_, buf, len);
size_ = len;
// Read the TIFF header // Read the TIFF header
delete pTiffHeader_; std::auto_ptr<TiffHeader> tmpTiffHeader(new TiffHeader);
pTiffHeader_ = new TiffHeader; assert(tmpTiffHeader.get() != 0);
assert(pTiffHeader_ != 0); if (tmpData.size_ < tmpTiffHeader->size()) return 1;
int rc = pTiffHeader_->read(pData_); int rc = tmpTiffHeader->read(tmpData.pData_);
if (rc) return rc; if (rc) return rc;
// Read IFD0 // Read IFD0
delete pIfd0_; std::auto_ptr<Ifd> tmpIfd0(new Ifd(ifd0Id, 0, false));
pIfd0_ = new Ifd(ifd0Id, 0, false); assert(tmpIfd0.get() != 0);
assert(pIfd0_ != 0); rc = tmpIfd0->read(tmpData.pData_,
rc = pIfd0_->read(pData_, size_, pTiffHeader_->offset(), byteOrder()); tmpData.size_,
tmpTiffHeader->offset(),
tmpTiffHeader->byteOrder());
if (rc) return rc; // no point to continue if there is no IFD0 if (rc) return rc; // no point to continue if there is no IFD0
delete pExifIfd_; // We have at least a valid IFD0, so replace old metadata with new now
pExifIfd_ = 0; // After this point we only return 0 (success), although parts of the
// Exif data may be missing due to problems reading specific IFDs.
this->clear(); // Deletes existing pointers
pData_ = tmpData.pData_;
size_ = tmpData.size_;
tmpData.release();
pTiffHeader_ = tmpTiffHeader.release();
pIfd0_ = tmpIfd0.release();
std::auto_ptr<Ifd> tmpExif(new Ifd(exifIfdId, 0, false)); std::auto_ptr<Ifd> tmpExif(new Ifd(exifIfdId, 0, false));
assert(tmpExif.get() != 0); assert(tmpExif.get() != 0);
// Find and read ExifIFD sub-IFD of IFD0 // Find and read ExifIFD sub-IFD of IFD0
@ -496,13 +505,12 @@ namespace Exiv2 {
if (0 == rc) { if (0 == rc) {
pExifIfd_ = tmpExif.release(); pExifIfd_ = tmpExif.release();
} }
if (pExifIfd_) { if (pExifIfd_) {
// Find MakerNote in ExifIFD, create a MakerNote class // Find MakerNote in ExifIFD, create a MakerNote class
Ifd::iterator pos = pExifIfd_->findTag(0x927c); Ifd::iterator pos = pExifIfd_->findTag(0x927c);
Ifd::iterator make = pIfd0_->findTag(0x010f); Ifd::iterator make = pIfd0_->findTag(0x010f);
Ifd::iterator model = pIfd0_->findTag(0x0110); Ifd::iterator model = pIfd0_->findTag(0x0110);
delete pMakerNote_;
pMakerNote_ = 0;
MakerNote::AutoPtr tmpMakerNote; MakerNote::AutoPtr tmpMakerNote;
if ( pos != pExifIfd_->end() if ( pos != pExifIfd_->end()
&& make != pIfd0_->end() && model != pIfd0_->end()) { && make != pIfd0_->end() && model != pIfd0_->end()) {
@ -538,8 +546,6 @@ namespace Exiv2 {
pExifIfd_->erase(pos); pExifIfd_->erase(pos);
} }
delete pIopIfd_;
pIopIfd_ = 0;
std::auto_ptr<Ifd> tmpIop(new Ifd(iopIfdId, 0, false)); std::auto_ptr<Ifd> tmpIop(new Ifd(iopIfdId, 0, false));
assert(tmpIop.get() != 0); assert(tmpIop.get() != 0);
// Find and read Interoperability IFD in ExifIFD // Find and read Interoperability IFD in ExifIFD
@ -549,8 +555,6 @@ namespace Exiv2 {
} }
} // if (pExifIfd_) } // if (pExifIfd_)
delete pGpsIfd_;
pGpsIfd_ = 0;
std::auto_ptr<Ifd> tmpGps(new Ifd(gpsIfdId, 0, false)); std::auto_ptr<Ifd> tmpGps(new Ifd(gpsIfdId, 0, false));
assert(tmpGps.get() != 0); assert(tmpGps.get() != 0);
// Find and read GPSInfo sub-IFD in IFD0 // Find and read GPSInfo sub-IFD in IFD0
@ -559,8 +563,6 @@ namespace Exiv2 {
pGpsIfd_ = tmpGps.release(); pGpsIfd_ = tmpGps.release();
} }
delete pIfd1_;
pIfd1_ = 0;
std::auto_ptr<Ifd> tmpIfd1(new Ifd(ifd1Id, 0, false)); std::auto_ptr<Ifd> tmpIfd1(new Ifd(ifd1Id, 0, false));
assert(tmpIfd1.get() != 0); assert(tmpIfd1.get() != 0);
// Read IFD1 // Read IFD1
@ -575,17 +577,14 @@ namespace Exiv2 {
Ifd::iterator pos = pIfd1_->findTag(0x8769); Ifd::iterator pos = pIfd1_->findTag(0x8769);
if (pos != pIfd1_->end()) { if (pos != pIfd1_->end()) {
pIfd1_->erase(pos); pIfd1_->erase(pos);
rc = 7;
} }
// Find and delete GPSInfo sub-IFD in IFD1 // Find and delete GPSInfo sub-IFD in IFD1
pos = pIfd1_->findTag(0x8825); pos = pIfd1_->findTag(0x8825);
if (pos != pIfd1_->end()) { if (pos != pIfd1_->end()) {
pIfd1_->erase(pos); pIfd1_->erase(pos);
rc = 7;
} }
} }
// Copy all entries from the IFDs and the MakerNote to the metadata // Copy all entries from the IFDs and the MakerNote to the metadata
exifMetadata_.clear();
add(pIfd0_->begin(), pIfd0_->end(), byteOrder()); add(pIfd0_->begin(), pIfd0_->end(), byteOrder());
if (pExifIfd_) add(pExifIfd_->begin(), pExifIfd_->end(), byteOrder()); if (pExifIfd_) add(pExifIfd_->begin(), pExifIfd_->end(), byteOrder());
if (pMakerNote_) { if (pMakerNote_) {
@ -599,7 +598,7 @@ namespace Exiv2 {
// Read the thumbnail (but don't worry whether it was successful or not) // Read the thumbnail (but don't worry whether it was successful or not)
readThumbnail(); readThumbnail();
return rc; return 0;
} // ExifData::load } // ExifData::load
DataBuf ExifData::copy() DataBuf ExifData::copy()
@ -806,6 +805,28 @@ namespace Exiv2 {
FindMetadatumByIfdIdIdx(ifdId, idx)); FindMetadatumByIfdIdIdx(ifdId, idx));
} }
void ExifData::clear()
{
eraseThumbnail();
exifMetadata_.clear();
delete pTiffHeader_;
pTiffHeader_ = 0;
delete pIfd0_;
pIfd0_ = 0;
delete pExifIfd_;
pExifIfd_ = 0;
delete pIopIfd_;
pIopIfd_ = 0;
delete pGpsIfd_;
pGpsIfd_ = 0;
delete pIfd1_;
pIfd1_ = 0;
delete pMakerNote_;
pMakerNote_ = 0;
delete[] pData_;
pData_ = 0;
}
void ExifData::sortByKey() void ExifData::sortByKey()
{ {
std::sort(exifMetadata_.begin(), exifMetadata_.end(), cmpMetadataByKey); std::sort(exifMetadata_.begin(), exifMetadata_.end(), cmpMetadataByKey);

@ -573,7 +573,7 @@ namespace Exiv2 {
@brief Delete all Exifdatum instances resulting in an empty container. @brief Delete all Exifdatum instances resulting in an empty container.
Note that this also removes thumbnails. Note that this also removes thumbnails.
*/ */
void clear() { eraseThumbnail(); exifMetadata_.clear(); } void clear();
//! Sort metadata by key //! Sort metadata by key
void sortByKey(); void sortByKey();
//! Sort metadata by tag //! Sort metadata by tag

@ -248,5 +248,6 @@ Error: Directory Iop with 768 entries considered invalid; not read.
Warning: IFD1: Pointer to next IFD is out of bounds; ignored. Warning: IFD1: Pointer to next IFD is out of bounds; ignored.
Error: Upper boundary of the 1st data entry of IFD1 is out of bounds: Error: Upper boundary of the 1st data entry of IFD1 is out of bounds:
Offset = 0x0203fa04, exceeds buffer size by 168813082 Bytes Offset = 0x0203fa04, exceeds buffer size by 168813082 Bytes
Exiv2 exception in print action for file exiv2-bug495.jpg: Iptc.Application2.Caption String 56 Die Insel Stromboli mit dem Vulkan Stromboli, 1000m hoch
Failed to decode Exif metadata Iptc.Application2.Program String 7 digiKam
Iptc.Application2.ProgramVersion String 11 0.9.0-beta3

Loading…
Cancel
Save