ILIAS  release_5-0 Revision 5.0.0-1144-gc4397b1f870
getid3_apetag Class Reference

getID3() by James Heinrich info@.nosp@m.geti.nosp@m.d3.or.nosp@m.g // More...

+ Collaboration diagram for getid3_apetag:

Public Member Functions

 getid3_apetag (&$fd, &$ThisFileInfo, $overrideendoffset=0)
 
 parseAPEheaderFooter ($APEheaderFooterData)
 
 parseAPEtagFlags ($rawflagint)
 
 APEcontentTypeFlagLookup ($contenttypeid)
 
 APEtagItemIsUTF8Lookup ($itemkey)
 

Detailed Description

getID3() by James Heinrich info@.nosp@m.geti.nosp@m.d3.or.nosp@m.g //

Definition at line 16 of file module.tag.apetag.php.

Member Function Documentation

◆ APEcontentTypeFlagLookup()

getid3_apetag::APEcontentTypeFlagLookup (   $contenttypeid)

Definition at line 243 of file module.tag.apetag.php.

243 {
244 static $APEcontentTypeFlagLookup = array(
245 0 => 'utf-8',
246 1 => 'binary',
247 2 => 'external',
248 3 => 'reserved'
249 );
250 return (isset($APEcontentTypeFlagLookup[$contenttypeid]) ? $APEcontentTypeFlagLookup[$contenttypeid] : 'invalid');
251 }

Referenced by parseAPEtagFlags().

+ Here is the caller graph for this function:

◆ APEtagItemIsUTF8Lookup()

getid3_apetag::APEtagItemIsUTF8Lookup (   $itemkey)

Definition at line 253 of file module.tag.apetag.php.

253 {
254 static $APEtagItemIsUTF8Lookup = array(
255 'title',
256 'subtitle',
257 'artist',
258 'album',
259 'debut album',
260 'publisher',
261 'conductor',
262 'track',
263 'composer',
264 'comment',
265 'copyright',
266 'publicationright',
267 'file',
268 'year',
269 'record date',
270 'record location',
271 'genre',
272 'media',
273 'related',
274 'isrc',
275 'abstract',
276 'language',
277 'bibliography'
278 );
279 return in_array(strtolower($itemkey), $APEtagItemIsUTF8Lookup);
280 }

◆ getid3_apetag()

getid3_apetag::getid3_apetag ( $fd,
$ThisFileInfo,
  $overrideendoffset = 0 
)

Definition at line 19 of file module.tag.apetag.php.

19 {
20 $id3v1tagsize = 128;
21 $apetagheadersize = 32;
22 $lyrics3tagsize = 10;
23
24 if ($overrideendoffset == 0) {
25
26 fseek($fd, 0 - $id3v1tagsize - $apetagheadersize - $lyrics3tagsize, SEEK_END);
27 $APEfooterID3v1 = fread($fd, $id3v1tagsize + $apetagheadersize + $lyrics3tagsize);
28
29 //if (preg_match('/APETAGEX.{24}TAG.{125}$/i', $APEfooterID3v1)) {
30 if (substr($APEfooterID3v1, strlen($APEfooterID3v1) - $id3v1tagsize - $apetagheadersize, 8) == 'APETAGEX') {
31
32 // APE tag found before ID3v1
33 $ThisFileInfo['ape']['tag_offset_end'] = $ThisFileInfo['filesize'] - $id3v1tagsize;
34
35 //} elseif (preg_match('/APETAGEX.{24}$/i', $APEfooterID3v1)) {
36 } elseif (substr($APEfooterID3v1, strlen($APEfooterID3v1) - $apetagheadersize, 8) == 'APETAGEX') {
37
38 // APE tag found, no ID3v1
39 $ThisFileInfo['ape']['tag_offset_end'] = $ThisFileInfo['filesize'];
40
41 }
42
43 } else {
44
45 fseek($fd, $overrideendoffset - $apetagheadersize, SEEK_SET);
46 if (fread($fd, 8) == 'APETAGEX') {
47 $ThisFileInfo['ape']['tag_offset_end'] = $overrideendoffset;
48 }
49
50 }
51 if (!isset($ThisFileInfo['ape']['tag_offset_end'])) {
52
53 // APE tag not found
54 unset($ThisFileInfo['ape']);
55 return false;
56
57 }
58
59 // shortcut
60 $thisfile_ape = &$ThisFileInfo['ape'];
61
62 fseek($fd, $thisfile_ape['tag_offset_end'] - $apetagheadersize, SEEK_SET);
63 $APEfooterData = fread($fd, 32);
64 if (!($thisfile_ape['footer'] = $this->parseAPEheaderFooter($APEfooterData))) {
65 $ThisFileInfo['error'][] = 'Error parsing APE footer at offset '.$thisfile_ape['tag_offset_end'];
66 return false;
67 }
68
69 if (isset($thisfile_ape['footer']['flags']['header']) && $thisfile_ape['footer']['flags']['header']) {
70 fseek($fd, $thisfile_ape['tag_offset_end'] - $thisfile_ape['footer']['raw']['tagsize'] - $apetagheadersize, SEEK_SET);
71 $thisfile_ape['tag_offset_start'] = ftell($fd);
72 $APEtagData = fread($fd, $thisfile_ape['footer']['raw']['tagsize'] + $apetagheadersize);
73 } else {
74 $thisfile_ape['tag_offset_start'] = $thisfile_ape['tag_offset_end'] - $thisfile_ape['footer']['raw']['tagsize'];
75 fseek($fd, $thisfile_ape['tag_offset_start'], SEEK_SET);
76 $APEtagData = fread($fd, $thisfile_ape['footer']['raw']['tagsize']);
77 }
78 $ThisFileInfo['avdataend'] = $thisfile_ape['tag_offset_start'];
79
80 if (isset($ThisFileInfo['id3v1']['tag_offset_start']) && ($ThisFileInfo['id3v1']['tag_offset_start'] < $thisfile_ape['tag_offset_end'])) {
81 $ThisFileInfo['warning'][] = 'ID3v1 tag information ignored since it appears to be a false synch in APEtag data';
82 unset($ThisFileInfo['id3v1']);
83 foreach ($ThisFileInfo['warning'] as $key => $value) {
84 if ($value == 'Some ID3v1 fields do not use NULL characters for padding') {
85 unset($ThisFileInfo['warning'][$key]);
86 sort($ThisFileInfo['warning']);
87 break;
88 }
89 }
90 }
91
92 $offset = 0;
93 if (isset($thisfile_ape['footer']['flags']['header']) && $thisfile_ape['footer']['flags']['header']) {
94 if ($thisfile_ape['header'] = $this->parseAPEheaderFooter(substr($APEtagData, 0, $apetagheadersize))) {
95 $offset += $apetagheadersize;
96 } else {
97 $ThisFileInfo['error'][] = 'Error parsing APE header at offset '.$thisfile_ape['tag_offset_start'];
98 return false;
99 }
100 }
101
102 // shortcut
103 $ThisFileInfo['replay_gain'] = array();
104 $thisfile_replaygain = &$ThisFileInfo['replay_gain'];
105
106 for ($i = 0; $i < $thisfile_ape['footer']['raw']['tag_items']; $i++) {
107 $value_size = getid3_lib::LittleEndian2Int(substr($APEtagData, $offset, 4));
108 $offset += 4;
109 $item_flags = getid3_lib::LittleEndian2Int(substr($APEtagData, $offset, 4));
110 $offset += 4;
111 if (strstr(substr($APEtagData, $offset), "\x00") === false) {
112 $ThisFileInfo['error'][] = 'Cannot find null-byte (0x00) seperator between ItemKey #'.$i.' and value. ItemKey starts '.$offset.' bytes into the APE tag, at file offset '.($thisfile_ape['tag_offset_start'] + $offset);
113 return false;
114 }
115 $ItemKeyLength = strpos($APEtagData, "\x00", $offset) - $offset;
116 $item_key = strtolower(substr($APEtagData, $offset, $ItemKeyLength));
117
118 // shortcut
119 $thisfile_ape['items'][$item_key] = array();
120 $thisfile_ape_items_current = &$thisfile_ape['items'][$item_key];
121
122 $offset += ($ItemKeyLength + 1); // skip 0x00 terminator
123 $thisfile_ape_items_current['data'] = substr($APEtagData, $offset, $value_size);
124 $offset += $value_size;
125
126 $thisfile_ape_items_current['flags'] = $this->parseAPEtagFlags($item_flags);
127 switch ($thisfile_ape_items_current['flags']['item_contents_raw']) {
128 case 0: // UTF-8
129 case 3: // Locator (URL, filename, etc), UTF-8 encoded
130 $thisfile_ape_items_current['data'] = explode("\x00", trim($thisfile_ape_items_current['data']));
131 break;
132
133 default: // binary data
134 break;
135 }
136
137 switch (strtolower($item_key)) {
138 case 'replaygain_track_gain':
139 $thisfile_replaygain['track']['adjustment'] = (float) str_replace(',', '.', $thisfile_ape_items_current['data'][0]); // float casting will see "0,95" as zero!
140 $thisfile_replaygain['track']['originator'] = 'unspecified';
141 break;
142
143 case 'replaygain_track_peak':
144 $thisfile_replaygain['track']['peak'] = (float) str_replace(',', '.', $thisfile_ape_items_current['data'][0]); // float casting will see "0,95" as zero!
145 $thisfile_replaygain['track']['originator'] = 'unspecified';
146 if ($thisfile_replaygain['track']['peak'] <= 0) {
147 $ThisFileInfo['warning'][] = 'ReplayGain Track peak from APEtag appears invalid: '.$thisfile_replaygain['track']['peak'].' (original value = "'.$thisfile_ape_items_current['data'][0].'")';
148 }
149 break;
150
151 case 'replaygain_album_gain':
152 $thisfile_replaygain['album']['adjustment'] = (float) str_replace(',', '.', $thisfile_ape_items_current['data'][0]); // float casting will see "0,95" as zero!
153 $thisfile_replaygain['album']['originator'] = 'unspecified';
154 break;
155
156 case 'replaygain_album_peak':
157 $thisfile_replaygain['album']['peak'] = (float) str_replace(',', '.', $thisfile_ape_items_current['data'][0]); // float casting will see "0,95" as zero!
158 $thisfile_replaygain['album']['originator'] = 'unspecified';
159 if ($thisfile_replaygain['album']['peak'] <= 0) {
160 $ThisFileInfo['warning'][] = 'ReplayGain Album peak from APEtag appears invalid: '.$thisfile_replaygain['album']['peak'].' (original value = "'.$thisfile_ape_items_current['data'][0].'")';
161 }
162 break;
163
164 case 'mp3gain_undo':
165 list($mp3gain_undo_left, $mp3gain_undo_right, $mp3gain_undo_wrap) = explode(',', $thisfile_ape_items_current['data'][0]);
166 $thisfile_replaygain['mp3gain']['undo_left'] = intval($mp3gain_undo_left);
167 $thisfile_replaygain['mp3gain']['undo_right'] = intval($mp3gain_undo_right);
168 $thisfile_replaygain['mp3gain']['undo_wrap'] = (($mp3gain_undo_wrap == 'Y') ? true : false);
169 break;
170
171 case 'mp3gain_minmax':
172 list($mp3gain_globalgain_min, $mp3gain_globalgain_max) = explode(',', $thisfile_ape_items_current['data'][0]);
173 $thisfile_replaygain['mp3gain']['globalgain_track_min'] = intval($mp3gain_globalgain_min);
174 $thisfile_replaygain['mp3gain']['globalgain_track_max'] = intval($mp3gain_globalgain_max);
175 break;
176
177 case 'mp3gain_album_minmax':
178 list($mp3gain_globalgain_album_min, $mp3gain_globalgain_album_max) = explode(',', $thisfile_ape_items_current['data'][0]);
179 $thisfile_replaygain['mp3gain']['globalgain_album_min'] = intval($mp3gain_globalgain_album_min);
180 $thisfile_replaygain['mp3gain']['globalgain_album_max'] = intval($mp3gain_globalgain_album_max);
181 break;
182
183 case 'tracknumber':
184 foreach ($thisfile_ape_items_current['data'] as $comment) {
185 $thisfile_ape['comments']['track'][] = $comment;
186 }
187 break;
188
189 default:
190 foreach ($thisfile_ape_items_current['data'] as $comment) {
191 $thisfile_ape['comments'][strtolower($item_key)][] = $comment;
192 }
193 break;
194 }
195
196 }
197 if (empty($thisfile_replaygain)) {
198 unset($ThisFileInfo['replay_gain']);
199 }
200
201 return true;
202 }
$comment
Definition: buildRTE.php:83
parseAPEheaderFooter($APEheaderFooterData)
parseAPEtagFlags($rawflagint)
LittleEndian2Int($byteword, $signed=false)
Definition: getid3.lib.php:266

References $comment, getid3_lib\LittleEndian2Int(), parseAPEheaderFooter(), and parseAPEtagFlags().

+ Here is the call graph for this function:

◆ parseAPEheaderFooter()

getid3_apetag::parseAPEheaderFooter (   $APEheaderFooterData)

Definition at line 204 of file module.tag.apetag.php.

204 {
205 // http://www.uni-jena.de/~pfk/mpp/sv8/apeheader.html
206
207 // shortcut
208 $headerfooterinfo['raw'] = array();
209 $headerfooterinfo_raw = &$headerfooterinfo['raw'];
210
211 $headerfooterinfo_raw['footer_tag'] = substr($APEheaderFooterData, 0, 8);
212 if ($headerfooterinfo_raw['footer_tag'] != 'APETAGEX') {
213 return false;
214 }
215 $headerfooterinfo_raw['version'] = getid3_lib::LittleEndian2Int(substr($APEheaderFooterData, 8, 4));
216 $headerfooterinfo_raw['tagsize'] = getid3_lib::LittleEndian2Int(substr($APEheaderFooterData, 12, 4));
217 $headerfooterinfo_raw['tag_items'] = getid3_lib::LittleEndian2Int(substr($APEheaderFooterData, 16, 4));
218 $headerfooterinfo_raw['global_flags'] = getid3_lib::LittleEndian2Int(substr($APEheaderFooterData, 20, 4));
219 $headerfooterinfo_raw['reserved'] = substr($APEheaderFooterData, 24, 8);
220
221 $headerfooterinfo['tag_version'] = $headerfooterinfo_raw['version'] / 1000;
222 if ($headerfooterinfo['tag_version'] >= 2) {
223 $headerfooterinfo['flags'] = $this->parseAPEtagFlags($headerfooterinfo_raw['global_flags']);
224 }
225 return $headerfooterinfo;
226 }

References getid3_lib\LittleEndian2Int(), and parseAPEtagFlags().

Referenced by getid3_apetag().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ parseAPEtagFlags()

getid3_apetag::parseAPEtagFlags (   $rawflagint)

Definition at line 228 of file module.tag.apetag.php.

228 {
229 // "Note: APE Tags 1.0 do not use any of the APE Tag flags.
230 // All are set to zero on creation and ignored on reading."
231 // http://www.uni-jena.de/~pfk/mpp/sv8/apetagflags.html
232 $flags['header'] = (bool) ($rawflagint & 0x80000000);
233 $flags['footer'] = (bool) ($rawflagint & 0x40000000);
234 $flags['this_is_header'] = (bool) ($rawflagint & 0x20000000);
235 $flags['item_contents_raw'] = ($rawflagint & 0x00000006) >> 1;
236 $flags['read_only'] = (bool) ($rawflagint & 0x00000001);
237
238 $flags['item_contents'] = $this->APEcontentTypeFlagLookup($flags['item_contents_raw']);
239
240 return $flags;
241 }
APEcontentTypeFlagLookup($contenttypeid)

References APEcontentTypeFlagLookup().

Referenced by getid3_apetag(), and parseAPEheaderFooter().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

The documentation for this class was generated from the following file: