// reads entire *FileHeader* structure from file (starting at current position) void read(XMP_IO* file) { this->release(); file ->ReadAll ( fields , FIXED_SIZE ); XMP_Uns32 tmp32 = GetUns32LE( &this->fields[FileHeader::o_sig] ); XMP_Validate( SIG == tmp32, "invalid header", kXMPErr_BadFileFormat ); filenameLen = GetUns16LE( &this->fields[FileHeader::o_fileNameLength] ); extraFieldLen = GetUns16LE( &this->fields[FileHeader::o_extraFieldLength] ); // nb unlike the CDFileHeader the FileHeader will in practice never have // extra fields. Reasoning: File headers never carry (their own) offsets, // (un)compressed size of XMP will hardly ever reach 4 GB if (filenameLen) { filename = new char[filenameLen]; file->ReadAll ( filename, filenameLen ); } if (extraFieldLen) { extraField = new char[extraFieldLen]; file->ReadAll ( extraField, extraFieldLen ); // *** NB: this WOULD need parsing for content files that are // compressed or uncompressed >4GB (VERY unlikely for XMP) } }
void write(XMP_IO* file) { XMP_Enforce( this->SIG == GetUns32LE( &this->fields[o_Sig] ) ); commentLen = GetUns16LE( &this->fields[o_CommentLen] ); file ->Write ( fields , FIXED_SIZE ); if (commentLen) file->Write ( comment, commentLen ); }
XMP_Uns32 ReadFileAttrFlags ( IO::InputStream* inputStream ) { XMP_Uns8 buffer[4]; XMP_Uns32 bytes = inputStream->Read ( buffer, 4 ); XMP_Assert ( bytes == 4 ); return GetUns32LE ( buffer ); } // ReadFileAttrFlags
// writes structure to file (starting at current position) void write(XMP_IO* file) { XMP_Validate( SIG == GetUns32LE( &this->fields[FileHeader::o_sig] ), "invalid header on write", kXMPErr_BadFileFormat ); filenameLen = GetUns16LE( &this->fields[FileHeader::o_fileNameLength] ); extraFieldLen = GetUns16LE( &this->fields[FileHeader::o_extraFieldLength] ); file ->Write ( fields , FIXED_SIZE ); if (filenameLen) file->Write ( filename, filenameLen ); if (extraFieldLen) file->Write ( extraField, extraFieldLen ); }
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; }
// writes structure to file (starting at current position) void write(XMP_IO* file) { //// WRITE BACK REAL 64 BIT VALUES, CREATE EXTRA FIELD /////////////// //may only wipe extra field after obtaining all Info from it if (extraField) delete extraField; extraFieldLen=0; if ( ( sizeUncompressed > 0xffffffff ) || ( sizeCompressed > 0xffffffff ) || ( offsetLocalHeader > 0xffffffff ) ) { extraField = new char[64]; // actual maxlen is 32 extraFieldLen = 4; //first fields are for ID, size if ( sizeUncompressed > 0xffffffff ) { PutUns64LE( sizeUncompressed, &extraField[extraFieldLen] ); extraFieldLen += 8; sizeUncompressed = 0xffffffff; } if ( sizeCompressed > 0xffffffff ) { PutUns64LE( sizeCompressed, &extraField[extraFieldLen] ); extraFieldLen += 8; sizeCompressed = 0xffffffff; } if ( offsetLocalHeader > 0xffffffff ) { PutUns64LE( offsetLocalHeader, &extraField[extraFieldLen] ); extraFieldLen += 8; offsetLocalHeader = 0xffffffff; } //write ID, dataSize PutUns16LE( 0x0001, &extraField[0] ); PutUns16LE( extraFieldLen-4, &extraField[2] ); //extraFieldSize PutUns16LE( extraFieldLen, &this->fields[CDFileHeader::o_extraFieldLength] ); } // write out 32-bit ('ff-stubs' or not) PutUns32LE( (XMP_Uns32)sizeUncompressed, &fields[o_sizeUncompressed] ); PutUns32LE( (XMP_Uns32)sizeCompressed, &fields[o_sizeCompressed] ); PutUns32LE( (XMP_Uns32)offsetLocalHeader, &fields[o_offsetLocalHeader] ); /// WRITE ///////////////////////////////////////////////////////////////// XMP_Enforce( SIG == GetUns32LE( &this->fields[CDFileHeader::o_sig] ) ); file ->Write ( fields , FIXED_SIZE ); if (filenameLen) file->Write ( filename , filenameLen ); if (extraFieldLen) file->Write ( extraField , extraFieldLen ); if (commentLen) file->Write ( extraField , extraFieldLen ); }
void read (XMP_IO* file) { UCFECD_Free(); file->ReadAll ( fields, FIXED_SIZE ); XMP_Validate( this->SIG == GetUns32LE( &this->fields[o_Sig] ), "invalid header", kXMPErr_BadFileFormat ); commentLen = GetUns16LE( &this->fields[o_CommentLen] ); if(commentLen) { comment = new char[commentLen]; file->ReadAll ( comment, commentLen ); } };
void FileInfo::CheckFormat ( LFA_FileRef fileRef ) { IOBuffer ioBuf; LFA_Seek ( fileRef, 0, SEEK_SET ); if ( CheckFileSpace ( fileRef, &ioBuf, SWF_SIGNATURE_LEN ) ) { if ( CheckBytes ( ioBuf.ptr, SWF_F_SIGNATURE_DATA, SWF_SIGNATURE_LEN ) ) { this->compressedFile = false; } else if ( CheckBytes ( ioBuf.ptr, SWF_C_SIGNATURE_DATA, SWF_SIGNATURE_LEN ) ) { this->compressedFile = true; } LFA_Seek ( fileRef, 4, SEEK_SET ); XMP_Uns8 buffer[4]; LFA_Read ( fileRef, buffer, 4 ); iSize = GetUns32LE ( buffer ); } LFA_Seek ( fileRef, 0, SEEK_SET ); } // FileInfo::CheckFormat
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()
XMP_Uns32 sizeTotalCF() { //*** not zip64 bit safe yet, use only for non-large xmp packet return this->sizeHeader() + GetUns32LE( &fields[FileHeader::o_sizeCompressed] ); }
// writes structure to file (starting at current position) void write(XMP_IO* file) { XMP_Validate( ID == GetUns32LE( &this->fields[o_sig] ), "invalid header on write", kXMPErr_BadFileFormat ); file ->Write ( fields , TOTAL_SIZE ); }
static bool ReadTag ( LFA_FileRef inFileRef, long * outTag, UInt32 * outLength, long * subtype, UInt64 & inOutPosition, UInt64 maxOffset ) { UInt32 realLength; long bytesRead; bytesRead = LFA_Read ( inFileRef, outTag, 4 ); if ( bytesRead != 4 ) return false; *outTag = GetUns32LE ( outTag ); bytesRead = LFA_Read ( inFileRef, outLength, 4 ); if ( bytesRead != 4 ) return false; *outLength = GetUns32LE ( outLength ); realLength = *outLength; realLength += (realLength & 1); // Round up to an even value. inOutPosition = GetFilePosition ( inFileRef ); // The file offset of the data portion. UInt64 maxLength = maxOffset - inOutPosition; if ( (inOutPosition > maxOffset) || ((UInt64)(*outLength) > maxLength) ) { bool ignoreLastPad = true; // Ignore cases where a final pad byte is missing. UInt64 fileLen = LFA_Measure ( inFileRef ); if ( inOutPosition > (maxOffset + 1) ) ignoreLastPad = false; if ( (UInt64)(*outLength) > (maxLength + 1) ) ignoreLastPad = false; if ( ! ignoreLastPad ) { // Workaround for bad files in the field that have a bad size in the outermost RIFF // chunk. Do a "runtime repair" of cases where the length is too long (beyond EOF). // This handles read-only usage, update usage is repaired (or not) in the handler. bool oversizeRIFF = (inOutPosition == 8) && // Is this the initial 'RIFF' chunk? (fileLen >= 8); // Is the file at least of the minimal size? if ( ! oversizeRIFF ) { XMP_Throw ( "RIFF tag exceeds maximum length", kXMPErr_BadValue ); } else { *outLength = (UInt32)(fileLen) - 8; realLength = *outLength; realLength += (realLength & 1); // Round up to an even value. } } } *subtype = 0; if ( (*outTag != FOURCC_LIST) && (*outTag != FOURCC_RIFF) ) { UInt64 tempPos = inOutPosition + realLength; if ( tempPos <= maxOffset ) { LFA_Seek ( inFileRef, tempPos, SEEK_SET ); } else if ( (tempPos == (maxOffset + 1)) && (maxOffset == (UInt64)LFA_Measure(inFileRef)) ) { LFA_Seek ( inFileRef, 0, SEEK_END ); // Hack to tolerate a missing final pad byte. } else { XMP_Throw ( "Bad RIFF offset", kXMPErr_BadValue ); } } else { bytesRead = LFA_Read ( inFileRef, subtype, 4 ); if ( bytesRead != 4 ) return false; *subtype = GetUns32LE ( subtype ); *outLength -= 4; realLength -= 4; // Special case: // Since the 'movi' chunk can contain billions of subchunks, skip over the 'movi' subchunk. // // The 'movi' subtype is added to the list as the TAG. // The subtype is returned empty so nobody will try to parse the subchunks. if ( *subtype == listtypeAVIMOVIE ) { inOutPosition = GetFilePosition ( inFileRef ); UInt64 tempPos = inOutPosition + realLength; if ( tempPos <= maxOffset ) { LFA_Seek ( inFileRef, tempPos, SEEK_SET ); } else if ( (tempPos == (maxOffset + 1)) && (maxOffset == (UInt64)LFA_Measure(inFileRef)) ) { LFA_Seek ( inFileRef, 0, SEEK_END ); // Hack to tolerate a missing final pad byte. } else { XMP_Throw ( "Bad RIFF offset", kXMPErr_BadValue ); } *outLength += 4; *outTag = *subtype; *subtype = 0; } inOutPosition = GetFilePosition ( inFileRef ); } return true; }
bool ReadTag ( IO::InputStream* inputStream, TagState & inOutTagState, long* tagType, XMP_Uns32* tagLength, XMP_Uns64& inOutPosition ) { try { XMP_Uns64 startPosition = inOutPosition; long bytesRead; XMP_Uns8 buffer[4]; bytesRead = inputStream->Read ( buffer, 2 ); if ( bytesRead != 2 ) return false; inOutPosition += 2; XMP_Uns16 code = GetUns16LE ( buffer ); *tagType = code >> 6; *tagLength = code & 0x3f; bool longTag = false; if ( *tagLength == 0x3f ) { longTag = true; bytesRead = inputStream->Read ( buffer, 4 ); if ( bytesRead != 4 ) return false; inOutPosition += 4; *tagLength = GetUns32LE ( buffer ); } inOutPosition += *tagLength; TagData newTag; newTag.pos = startPosition; newTag.len = *tagLength; newTag.id = *tagType; newTag.offset = ( (! longTag) ? 2 : 6 ); // we cannot check valid XMP within the handler // provide validating XMP by invoking XMPCore // check tag for XMP if ( newTag.id == SWF_TAG_ID_METADATA ) { newTag.xmp = true; inOutTagState.xmpTag = newTag; CheckTag ( inputStream, inOutTagState, newTag ); if ( ! inOutTagState.hasFileAttrTag ) inOutTagState.hasXMP = true; } //store FileAttribute Tag if ( newTag.id == SWF_TAG_ID_FILEATTRIBUTES ) { inOutTagState.hasFileAttrTag = true; inOutTagState.fileAttrTag = newTag; inOutTagState.hasXMP = HasMetadata ( inputStream, inOutTagState ); //decreasing since stream moved on within HasMetadata function *tagLength -= 4; } //store tag in vector to process later inOutTagState.tags.push_back ( newTag ); //seek to next tag if ( ! newTag.xmp ) inputStream->Skip ( *tagLength ); if ( inputStream->IsEOF() ) return false; } catch ( ... ) { return false; } return true; } // ReadTag