XMP_Uns32 TagTree::digest32u(LFA_FileRef file,const std::string key /* ="" */, bool BigEndian /*=false*/,bool hexDisplay /*=false*/ ) { XMP_Uns32 r; if (4 != LFA_Read ( file, &r, 4, false)) // require all == false => leave the throwing to this routine Log::error("could not read 4-byte value from file (end of file?)"); if ( ((kBigEndianHost==1) && !BigEndian ) || ((kBigEndianHost==0) && BigEndian )) // "XOR" Flip4(&r); if (!key.empty()) { char out[19]; //longest unsigned int is "2147483648", 10 chars resp. 0xFFFFFFFF 10 chars if (!hexDisplay) snprintf(out,18,"%u",r); //unsigned, mind the trailing \0 on Mac btw else snprintf(out,18,"0x%.8X",r); //unsigned, mind the trailing \0 on Mac btw setKeyValue(key,out); } return r; }
XMP_Uns32 TIFF_MemoryReader::ProcessOneIFD ( XMP_Uns32 ifdOffset, XMP_Uns8 ifd ) { TweakedIFDInfo& ifdInfo = this->containedIFDs[ifd]; if ( (ifdOffset < 8) || (ifdOffset > (this->tiffLength - kEmptyIFDLength)) ) { XMP_Error error(kXMPErr_BadTIFF, "Bad IFD offset" ); this->NotifyClient ( kXMPErrSev_FileFatal, error ); } XMP_Uns8* ifdPtr = this->tiffStream + ifdOffset; XMP_Uns16 ifdCount = this->GetUns16 ( ifdPtr ); TweakedIFDEntry* ifdEntries = (TweakedIFDEntry*)(ifdPtr+2); if ( ifdCount >= 0x8000 ) { XMP_Error error(kXMPErr_BadTIFF, "Outrageous IFD count" ); this->NotifyClient ( kXMPErrSev_FileFatal, error ); } if ( (XMP_Uns32)(2 + ifdCount*12 + 4) > (this->tiffLength - ifdOffset) ) { XMP_Error error(kXMPErr_BadTIFF, "Out of bounds IFD" ); this->NotifyClient ( kXMPErrSev_FileFatal, error ); } ifdInfo.count = ifdCount; ifdInfo.entries = ifdEntries; XMP_Int32 prevTag = -1; // ! The GPS IFD has a tag 0, so we need a signed initial value. bool needsSorting = false; for ( size_t i = 0; i < ifdCount; ++i ) { TweakedIFDEntry* thisEntry = &ifdEntries[i]; // Tweak the IFD entry to be more useful. if ( ! this->nativeEndian ) { Flip2 ( &thisEntry->id ); Flip2 ( &thisEntry->type ); Flip4 ( &thisEntry->bytes ); } if ( GetUns16AsIs(&thisEntry->id) <= prevTag ) needsSorting = true; prevTag = GetUns16AsIs ( &thisEntry->id ); if ( (GetUns16AsIs(&thisEntry->type) < kTIFF_ByteType) || (GetUns16AsIs(&thisEntry->type) > kTIFF_LastType) ) continue; // Bad type, skip this tag. #if ! SUNOS_SPARC thisEntry->bytes *= (XMP_Uns32)kTIFF_TypeSizes[thisEntry->type]; if ( thisEntry->bytes > 4 ) { if ( ! this->nativeEndian ) Flip4 ( &thisEntry->dataOrPos ); if ( (thisEntry->dataOrPos < 8) || (thisEntry->dataOrPos >= this->tiffLength) ) { thisEntry->bytes = thisEntry->dataOrPos = 0; // Make this bad tag look empty. } if ( thisEntry->bytes > (this->tiffLength - thisEntry->dataOrPos) ) { thisEntry->bytes = thisEntry->dataOrPos = 0; // Make this bad tag look empty. } } #else void *tempEntryByte = &thisEntry->bytes; XMP_Uns32 temp = GetUns32AsIs(&thisEntry->bytes); temp = temp * (XMP_Uns32)kTIFF_TypeSizes[GetUns16AsIs(&thisEntry->type)]; memcpy ( tempEntryByte, &temp, sizeof(thisEntry->bytes) ); // thisEntry->bytes *= (XMP_Uns32)kTIFF_TypeSizes[thisEntry->type]; if ( GetUns32AsIs(&thisEntry->bytes) > 4 ) { void *tempEntryDataOrPos = &thisEntry->dataOrPos; if ( ! this->nativeEndian ) Flip4 ( &thisEntry->dataOrPos ); if ( (GetUns32AsIs(&thisEntry->dataOrPos) < 8) || (GetUns32AsIs(&thisEntry->dataOrPos) >= this->tiffLength) ) { // thisEntry->bytes = thisEntry->dataOrPos = 0; // Make this bad tag look empty. memset ( tempEntryByte, 0, sizeof(XMP_Uns32) ); memset ( tempEntryDataOrPos, 0, sizeof(XMP_Uns32) ); } if ( GetUns32AsIs(&thisEntry->bytes) > (this->tiffLength - GetUns32AsIs(&thisEntry->dataOrPos)) ) { // thisEntry->bytes = thisEntry->dataOrPos = 0; // Make this bad tag look empty. memset ( tempEntryByte, 0, sizeof(XMP_Uns32) ); memset ( tempEntryDataOrPos, 0, sizeof(XMP_Uns32) ); } } #endif } ifdPtr += (2 + ifdCount*12); XMP_Uns32 nextIFDOffset = this->GetUns32 ( ifdPtr ); if ( needsSorting ) SortIFD ( &ifdInfo ); // ! Don't perturb the ifdCount used to find the next IFD offset. return nextIFDOffset; } // TIFF_MemoryReader::ProcessOneIFD