luint ID3_Tag::Render( uchar *buffer ) { luint bytesUsed = 0; if ( buffer ) { ID3_Elem *cur = frameList; ID3_TagHeader header; SetVersion ( ID3_TAGVERSION, ID3_TAGREVISION ); header.SetVersion ( m_nVersion, m_nRevision ); bytesUsed += header.Size(); // set up the encryption and grouping IDs // ... while( cur ) { // PL // Check that frame has a valid FrameID if( ( cur->frame->GetID() <= 0 ) || (cur->frame->GetID() > ID3FID_CRYPTOREG )) { // TRACE( "Invalide FrameID\n" ); cur = cur->next; continue; } // End PL if ( cur->frame ) { cur->frame->compression = m_bCompression; cur->frame->SetVersion ( m_nVersion, m_nRevision ); bytesUsed += cur->frame->Render ( &buffer[ bytesUsed ] ); } cur = cur->next; } if ( m_bSyncOn ) { uchar *tempz; luint newTagSize; newTagSize = GetUnSyncSize ( &buffer[ header.Size() ], bytesUsed - header.Size() ); if ( newTagSize > 0 && ( newTagSize + header.Size() ) > bytesUsed ) { #ifdef _DEBUG // ASSERT( newTagSize < MAX_ALLOC ); // PL #endif if ( tempz = new uchar[ newTagSize ] ) { UnSync ( tempz, newTagSize, &buffer[ header.Size() ], bytesUsed - header.Size() ); header.SetFlags ( ID3HF_UNSYNC ); memcpy ( &buffer[ header.Size() ], tempz, newTagSize ); bytesUsed = newTagSize + header.Size(); delete[] tempz; } else ID3_THROW ( ID3E_NoMemory ); } } // zero the remainder of the buffer so that our // padding bytes are zero for ( luint i = 0; i < PaddingSize ( bytesUsed ); i++ ) buffer[ bytesUsed + i ] = 0; bytesUsed += PaddingSize ( bytesUsed ); header.SetDataSize ( bytesUsed - header.Size() ); header.Render ( buffer ); } else ID3_THROW ( ID3E_NoBuffer ); // set the flag which says that the tag hasn't changed m_bHasChanged = false; return bytesUsed; }
void ID3v2_Parse(const void* Ptr,size_t Len,pin* Pin,filepos_t Offset) { const uint8_t* Data = (const uint8_t*)Ptr; size_t Size = ID3v2_Query(Ptr,Len); uint8_t* Data_org=(const uint8_t*)Ptr; Data_org+=Size; // RETAILMSG(1, (TEXT(" ^^^^11111111111111111111^^^^^^^^ID3v2_Parse = %x , %x, %x \r\n"), Size,&Size,Data)); if (Size>0 && Pin) { int HeadFlag = Data[5]; int Ver = Data[3]; if (Ver >= 2 && Ver <= 4 && Size<=Len) { uint8_t* Tmp = NULL; // jump after header Data += 10; Size -= 10; if (Ver<4 && (HeadFlag & FLAG_UNSYNC)) { // undo unsync coding Tmp = malloc(Size); if (Tmp) { Size = UnSync(Tmp,Data,Size); Data = Tmp; } else return; } if ((HeadFlag & FLAG_EXTENDED) && Size>=4) { // skip extended header size_t n = (Ver>=4)?Read7Bit(Data,4):Read8Bit(Data,4); Data += 4+n; Size -= 4+n; } while (Data_org > Data ) { // parse frame uint8_t* Tmp = NULL; uint8_t* Tmp2 = NULL; const uint8_t* p; bool_t NeedDecompress = 0; bool_t NeedUnSync = 0; int Id = 0; int Len = 0; int Len2 = 0; int Flag = 0; const int* Info; if( Size <= 0 || Data[0]==0) break; switch (Ver) { case 2: if (Size >= 6) { Id = FOURCC(Data[0],Data[1],Data[2],' '); Len = Read8Bit(Data+3,3); Data += 6; Size -= 6; } break; case 3: if (Size >= 10) { Id = FOURCC(Data[0],Data[1],Data[2],Data[3]); Len = Read8Bit(Data+4,4); Flag = Read8Bit(Data+8,2); Data += 10; Size -= 10; if (Flag & FLAG3_UNKNOWN) Id = 0; if ((Flag & FLAG3_COMPRESSION) && Size>=4) { NeedDecompress = 1; Len2 = Read8Bit(Data,4); Data += 4; Size -= 4; } if ((Flag & FLAG3_GROUPID) && Size>=1) { Data++; Size--; } } break; case 4: if (Size >= 10) { Id = FOURCC(Data[0],Data[1],Data[2],Data[3]); Len = Read8Bit(Data+4,4); Flag = Read8Bit(Data+8,2); Data += 10; Size -= 10; if (Flag & FLAG4_UNKNOWN) Id = 0; if ((Flag & FLAG4_GROUPID) && Size>=1) { Data++; Size--; } if ((Flag & FLAG4_DATALENGTH) && Size>=4) { Len2 = Read8Bit(Data,4); Data += 4; Size -= 4; } if (Flag & FLAG4_COMPRESSION) NeedDecompress = 1; if (Flag & FLAG4_UNSYNC) NeedUnSync = 1; } break; } p = Data; Data += Len; Size -= Len; if (Id && Size>=0) for (Info=FrameInfo;Info[0];Info+=3) if (Info[0]==Id) { int n; tchar_t Value[512]; if (NeedUnSync) { Tmp = malloc(Len); if (!Tmp) break; Len = UnSync(Tmp,p,Len); p = Tmp; } if (NeedDecompress && Len2>0) { unsigned long n = Len2; Tmp2 = malloc(Len2); if (!Tmp2 || uncompress(Tmp2,&n,p,Len)!=Z_OK) break; Len = n; p = Tmp2; } switch (Info[2]) { case FIELD_STRING: if (Len>1) { ReadStrEncode(p+1,Len-1,p[0],Value,TSIZEOF(Value)); AddFieldStr(Pin,Info[1],Value); } break; case FIELD_COMMENT: if (Len>5) for (n=4;n<Len;++n) if (p[n]==0) { ReadStrEncode(p+n+1,Len-n-1,p[0],Value,TSIZEOF(Value)); AddFieldStr(Pin,Info[1],Value); break; } break; case FIELD_APIC: if (Len>5) { int Encode = *(p++); --Len; if (Ver==2) { tcscpy_s(Value,TSIZEOF(Value),T("image/")); GetAsciiToken(Value+tcslen(Value),TSIZEOF(Value)-tcslen(Value),(const char*)p,3); Len -= 3; p += 3; if (tcsicmp(Value,T("image/jpg"))==0) tcscpy_s(Value,TSIZEOF(Value),T("image/jpeg")); } else { n = ReadStrEncode(p,Len,Encode,Value,TSIZEOF(Value)); Len -= n; p += n; } ++p; --Len; n = ReadStrEncode(p,Len,Encode,NULL,0); // skip description Len -= n; p += n; AddFieldAttachment(Pin,COMMENT_COVER,(p-(const uint8_t*)Ptr)+Offset,Len,Value); } break; } break; } free(Tmp); free(Tmp2); } free(Tmp); } } }