bool ASF_Support::UpdateFileSize ( XMP_IO* fileRef ) { if ( fileRef == 0 ) return false; XMP_Uns64 posCurrent = fileRef->Seek ( 0, kXMP_SeekFromCurrent ); XMP_Uns64 newSizeLE = MakeUns64LE ( fileRef->Length() ); if ( this->posFileSizeInfo != 0 ) { fileRef->Seek ( this->posFileSizeInfo, kXMP_SeekFromStart ); } else { // The position of the file size field is not known, find it. ASF_ObjectBase objHeader; // Read the Header object at the start of the file. fileRef->Rewind(); fileRef->ReadAll ( &objHeader, kASF_ObjectBaseLen ); if ( ! IsEqualGUID ( ASF_Header_Object, objHeader.guid ) ) return false; XMP_Uns32 childCount; fileRef->ReadAll ( &childCount, 4 ); childCount = GetUns32LE ( &childCount ); fileRef->Seek ( 2, kXMP_SeekFromCurrent ); // Skip the 2 reserved bytes. // Look for the File Properties object in the Header's children. for ( ; childCount > 0; --childCount ) { fileRef->ReadAll ( &objHeader, kASF_ObjectBaseLen ); if ( IsEqualGUID ( ASF_File_Properties_Object, objHeader.guid ) ) break; XMP_Uns64 dataLen = GetUns64LE ( &objHeader.size ) - 24; fileRef->Seek ( dataLen, kXMP_SeekFromCurrent ); // Skip this object's data. } if ( childCount == 0 ) return false; // Seek to the file size field. XMP_Uns64 fpoSize = GetUns64LE ( &objHeader.size ); if ( fpoSize < (16+8+16+8) ) return false; fileRef->Seek ( 16, kXMP_SeekFromCurrent ); // Skip to the file size field. } fileRef->Write ( &newSizeLE, 8 ); // Write the new file size. fileRef->Seek ( posCurrent, kXMP_SeekFromStart ); return true; }
void ASF_LegacyManager::ConvertISODateToMSDate ( std::string& source, std::string* dest ) { XMP_DateTime date; SXMPUtils::ConvertToDate ( source, &date ); SXMPUtils::ConvertToUTCTime ( &date ); XMP_Int64 creationDate; creationDate = date.nanoSecond / 100; creationDate += (XMP_Int64 ( date.second) * (10*1000*1000) ); creationDate += (XMP_Int64 ( date.minute) * 60 * (10*1000*1000) ); creationDate += (XMP_Int64 ( date.hour) * 3600 * (10*1000*1000) ); XMP_Int32 days = (date.day - 1); --date.month; while ( date.month >= 1 ) { days += DaysInMonth ( date.year, date.month ); --date.month; } --date.year; while ( date.year >= 1601 ) { days += (IsLeapYear ( date.year) ? 366 : 365 ); --date.year; } creationDate += (XMP_Int64 ( days) * 86400 * (10*1000*1000) ); creationDate = GetUns64LE ( &creationDate ); dest->assign ( (const char*)&creationDate, 8 ); }
bool ASF_Support::ReadObject ( XMP_IO* fileRef, ObjectState & inOutObjectState, XMP_Uns64 * objectLength, XMP_Uns64 & inOutPosition ) { try { XMP_Uns64 startPosition = inOutPosition; XMP_Uns32 bytesRead; ASF_ObjectBase objectBase; bytesRead = fileRef->ReadAll ( &objectBase, kASF_ObjectBaseLen ); if ( bytesRead != kASF_ObjectBaseLen ) return false; *objectLength = GetUns64LE ( &objectBase.size ); inOutPosition += *objectLength; ObjectData newObject; newObject.pos = startPosition; newObject.len = *objectLength; newObject.guid = objectBase.guid; // xmpIsLastObject indicates, that the XMP-object is the last top-level object // reset here, if any another object is read inOutObjectState.xmpIsLastObject = false; if ( IsEqualGUID ( ASF_Header_Object, newObject.guid ) ) { // header object ? this->ReadHeaderObject ( fileRef, inOutObjectState, newObject ); } else if ( IsEqualGUID ( ASF_XMP_Metadata, newObject.guid ) ) { // check object for XMP GUID inOutObjectState.xmpPos = newObject.pos + kASF_ObjectBaseLen; inOutObjectState.xmpLen = newObject.len - kASF_ObjectBaseLen; inOutObjectState.xmpIsLastObject = true; inOutObjectState.xmpObject = newObject; newObject.xmp = true; } inOutObjectState.objects.push_back ( newObject ); fileRef->Seek ( inOutPosition, kXMP_SeekFromStart ); } catch ( ... ) { return false; } return true; }
bool ASF_Support::WriteHeaderExtensionObject ( const std::string& buffer, std::string* header, const ASF_ObjectBase& _objectBase, const int /*reservePadding*/ ) { if ( ! IsEqualGUID ( ASF_Header_Extension_Object, _objectBase.guid ) || (! header) || (buffer.size() < 46) ) return false; const XMP_Uns64 offset = 46; int startPos = header->size(); // copy header base header->append ( buffer, 0, offset ); // read extended header-object structure beginning at the data part (offset = 46) XMP_Uns64 read = 0; XMP_Uns64 data = (_objectBase.size - offset); XMP_Uns64 pos = offset; ASF_ObjectBase objectBase; while ( read < data ) { memcpy ( &objectBase, &buffer[int(pos)], kASF_ObjectBaseLen ); objectBase.size = GetUns64LE ( &objectBase.size ); if ( IsEqualGUID ( ASF_Padding_Object, objectBase.guid ) ) { // eliminate } else { // copy other objects header->append ( buffer, XMP_Uns32(pos), XMP_Uns32(objectBase.size) ); } pos += objectBase.size; read += objectBase.size; } // update header extension data size XMP_Uns32 valueUns32LE = MakeUns32LE ( header->size() - startPos - offset ); std::string newDataSize ( (const char*)&valueUns32LE, 4 ); ReplaceString ( *header, newDataSize, (startPos + 42), 4 ); // update new object size XMP_Uns64 valueUns64LE = MakeUns64LE ( header->size() - startPos ); std::string newObjectSize ( (const char*)&valueUns64LE, 8 ); ReplaceString ( *header, newObjectSize, (startPos + 16), 8 ); return true; }
bool ASF_Support::ReadHeaderExtensionObject ( XMP_IO* fileRef, ObjectState& /*inOutObjectState*/, const XMP_Uns64& _pos, const ASF_ObjectBase& _objectBase ) { if ( ! IsEqualGUID ( ASF_Header_Extension_Object, _objectBase.guid) || (! legacyManager ) ) return false; try { // read extended header-object structure beginning at the data part (offset = 46) const XMP_Uns64 offset = 46; XMP_Uns64 read = 0; XMP_Uns64 data = (_objectBase.size - offset); XMP_Uns64 pos = (_pos + offset); ASF_ObjectBase objectBase; while ( read < data ) { fileRef->Seek ( pos, kXMP_SeekFromStart ); if ( kASF_ObjectBaseLen != fileRef->Read ( &objectBase, kASF_ObjectBaseLen, true ) ) break; objectBase.size = GetUns64LE ( &objectBase.size ); if ( IsEqualGUID ( ASF_Padding_Object, objectBase.guid ) ) { legacyManager->SetPadding ( legacyManager->GetPadding() + (objectBase.size - 24) ); } pos += objectBase.size; read += objectBase.size; } } catch ( ... ) { return false; } return true; }
void ASF_LegacyManager::ConvertMSDateToISODate ( std::string& source, std::string* dest ) { XMP_Int64 creationDate = GetUns64LE ( source.c_str() ); XMP_Int64 totalSecs = creationDate / (10*1000*1000); XMP_Int32 nanoSec = ( ( XMP_Int32) (creationDate - (totalSecs * 10*1000*1000)) ) * 100; XMP_Int32 days = (XMP_Int32) (totalSecs / 86400); totalSecs -= ( ( XMP_Int64)days * 86400 ); XMP_Int32 hour = (XMP_Int32) (totalSecs / 3600); totalSecs -= ( ( XMP_Int64)hour * 3600 ); XMP_Int32 minute = (XMP_Int32) (totalSecs / 60); totalSecs -= ( ( XMP_Int64)minute * 60 ); XMP_Int32 second = (XMP_Int32)totalSecs; // A little more simple code converts this to an XMP date string: XMP_DateTime date; memset ( &date, 0, sizeof ( date ) ); date.year = 1601; // The MS date origin. date.month = 1; date.day = 1; date.day += days; // Add in the delta. date.hour = hour; date.minute = minute; date.second = second; date.nanoSecond = nanoSec; date.hasTimeZone = true; // ! Needed for ConvertToUTCTime to do anything. SXMPUtils::ConvertToUTCTime ( &date ); // Normalize the date/time. SXMPUtils::ConvertFromDate ( date, dest ); // Convert to an ISO 8601 string. }
bool ASF_Support::WriteHeaderObject ( XMP_IO* sourceRef, XMP_IO* destRef, const ObjectData& object, ASF_LegacyManager& _legacyManager, bool usePadding ) { if ( ! IsEqualGUID ( ASF_Header_Object, object.guid ) ) return false; std::string buffer; XMP_Uns16 valueUns16LE; XMP_Uns32 valueUns32LE; XMP_Uns64 valueUns64LE; try { // read header-object structure XMP_Uns64 pos = object.pos; XMP_Uns32 bufferSize = kASF_ObjectBaseLen + 6; buffer.clear(); buffer.reserve ( bufferSize ); buffer.assign ( bufferSize, ' ' ); sourceRef->Seek ( pos, kXMP_SeekFromStart ); sourceRef->ReadAll ( const_cast<char*>(buffer.data()), bufferSize ); XMP_Uns64 read = bufferSize; pos += bufferSize; // read contained header objects /*XMP_Uns32 numberOfHeaders = GetUns32LE ( &buffer[24] );*/ ASF_ObjectBase objectBase; // prepare new header in memory std::string header; int changedObjects = _legacyManager.changedObjects(); int exportedObjects = 0; int writtenObjects = 0; header.append ( buffer.c_str(), bufferSize ); while ( read < object.len ) { sourceRef->Seek ( pos, kXMP_SeekFromStart ); if ( kASF_ObjectBaseLen != sourceRef->Read ( &objectBase, kASF_ObjectBaseLen, true ) ) break; sourceRef->Seek ( pos, kXMP_SeekFromStart ); objectBase.size = GetUns64LE ( &objectBase.size ); int headerStartPos = header.size(); // save position of filesize-information if ( IsEqualGUID ( ASF_File_Properties_Object, objectBase.guid ) ) { posFileSizeInfo = (headerStartPos + 40); } // write objects if ( IsEqualGUID ( ASF_File_Properties_Object, objectBase.guid ) && (objectBase.size >= 104) && (changedObjects & ASF_LegacyManager::objectFileProperties) ) { // copy object and replace creation-date buffer.reserve ( XMP_Uns32 ( objectBase.size ) ); buffer.assign ( XMP_Uns32 ( objectBase.size ), ' ' ); sourceRef->ReadAll ( const_cast<char*>(buffer.data()), XMP_Int32(objectBase.size) ); header.append ( buffer, 0, XMP_Uns32( objectBase.size ) ); if ( ! _legacyManager.GetBroadcast() ) { buffer = _legacyManager.GetField ( ASF_LegacyManager::fieldCreationDate ); ReplaceString ( header, buffer, (headerStartPos + 48), 8 ); } exportedObjects |= ASF_LegacyManager::objectFileProperties; } else if ( IsEqualGUID ( ASF_Content_Description_Object, objectBase.guid ) && (objectBase.size >= 34) && (changedObjects & ASF_LegacyManager::objectContentDescription) ) { // re-create object with xmp-data buffer.reserve ( XMP_Uns32( objectBase.size ) ); buffer.assign ( XMP_Uns32( objectBase.size ), ' ' ); sourceRef->ReadAll ( const_cast<char*>(buffer.data()), XMP_Int32(objectBase.size) ); // write header only header.append ( buffer, 0, XMP_Uns32( kASF_ObjectBaseLen ) ); // write length fields XMP_Uns16 titleLen = _legacyManager.GetField ( ASF_LegacyManager::fieldTitle).size( ); valueUns16LE = MakeUns16LE ( titleLen ); header.append ( (const char*)&valueUns16LE, 2 ); XMP_Uns16 authorLen = _legacyManager.GetField ( ASF_LegacyManager::fieldAuthor).size( ); valueUns16LE = MakeUns16LE ( authorLen ); header.append ( (const char*)&valueUns16LE, 2 ); XMP_Uns16 copyrightLen = _legacyManager.GetField ( ASF_LegacyManager::fieldCopyright).size( ); valueUns16LE = MakeUns16LE ( copyrightLen ); header.append ( (const char*)&valueUns16LE, 2 ); XMP_Uns16 descriptionLen = _legacyManager.GetField ( ASF_LegacyManager::fieldDescription).size( ); valueUns16LE = MakeUns16LE ( descriptionLen ); header.append ( (const char*)&valueUns16LE, 2 ); // retrieve existing overall length of preceding fields XMP_Uns16 precedingLen = 0; precedingLen += GetUns16LE ( &buffer[24] ); // Title precedingLen += GetUns16LE ( &buffer[26] ); // Author precedingLen += GetUns16LE ( &buffer[28] ); // Copyright precedingLen += GetUns16LE ( &buffer[30] ); // Description // retrieve existing 'Rating' length XMP_Uns16 ratingLen = GetUns16LE ( &buffer[32] ); // Rating valueUns16LE = MakeUns16LE ( ratingLen ); header.append ( (const char*)&valueUns16LE, 2 ); // write field contents header.append ( _legacyManager.GetField ( ASF_LegacyManager::fieldTitle ) ); header.append ( _legacyManager.GetField ( ASF_LegacyManager::fieldAuthor ) ); header.append ( _legacyManager.GetField ( ASF_LegacyManager::fieldCopyright ) ); header.append ( _legacyManager.GetField ( ASF_LegacyManager::fieldDescription ) ); header.append ( buffer, (34 + precedingLen), ratingLen ); // update new object size valueUns64LE = MakeUns64LE ( header.size() - headerStartPos ); std::string newSize ( (const char*)&valueUns64LE, 8 ); ReplaceString ( header, newSize, (headerStartPos + 16), 8 ); exportedObjects |= ASF_LegacyManager::objectContentDescription; } else if ( IsEqualGUID ( ASF_Content_Branding_Object, objectBase.guid ) && (changedObjects & ASF_LegacyManager::objectContentBranding) ) { // re-create object with xmp-data buffer.reserve ( XMP_Uns32( objectBase.size ) ); buffer.assign ( XMP_Uns32( objectBase.size ), ' ' ); sourceRef->ReadAll ( const_cast<char*>(buffer.data()), XMP_Int32(objectBase.size) ); // calculate size of fields coming before 'Copyright URL' XMP_Uns32 length = 28; length += (GetUns32LE ( &buffer[length] ) + 4); // Banner Image Data length += (GetUns32LE ( &buffer[length] ) + 4); // Banner Image URL // write first part of header header.append ( buffer, 0, length ); // copyright URL length = _legacyManager.GetField ( ASF_LegacyManager::fieldCopyrightURL).size( ); valueUns32LE = MakeUns32LE ( length ); header.append ( (const char*)&valueUns32LE, 4 ); header.append ( _legacyManager.GetField ( ASF_LegacyManager::fieldCopyrightURL ) ); // update new object size valueUns64LE = MakeUns64LE ( header.size() - headerStartPos ); std::string newSize ( (const char*)&valueUns64LE, 8 ); ReplaceString ( header, newSize, (headerStartPos + 16), 8 ); exportedObjects |= ASF_LegacyManager::objectContentBranding; #if ! Exclude_LicenseURL_Recon } else if ( IsEqualGUID ( ASF_Content_Encryption_Object, objectBase.guid ) && (changedObjects & ASF_LegacyManager::objectContentEncryption) ) { // re-create object with xmp-data buffer.reserve ( XMP_Uns32( objectBase.size ) ); buffer.assign ( XMP_Uns32( objectBase.size ), ' ' ); sourceRef->ReadAll ( const_cast<char*>(buffer.data()), XMP_Int32(objectBase.size) ); // calculate size of fields coming before 'License URL' XMP_Uns32 length = 24; length += (GetUns32LE ( &buffer[length] ) + 4); // Secret Data length += (GetUns32LE ( &buffer[length] ) + 4); // Protection Type length += (GetUns32LE ( &buffer[length] ) + 4); // Key ID // write first part of header header.append ( buffer, 0, length ); // License URL length = _legacyManager.GetField ( ASF_LegacyManager::fieldLicenseURL).size( ); valueUns32LE = MakeUns32LE ( length ); header.append ( (const char*)&valueUns32LE, 4 ); header.append ( _legacyManager.GetField ( ASF_LegacyManager::fieldLicenseURL ) ); // update new object size valueUns64LE = MakeUns64LE ( header.size() - headerStartPos ); std::string newSize ( (const char*)&valueUns64LE, 8 ); ReplaceString ( header, newSize, (headerStartPos + 16), 8 ); exportedObjects |= ASF_LegacyManager::objectContentEncryption; #endif } else if ( IsEqualGUID ( ASF_Header_Extension_Object, objectBase.guid ) && usePadding ) { // re-create object if padding needs to be used buffer.reserve ( XMP_Uns32( objectBase.size ) ); buffer.assign ( XMP_Uns32( objectBase.size ), ' ' ); sourceRef->ReadAll ( const_cast<char*>(buffer.data()), XMP_Int32(objectBase.size) ); ASF_Support::WriteHeaderExtensionObject ( buffer, &header, objectBase, 0 ); } else if ( IsEqualGUID ( ASF_Padding_Object, objectBase.guid ) && usePadding ) { // eliminate padding (will be created as last object) } else { // simply copy all other objects buffer.reserve ( XMP_Uns32( objectBase.size ) ); buffer.assign ( XMP_Uns32( objectBase.size ), ' ' ); sourceRef->ReadAll ( const_cast<char*>(buffer.data()), XMP_Int32(objectBase.size) ); header.append ( buffer, 0, XMP_Uns32( objectBase.size ) ); } pos += objectBase.size; read += objectBase.size; writtenObjects ++; } // any objects to create ? int newObjects = (changedObjects ^ exportedObjects); if ( newObjects ) { // create new objects with xmp-data int headerStartPos; ASF_ObjectBase newObjectBase; XMP_Uns32 length; if ( newObjects & ASF_LegacyManager::objectContentDescription ) { headerStartPos = header.size(); newObjectBase.guid = ASF_Content_Description_Object; newObjectBase.size = 0; // write object header header.append ( (const char*)&newObjectBase, kASF_ObjectBaseLen ); XMP_Uns16 titleLen = _legacyManager.GetField ( ASF_LegacyManager::fieldTitle).size( ); valueUns16LE = MakeUns16LE ( titleLen ); header.append ( (const char*)&valueUns16LE, 2 ); XMP_Uns16 authorLen = _legacyManager.GetField ( ASF_LegacyManager::fieldAuthor).size( ); valueUns16LE = MakeUns16LE ( authorLen ); header.append ( (const char*)&valueUns16LE, 2 ); XMP_Uns16 copyrightLen = _legacyManager.GetField ( ASF_LegacyManager::fieldCopyright).size( ); valueUns16LE = MakeUns16LE ( copyrightLen ); header.append ( (const char*)&valueUns16LE, 2 ); XMP_Uns16 descriptionLen = _legacyManager.GetField ( ASF_LegacyManager::fieldDescription).size( ); valueUns16LE = MakeUns16LE ( descriptionLen ); header.append ( (const char*)&valueUns16LE, 2 ); XMP_Uns16 ratingLen = 0; valueUns16LE = MakeUns16LE ( ratingLen ); header.append ( (const char*)&valueUns16LE, 2 ); // write field contents header.append ( _legacyManager.GetField ( ASF_LegacyManager::fieldTitle ) ); header.append ( _legacyManager.GetField ( ASF_LegacyManager::fieldAuthor ) ); header.append ( _legacyManager.GetField ( ASF_LegacyManager::fieldCopyright ) ); header.append ( _legacyManager.GetField ( ASF_LegacyManager::fieldDescription ) ); // update new object size valueUns64LE = MakeUns64LE ( header.size() - headerStartPos ); std::string newSize ( (const char*)&valueUns64LE, 8 ); ReplaceString ( header, newSize, (headerStartPos + 16), 8 ); newObjects &= ~ASF_LegacyManager::objectContentDescription; writtenObjects ++; } if ( newObjects & ASF_LegacyManager::objectContentBranding ) { headerStartPos = header.size(); newObjectBase.guid = ASF_Content_Branding_Object; newObjectBase.size = 0; // write object header header.append ( (const char*)&newObjectBase, kASF_ObjectBaseLen ); // write 'empty' fields header.append ( 12, '\0' ); // copyright URL length = _legacyManager.GetField ( ASF_LegacyManager::fieldCopyrightURL).size( ); valueUns32LE = MakeUns32LE ( length ); header.append ( (const char*)&valueUns32LE, 4 ); header.append ( _legacyManager.GetField ( ASF_LegacyManager::fieldCopyrightURL ) ); // update new object size valueUns64LE = MakeUns64LE ( header.size() - headerStartPos ); std::string newSize ( (const char*)&valueUns64LE, 8 ); ReplaceString ( header, newSize, (headerStartPos + 16), 8 ); newObjects &= ~ASF_LegacyManager::objectContentBranding; writtenObjects ++; } #if ! Exclude_LicenseURL_Recon if ( newObjects & ASF_LegacyManager::objectContentEncryption ) { headerStartPos = header.size(); newObjectBase.guid = ASF_Content_Encryption_Object; newObjectBase.size = 0; // write object header header.append ( (const char*)&newObjectBase, kASF_ObjectBaseLen ); // write 'empty' fields header.append ( 12, '\0' ); // License URL length = _legacyManager.GetField ( ASF_LegacyManager::fieldLicenseURL).size( ); valueUns32LE = MakeUns32LE ( length ); header.append ( (const char*)&valueUns32LE, 4 ); header.append ( _legacyManager.GetField ( ASF_LegacyManager::fieldLicenseURL ) ); // update new object size valueUns64LE = MakeUns64LE ( header.size() - headerStartPos ); std::string newSize ( (const char*)&valueUns64LE, 8 ); ReplaceString ( header, newSize, (headerStartPos + 16), 8 ); newObjects &= ~ASF_LegacyManager::objectContentEncryption; writtenObjects ++; } #endif } // create padding object ? if ( usePadding && (header.size ( ) < object.len ) ) { ASF_Support::CreatePaddingObject ( &header, (object.len - header.size()) ); writtenObjects ++; } // update new header-object size valueUns64LE = MakeUns64LE ( header.size() ); std::string newValue ( (const char*)&valueUns64LE, 8 ); ReplaceString ( header, newValue, 16, 8 ); // update new number of Header objects valueUns32LE = MakeUns32LE ( writtenObjects ); newValue = std::string ( (const char*)&valueUns32LE, 4 ); ReplaceString ( header, newValue, 24, 4 ); // if we are operating on the same file (in-place update), place pointer before writing if ( sourceRef == destRef ) destRef->Seek ( object.pos, kXMP_SeekFromStart ); if ( this->progressTracker != 0 ) { XMP_Assert ( this->progressTracker->WorkInProgress() ); this->progressTracker->AddTotalWork ( (float)header.size() ); } // write header destRef->Write ( header.c_str(), header.size() ); } catch ( ... ) { return false; } return true; }
bool ASF_Support::ReadHeaderObject ( XMP_IO* fileRef, ObjectState& inOutObjectState, const ObjectData& newObject ) { if ( ! IsEqualGUID ( ASF_Header_Object, newObject.guid) || (! legacyManager ) ) return false; std::string buffer; legacyManager->SetPadding(0); try { // read header-object structure XMP_Uns64 pos = newObject.pos; XMP_Uns32 bufferSize = kASF_ObjectBaseLen + 6; buffer.clear(); buffer.reserve ( bufferSize ); buffer.assign ( bufferSize, ' ' ); fileRef->Seek ( pos, kXMP_SeekFromStart ); fileRef->ReadAll ( const_cast<char*>(buffer.data()), bufferSize ); XMP_Uns64 read = bufferSize; pos += bufferSize; // read contained header objects /*XMP_Uns32 numberOfHeaders = GetUns32LE ( &buffer[24] );*/ ASF_ObjectBase objectBase; while ( read < newObject.len ) { fileRef->Seek ( pos, kXMP_SeekFromStart ); if ( kASF_ObjectBaseLen != fileRef->Read ( &objectBase, kASF_ObjectBaseLen, true ) ) break; fileRef->Seek ( pos, kXMP_SeekFromStart ); objectBase.size = GetUns64LE ( &objectBase.size ); if ( IsEqualGUID ( ASF_File_Properties_Object, objectBase.guid) && (objectBase.size >= 104 ) ) { buffer.clear(); buffer.reserve ( XMP_Uns32( objectBase.size ) ); buffer.assign ( XMP_Uns32( objectBase.size ), ' ' ); fileRef->ReadAll ( const_cast<char*>(buffer.data()), XMP_Int32(objectBase.size) ); // save position of filesize-information posFileSizeInfo = (pos + 40); // creation date std::string sub ( buffer.substr ( 48, 8 ) ); legacyManager->SetField ( ASF_LegacyManager::fieldCreationDate, sub ); // broadcast flag set ? XMP_Uns32 flags = GetUns32LE ( &buffer[88] ); inOutObjectState.broadcast = (flags & 1); legacyManager->SetBroadcast ( inOutObjectState.broadcast ); legacyManager->SetObjectExists ( ASF_LegacyManager::objectFileProperties ); } else if ( IsEqualGUID ( ASF_Content_Description_Object, objectBase.guid) && (objectBase.size >= 34 ) ) { buffer.clear(); buffer.reserve ( XMP_Uns32( objectBase.size ) ); buffer.assign ( XMP_Uns32( objectBase.size ), ' ' ); fileRef->ReadAll ( const_cast<char*>(buffer.data()), XMP_Int32(objectBase.size) ); XMP_Uns16 titleLen = GetUns16LE ( &buffer[24] ); XMP_Uns16 authorLen = GetUns16LE ( &buffer[26] ); XMP_Uns16 copyrightLen = GetUns16LE ( &buffer[28] ); XMP_Uns16 descriptionLen = GetUns16LE ( &buffer[30] ); /*XMP_Uns16 ratingLen = GetUns16LE ( &buffer[32] );*/ XMP_Uns16 fieldPos = 34; std::string titleStr = buffer.substr ( fieldPos, titleLen ); fieldPos += titleLen; legacyManager->SetField ( ASF_LegacyManager::fieldTitle, titleStr ); std::string authorStr = buffer.substr ( fieldPos, authorLen ); fieldPos += authorLen; legacyManager->SetField ( ASF_LegacyManager::fieldAuthor, authorStr ); std::string copyrightStr = buffer.substr ( fieldPos, copyrightLen ); fieldPos += copyrightLen; legacyManager->SetField ( ASF_LegacyManager::fieldCopyright, copyrightStr ); std::string descriptionStr = buffer.substr ( fieldPos, descriptionLen ); fieldPos += descriptionLen; legacyManager->SetField ( ASF_LegacyManager::fieldDescription, descriptionStr ); /* rating is currently not part of reconciliation std::string ratingStr = buffer.substr ( fieldPos, ratingLen ); fieldPos += ratingLen; legacyData.append ( titleStr ); */ legacyManager->SetObjectExists ( ASF_LegacyManager::objectContentDescription ); } else if ( IsEqualGUID ( ASF_Content_Branding_Object, objectBase.guid ) ) { buffer.clear(); buffer.reserve ( XMP_Uns32( objectBase.size ) ); buffer.assign ( XMP_Uns32( objectBase.size ), ' ' ); fileRef->ReadAll ( const_cast<char*>(buffer.data()), XMP_Int32(objectBase.size) ); XMP_Uns32 fieldPos = 28; // copyright URL is 3. element with variable size for ( int i = 1; i <= 3 ; ++i ) { XMP_Uns32 len = GetUns32LE ( &buffer[fieldPos] ); if ( i == 3 ) { std::string copyrightURLStr = buffer.substr ( fieldPos + 4, len ); legacyManager->SetField ( ASF_LegacyManager::fieldCopyrightURL, copyrightURLStr ); } fieldPos += (len + 4); } legacyManager->SetObjectExists ( ASF_LegacyManager::objectContentBranding ); #if ! Exclude_LicenseURL_Recon } else if ( IsEqualGUID ( ASF_Content_Encryption_Object, objectBase.guid ) ) { buffer.clear(); buffer.reserve ( XMP_Uns32( objectBase.size ) ); buffer.assign ( XMP_Uns32( objectBase.size ), ' ' ); fileRef->ReadAll ( const_cast<char*>(buffer.data()), XMP_Int32(objectBase.size) ); XMP_Uns32 fieldPos = 24; // license URL is 4. element with variable size for ( int i = 1; i <= 4 ; ++i ) { XMP_Uns32 len = GetUns32LE ( &buffer[fieldPos] ); if ( i == 4 ) { std::string licenseURLStr = buffer.substr ( fieldPos + 4, len ); legacyManager->SetField ( ASF_LegacyManager::fieldLicenseURL, licenseURLStr ); } fieldPos += (len + 4); } legacyManager->SetObjectExists ( objectContentEncryption ); #endif } else if ( IsEqualGUID ( ASF_Padding_Object, objectBase.guid ) ) { legacyManager->SetPadding ( legacyManager->GetPadding() + (objectBase.size - 24) ); } else if ( IsEqualGUID ( ASF_Header_Extension_Object, objectBase.guid ) ) { this->ReadHeaderExtensionObject ( fileRef, inOutObjectState, pos, objectBase ); } else if (objectBase.size == 0) { break; } pos += objectBase.size; read += objectBase.size; } } catch ( ... ) { return false; } legacyManager->ComputeDigest(); return true; }
// reads entire structure from file (starting at current position) void read(XMP_IO* file) { this->release(); file->ReadAll ( fields, FIXED_SIZE ); XMP_Validate( SIG == GetUns32LE( &this->fields[CDFileHeader::o_sig] ), "invalid header", kXMPErr_BadFileFormat ); filenameLen = GetUns16LE( &this->fields[CDFileHeader::o_fileNameLength] ); extraFieldLen = GetUns16LE( &this->fields[CDFileHeader::o_extraFieldLength] ); commentLen = GetUns16LE( &this->fields[CDFileHeader::o_commentLength] ); if (filenameLen) { filename = new char[filenameLen]; file->ReadAll ( filename, filenameLen ); } if (extraFieldLen) { extraField = new char[extraFieldLen]; file->ReadAll ( extraField, extraFieldLen ); } if (commentLen) { comment = new char[commentLen]; file->ReadAll ( comment, commentLen ); } ////// GET ACTUAL 64 BIT VALUES ////////////////////////////////////////////// // get 32bit goodies first, correct later sizeUncompressed = GetUns32LE( &fields[o_sizeUncompressed] ); sizeCompressed = GetUns32LE( &fields[o_sizeCompressed] ); offsetLocalHeader = GetUns32LE( &fields[o_offsetLocalHeader] ); XMP_Int32 offset = 0; while ( offset < extraFieldLen ) { XMP_Validate( (extraFieldLen - offset) >= 4, "need 4 bytes for next header ID+len", kXMPErr_BadFileFormat); XMP_Uns16 headerID = GetUns16LE( &extraField[offset] ); XMP_Uns16 dataSize = GetUns16LE( &extraField[offset+2] ); offset += 4; XMP_Validate( (extraFieldLen - offset) <= dataSize, "actual field lenght not given", kXMPErr_BadFileFormat); if ( headerID == 0x1 ) //we only care about "Zip64 extended information extra field" { XMP_Validate( offset < extraFieldLen, "extra field too short", kXMPErr_BadFileFormat); if (sizeUncompressed == 0xffffffff) { sizeUncompressed = GetUns64LE( &extraField[offset] ); offset += 8; } if (sizeCompressed == 0xffffffff) { sizeCompressed = GetUns64LE( &extraField[offset] ); offset += 8; } if (offsetLocalHeader == 0xffffffff) { offsetLocalHeader = GetUns64LE( &extraField[offset] ); offset += 8; } } else { offset += dataSize; } // if } // while } // read()