id3_header_frame.cpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. // The authors have released ID3Lib as Public Domain (PD) and claim no copyright,
  2. // patent or other intellectual property protection in this work. This means that
  3. // it may be modified, redistributed and used in commercial and non-commercial
  4. // software and hardware without restrictions. ID3Lib is distributed on an "AS IS"
  5. // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
  6. //
  7. // The ID3Lib authors encourage improvements and optimisations to be sent to the
  8. // ID3Lib coordinator, currently Dirk Mahoney ([email protected]). Approved
  9. // submissions may be altered, and will be included and released under these terms.
  10. //
  11. // Mon Nov 23 18:34:01 1998
  12. #include <string.h>
  13. #include <memory.h>
  14. #include "id3_header_frame.h"
  15. #include "id3_error.h"
  16. bool ID3_FrameAttr::HasDataLength(int version)
  17. {
  18. if (version == 4)
  19. return !!(flags & ID3FL_DATA_LENGTH_2_4);
  20. else
  21. return 0;
  22. }
  23. bool ID3_FrameAttr::HasCompression(int version)
  24. {
  25. if (version == 4)
  26. return !!(flags & ID3FL_COMPRESSION_2_4);
  27. else
  28. return !!(flags & ID3FL_COMPRESSION_2_3);
  29. }
  30. bool ID3_FrameAttr::HasEncryption(int version)
  31. {
  32. if (version == 4)
  33. return !!(flags & ID3FL_ENCRYPTION_2_4);
  34. else
  35. return !!(flags & ID3FL_ENCRYPTION_2_3);
  36. }
  37. bool ID3_FrameAttr::HasGrouping(int version)
  38. {
  39. if (version == 4)
  40. return !!(flags & ID3FL_GROUPING_2_4);
  41. else
  42. return !!(flags & ID3FL_GROUPING_2_3);
  43. }
  44. bool ID3_FrameAttr::HasUnsync(int version)
  45. {
  46. if (version == 4)
  47. return !!(flags & ID3FL_UNSYNC_2_4);
  48. else
  49. return false;
  50. }
  51. void ID3_FrameAttr::ClearUnSync(int version)
  52. {
  53. if (version == 4)
  54. flags&= ~ID3FL_UNSYNC_2_4;
  55. }
  56. void ID3_FrameAttr::SetFlags(luint _flags)
  57. {
  58. flags = _flags;
  59. }
  60. void ID3_FrameHeader::SetFrameID (ID3_FrameID id)
  61. {
  62. frameID = id;
  63. }
  64. luint ID3_FrameHeader::Size(void)
  65. {
  66. if (!info)
  67. return 0;
  68. return info->frameIDBytes + info->frameSizeBytes + info->frameFlagsBytes;
  69. }
  70. // TODO: benski> we should make a return value of 0 mean 'error'
  71. luint ID3_FrameHeader::GetFrameInfo(ID3_FrameAttr &attr, const uchar *buffer, size_t remSize)
  72. {
  73. luint posn = 0;
  74. luint i = 0, bpos = 4;
  75. // verify that the text is all between A-Z and 0-9 (for TALB and TIT2, etc)
  76. for (i = 0; i < 4; i++)
  77. {
  78. if (!((buffer[i] >= '0' && buffer[i] <= '9') || (buffer[i] >= 'A' && buffer[i] <= 'Z')))
  79. {
  80. // TODO: benski> return an error here
  81. // this helps us to get ID3v2.2 PIC frames without
  82. // breaking others since it's not null-terminated!
  83. bpos = i;
  84. }
  85. }
  86. memcpy(attr.textID, (char *) buffer, (bpos > 0 && bpos <= 4 ? bpos : 4));
  87. if (bpos == 3) attr.textID[3] = 0;
  88. attr.textID[4] = 0;
  89. posn += info->frameIDBytes;
  90. attr.size = 0;
  91. for (i = 0; i < info->frameSizeBytes; i++)
  92. attr.size |= buffer[posn + i] << ((info->frameSizeBytes - 1 - i) * 8);
  93. if (version == 4) // 2.4 uses syncsafe sizes
  94. {
  95. // many programs write non-syncsafe sizes anyway (iTunes is the biggest culprit)
  96. // so we'll try to detect it. unfortunately this isn't foolproof
  97. int mask = attr.size & 0x80808080;
  98. if (!quirks.id3v2_4_itunes_bug // make sure we've havn't previously identified that this tag has a problem
  99. && mask == 0) // if none of the 'reserved' bits are set
  100. {
  101. attr.size = int28().setFromFile(attr.size).get(); // convert to syncsafe value
  102. }
  103. else
  104. {
  105. // benski> cut for now. this can't be trusted because it applies on subsequent re-parses but not anything before this
  106. // quirks.id3v2_4_itunes_bug = true; // mark that the tag has a problem
  107. }
  108. // TODO: it'd be nice to look ahead into the buffer and make sure that our calculated size
  109. // lets us land on the start of a new frame
  110. // although that isn't foolproof either (non-standard fields, etc)
  111. }
  112. posn += info->frameSizeBytes;
  113. luint flags=0;
  114. flags = 0;
  115. for (i = 0; i < info->frameFlagsBytes; i++)
  116. flags |= buffer[ posn + i ] << ((info->frameFlagsBytes - 1 - i) * 8);
  117. attr.SetFlags(flags);
  118. posn += info->frameFlagsBytes;
  119. return posn;
  120. }
  121. luint ID3_FrameHeader::Render(uchar *buffer)
  122. {
  123. luint bytesUsed = 0;
  124. ID3_FrameDef *frameDef = NULL;
  125. char *textID = NULL;
  126. luint i;
  127. if (frameDef = ID3_FindFrameDef(frameID))
  128. {
  129. if (info->frameIDBytes < strlen (frameDef->longTextID))
  130. textID = frameDef->shortTextID;
  131. else
  132. textID = frameDef->longTextID;
  133. }
  134. else
  135. ID3_THROW (ID3E_InvalidFrameID);
  136. memcpy (&buffer[ bytesUsed ], (uchar *) textID, info->frameIDBytes);
  137. bytesUsed += info->frameIDBytes;
  138. for (i = 0; i < info->frameSizeBytes; i++)
  139. {
  140. if (version==4) // 2.4 uses syncsafe sizes
  141. buffer[ bytesUsed + i ] = (uchar) ((dataSize >> ((info->frameSizeBytes - i - 1) * 7)) & 0x7F);
  142. else
  143. buffer[ bytesUsed + i ] = (uchar) ((dataSize >> ((info->frameSizeBytes - i - 1) * 8)) & 0xFF);
  144. }
  145. bytesUsed += info->frameSizeBytes;
  146. for (i = 0; i < info->frameFlagsBytes; i++)
  147. buffer[ bytesUsed + i ] = (uchar) ((flags >> ((info->frameFlagsBytes - i - 1) * 8)) & 0xFF);
  148. bytesUsed += info->frameFlagsBytes;
  149. return bytesUsed;
  150. }