XMP_Uns8 * MOOV_Manager::AppendNewSubtree ( const BoxNode & node, const std::string & parentPath, XMP_Uns8 * newPtr, XMP_Uns8 * newEnd ) { if ( (node.boxType == ISOMedia::k_free) || (node.boxType == ISOMedia::k_wide) ) { } XMP_Assert ( (node.boxType != ISOMedia::k_meta) ? (node.children.empty() || (node.contentSize == 0)) : (node.children.empty() || (node.contentSize == 4)) ); XMP_Enforce ( (XMP_Uns32)(newEnd - newPtr) >= (8 + node.contentSize) ); #if TraceUpdateMoovTree XMP_Uns32 be32 = MakeUns32BE ( node.boxType ); XMP_Uns32 newOffset = (XMP_Uns32) (newPtr - newOrigin); XMP_Uns32 addr32 = (XMP_Uns32) this->PickContentPtr ( node ); fprintf ( stderr, " Appending %s/%.4s @ 0x%X, size %d, content @ 0x%X\n", parentPath.c_str(), &be32, newOffset, node.contentSize, addr32 ); #endif // Leave the size as 0 for now, append the type and content. XMP_Uns8 * boxOrigin = newPtr; // Save origin to fill in the final size. PutUns32BE ( node.boxType, (newPtr + 4) ); IncrNewPtr ( 8 ); if( node.boxType == ISOMedia::k_uuid ) // For uuid, additional 16 bytes is stored for ID { XMP_Enforce ( (XMP_Uns32)(newEnd - newPtr) >= ( 16 + node.contentSize ) ); memcpy( newPtr, node.idUUID, 16 ); IncrNewPtr ( 16 ); } if ( node.contentSize != 0 ) { const XMP_Uns8 * content = PickContentPtr( node ); memcpy ( newPtr, content, node.contentSize ); IncrNewPtr ( node.contentSize ); } // Append the nested boxes. if ( ! node.children.empty() ) { char suffix[6]; suffix[0] = '/'; PutUns32BE ( node.boxType, &suffix[1] ); suffix[5] = 0; std::string nodePath = parentPath + suffix; for ( size_t i = 0, limit = node.children.size(); i < limit; ++i ) { newPtr = this->AppendNewSubtree ( node.children[i], nodePath, newPtr, newEnd ); } } // Fill in the final size. PutUns32BE ( (XMP_Uns32)(newPtr - boxOrigin), boxOrigin ); return newPtr; } // MOOV_Manager::AppendNewSubtree
XMP_Uns32 MOOV_Manager::NewSubtreeSize ( const BoxNode & node, const std::string & parentPath ) { XMP_Uns32 subtreeSize = 8 + node.contentSize; // All boxes will have 8 byte headers. if( node.boxType == ISOMedia::k_uuid ) subtreeSize += 16; // id of uuid is 16 bytes long if ( (node.boxType == ISOMedia::k_free) || (node.boxType == ISOMedia::k_wide) ) { } for ( size_t i = 0, limit = node.children.size(); i < limit; ++i ) { char suffix[6]; suffix[0] = '/'; PutUns32BE ( node.boxType, &suffix[1] ); suffix[5] = 0; std::string nodePath = parentPath + suffix; subtreeSize += this->NewSubtreeSize ( node.children[i], nodePath ); XMP_Enforce ( subtreeSize < moovBoxSizeLimit ); } return subtreeSize; } // MOOV_Manager::NewSubtreeSize
void ID3Header::write ( XMP_IO* file, XMP_Int64 tagSize ) { XMP_Assert ( ((XMP_Int64)kID3_TagHeaderSize <= tagSize) && (tagSize < 256*1024*1024) ); // 256 MB limit due to synching. XMP_Uns32 synchSize = int32ToSynch ( (XMP_Uns32)tagSize - kID3_TagHeaderSize ); PutUns32BE ( synchSize, &this->fields[ID3Header::o_size] ); file->Write ( this->fields, kID3_TagHeaderSize ); }
void ID3v2Frame::write ( XMP_IO* file, XMP_Uns8 majorVersion ) { XMP_Assert ( (2 <= majorVersion) && (majorVersion <= 4) ); if ( majorVersion < 4 ) { PutUns32BE ( this->contentSize, &this->fields[o_size] ); } else { PutUns32BE ( int32ToSynch ( this->contentSize ), &this->fields[o_size] ); } if ( majorVersion > 2 ) { file->Write ( this->fields, kV23_FrameHeaderSize ); } else { file->Write ( &this->fields[o_id], 3 ); file->Write ( &this->fields[o_size+1], 3 ); } file->Write ( this->content, this->contentSize ); } // ID3v2Frame::write
ID3v2Frame::ID3v2Frame ( XMP_Uns32 id ) : frameDefaults { memset ( this->fields, 0, kV23_FrameHeaderSize ); this->id = id; PutUns32BE ( id, &this->fields[o_id] ); }
XMP_Uns32 PSIR_FileWriter::UpdateMemoryResources ( void** dataPtr ) { if ( this->fileParsed ) XMP_Throw ( "Not memory based", kXMPErr_EnforceFailure ); // Compute the size and allocate the new image resource block. XMP_Uns32 newLength = 0; InternalRsrcMap::iterator irPos = this->imgRsrcs.begin(); InternalRsrcMap::iterator irEnd = this->imgRsrcs.end(); for ( ; irPos != irEnd; ++irPos ) { // Add in the lengths for the 8BIM resources. const InternalRsrcInfo & rsrcInfo = irPos->second; newLength += 10; newLength += ((rsrcInfo.dataLen + 1) & 0xFFFFFFFEUL); if ( rsrcInfo.rsrcName == 0 ) { newLength += 2; } else { XMP_Uns32 nameLen = rsrcInfo.rsrcName[0]; newLength += ((nameLen + 2) & 0xFFFFFFFEUL); // ! Yes, +2. } } for ( size_t i = 0; i < this->otherRsrcs.size(); ++i ) { // Add in the non-8BIM resources. newLength += this->otherRsrcs[i].rsrcLength; } XMP_Uns8* newContent = (XMP_Uns8*) malloc ( newLength ); if ( newContent == 0 ) XMP_Throw ( "Out of memory", kXMPErr_NoMemory ); // Fill in the new image resource block. XMP_Uns8* rsrcPtr = newContent; for ( irPos = this->imgRsrcs.begin(); irPos != irEnd; ++irPos ) { // Do the 8BIM resources. const InternalRsrcInfo & rsrcInfo = irPos->second; PutUns32BE ( k8BIM, rsrcPtr ); rsrcPtr += 4; PutUns16BE ( rsrcInfo.id, rsrcPtr ); rsrcPtr += 2; if ( rsrcInfo.rsrcName == 0 ) { PutUns16BE ( 0, rsrcPtr ); rsrcPtr += 2; } else { XMP_Uns32 nameLen = rsrcInfo.rsrcName[0]; if ( (nameLen+1) > (newLength - (rsrcPtr - newContent)) ) { XMP_Throw ( "Buffer overrun", kXMPErr_InternalFailure ); } memcpy ( rsrcPtr, rsrcInfo.rsrcName, nameLen+1 ); // AUDIT: Protected by the above check. rsrcPtr += nameLen+1; if ( (nameLen & 1) == 0 ) { *rsrcPtr = 0; ++rsrcPtr; } } PutUns32BE ( rsrcInfo.dataLen, rsrcPtr ); rsrcPtr += 4; if ( rsrcInfo.dataLen > (newLength - (rsrcPtr - newContent)) ) { XMP_Throw ( "Buffer overrun", kXMPErr_InternalFailure ); } memcpy ( rsrcPtr, rsrcInfo.dataPtr, rsrcInfo.dataLen ); // AUDIT: Protected by the above check. rsrcPtr += rsrcInfo.dataLen; if ( (rsrcInfo.dataLen & 1) != 0 ) { // Pad to an even length if necessary. *rsrcPtr = 0; ++rsrcPtr; } } for ( size_t i = 0; i < this->otherRsrcs.size(); ++i ) { // Do the non-8BIM resources. XMP_Uns8* srcPtr = this->memContent + this->otherRsrcs[i].rsrcOffset; XMP_Uns32 srcLen = this->otherRsrcs[i].rsrcLength; if ( srcLen > (newLength - (rsrcPtr - newContent)) ) { XMP_Throw ( "Buffer overrun", kXMPErr_InternalFailure ); } memcpy ( rsrcPtr, srcPtr, srcLen ); // AUDIT: Protected by the above check. rsrcPtr += srcLen; // No need to pad, included in the original resource length. } XMP_Assert ( rsrcPtr == (newContent + newLength) ); // Parse the rebuilt image resource block. This is the easiest way to reconstruct the map. this->ParseMemoryResources ( newContent, newLength, false ); this->ownedContent = (newLength > 0); // ! We really do own the new content, if not empty. if ( dataPtr != 0 ) *dataPtr = newContent; return newLength; } // PSIR_FileWriter::UpdateMemoryResources