run:R W Run
54.21 KB
2026-03-11 16:18:51
R W Run
79.05 KB
2026-03-11 16:18:51
R W Run
1.36 KB
2026-03-11 16:18:51
R W Run
133.61 KB
2026-03-11 16:18:51
R W Run
26.5 KB
2026-03-11 16:18:51
R W Run
104.64 KB
2026-03-11 16:18:51
R W Run
164.97 KB
2026-03-11 16:18:51
R W Run
136.53 KB
2026-03-11 16:18:51
R W Run
38.46 KB
2026-03-11 16:18:51
R W Run
10.63 KB
2026-03-11 16:18:51
R W Run
19.23 KB
2026-03-11 16:18:51
R W Run
104.5 KB
2026-03-11 16:18:51
R W Run
42.74 KB
2026-03-11 16:18:51
R W Run
18.63 KB
2026-03-11 16:18:51
R W Run
14.7 KB
2026-03-11 16:18:51
R W Run
151.2 KB
2026-03-11 16:18:51
R W Run
11.75 KB
2026-03-11 16:18:51
R W Run
25.71 KB
2026-03-11 16:18:51
R W Run
error_log
📄module.tag.lyrics3.php
1<?php
2
3/////////////////////////////////////////////////////////////////
4/// getID3() by James Heinrich <info@getid3.org> //
5// available at https://github.com/JamesHeinrich/getID3 //
6// or https://www.getid3.org //
7// or http://getid3.sourceforge.net //
8// see readme.txt for more details //
9/////////////////////////////////////////////////////////////////
10/// //
11// module.tag.lyrics3.php //
12// module for analyzing Lyrics3 tags //
13// dependencies: module.tag.apetag.php (optional) //
14// ///
15/////////////////////////////////////////////////////////////////
16
17if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
18 exit;
19}
20class getid3_lyrics3 extends getid3_handler
21{
22 /**
23 * @return bool
24 */
25 public function Analyze() {
26 $info = &$this->getid3->info;
27
28 // http://www.volweb.cz/str/tags.htm
29
30 if (!getid3_lib::intValueSupported($info['filesize'])) {
31 $this->warning('Unable to check for Lyrics3 because file is larger than '.round(PHP_INT_MAX / 1073741824).'GB');
32 return false;
33 }
34
35 $this->fseek((0 - 128 - 9 - 6), SEEK_END); // end - ID3v1 - "LYRICSEND" - [Lyrics3size]
36 $lyrics3offset = null;
37 $lyrics3version = null;
38 $lyrics3size = null;
39 $lyrics3_id3v1 = $this->fread(128 + 9 + 6);
40 $lyrics3lsz = (int) substr($lyrics3_id3v1, 0, 6); // Lyrics3size
41 $lyrics3end = substr($lyrics3_id3v1, 6, 9); // LYRICSEND or LYRICS200
42 $id3v1tag = substr($lyrics3_id3v1, 15, 128); // ID3v1
43
44 if ($lyrics3end == 'LYRICSEND') {
45 // Lyrics3v1, ID3v1, no APE
46
47 $lyrics3size = 5100;
48 $lyrics3offset = $info['filesize'] - 128 - $lyrics3size;
49 $lyrics3version = 1;
50
51 } elseif ($lyrics3end == 'LYRICS200') {
52 // Lyrics3v2, ID3v1, no APE
53
54 // LSZ = lyrics + 'LYRICSBEGIN'; add 6-byte size field; add 'LYRICS200'
55 $lyrics3size = $lyrics3lsz + 6 + strlen('LYRICS200');
56 $lyrics3offset = $info['filesize'] - 128 - $lyrics3size;
57 $lyrics3version = 2;
58
59 } elseif (substr(strrev($lyrics3_id3v1), 0, 9) == strrev('LYRICSEND')) {
60 // Lyrics3v1, no ID3v1, no APE
61
62 $lyrics3size = 5100;
63 $lyrics3offset = $info['filesize'] - $lyrics3size;
64 $lyrics3version = 1;
65 $lyrics3offset = $info['filesize'] - $lyrics3size;
66
67 } elseif (substr(strrev($lyrics3_id3v1), 0, 9) == strrev('LYRICS200')) {
68
69 // Lyrics3v2, no ID3v1, no APE
70
71 $lyrics3size = (int) strrev(substr(strrev($lyrics3_id3v1), 9, 6)) + 6 + strlen('LYRICS200'); // LSZ = lyrics + 'LYRICSBEGIN'; add 6-byte size field; add 'LYRICS200'
72 $lyrics3offset = $info['filesize'] - $lyrics3size;
73 $lyrics3version = 2;
74
75 } else {
76
77 if (isset($info['ape']['tag_offset_start']) && ($info['ape']['tag_offset_start'] > 15)) {
78
79 $this->fseek($info['ape']['tag_offset_start'] - 15);
80 $lyrics3lsz = $this->fread(6);
81 $lyrics3end = $this->fread(9);
82
83 if ($lyrics3end == 'LYRICSEND') {
84 // Lyrics3v1, APE, maybe ID3v1
85
86 $lyrics3size = 5100;
87 $lyrics3offset = $info['ape']['tag_offset_start'] - $lyrics3size;
88 $info['avdataend'] = $lyrics3offset;
89 $lyrics3version = 1;
90 $this->warning('APE tag located after Lyrics3, will probably break Lyrics3 compatability');
91
92 } elseif ($lyrics3end == 'LYRICS200') {
93 // Lyrics3v2, APE, maybe ID3v1
94
95 $lyrics3size = $lyrics3lsz + 6 + strlen('LYRICS200'); // LSZ = lyrics + 'LYRICSBEGIN'; add 6-byte size field; add 'LYRICS200'
96 $lyrics3offset = $info['ape']['tag_offset_start'] - $lyrics3size;
97 $lyrics3version = 2;
98 $this->warning('APE tag located after Lyrics3, will probably break Lyrics3 compatability');
99
100 }
101
102 }
103
104 }
105
106 if (isset($lyrics3offset) && isset($lyrics3version) && isset($lyrics3size)) {
107 $info['avdataend'] = $lyrics3offset;
108 $this->getLyrics3Data($lyrics3offset, $lyrics3version, $lyrics3size);
109
110 if (!isset($info['ape'])) {
111 if (isset($info['lyrics3']['tag_offset_start'])) {
112 $GETID3_ERRORARRAY = &$info['warning'];
113 if ($this->getid3->option_tag_apetag) {
114 getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.tag.apetag.php', __FILE__, true);
115 $getid3_temp = new getID3();
116 $getid3_temp->openfile($this->getid3->filename, $this->getid3->info['filesize'], $this->getid3->fp);
117 $getid3_apetag = new getid3_apetag($getid3_temp);
118 $getid3_apetag->overrideendoffset = $info['lyrics3']['tag_offset_start'];
119 $getid3_apetag->Analyze();
120 if (!empty($getid3_temp->info['ape'])) {
121 $info['ape'] = $getid3_temp->info['ape'];
122 }
123 if (!empty($getid3_temp->info['replay_gain'])) {
124 $info['replay_gain'] = $getid3_temp->info['replay_gain'];
125 }
126 unset($getid3_temp, $getid3_apetag);
127 } else {
128 $this->warning('Unable to check for Lyrics3 and APE tags interaction since option_tag_apetag=FALSE');
129 }
130 } else {
131 $this->warning('Lyrics3 and APE tags appear to have become entangled (most likely due to updating the APE tags with a non-Lyrics3-aware tagger)');
132 }
133 }
134
135 }
136
137 return true;
138 }
139
140 /**
141 * @param int $endoffset
142 * @param int $version
143 * @param int $length
144 *
145 * @return bool
146 */
147 public function getLyrics3Data($endoffset, $version, $length) {
148 // http://www.volweb.cz/str/tags.htm
149
150 $info = &$this->getid3->info;
151
152 if (!getid3_lib::intValueSupported($endoffset)) {
153 $this->warning('Unable to check for Lyrics3 because file is larger than '.round(PHP_INT_MAX / 1073741824).'GB');
154 return false;
155 }
156
157 $this->fseek($endoffset);
158 if ($length <= 0) {
159 return false;
160 }
161 $rawdata = $this->fread($length);
162
163 $ParsedLyrics3 = array();
164
165 $ParsedLyrics3['raw']['lyrics3version'] = $version;
166 $ParsedLyrics3['raw']['lyrics3tagsize'] = $length;
167 $ParsedLyrics3['tag_offset_start'] = $endoffset;
168 $ParsedLyrics3['tag_offset_end'] = $endoffset + $length - 1;
169
170 if (substr($rawdata, 0, 11) != 'LYRICSBEGIN') {
171 if (strpos($rawdata, 'LYRICSBEGIN') !== false) {
172
173 $this->warning('"LYRICSBEGIN" expected at '.$endoffset.' but actually found at '.($endoffset + strpos($rawdata, 'LYRICSBEGIN')).' - this is invalid for Lyrics3 v'.$version);
174 $info['avdataend'] = $endoffset + strpos($rawdata, 'LYRICSBEGIN');
175 $rawdata = substr($rawdata, strpos($rawdata, 'LYRICSBEGIN'));
176 $length = strlen($rawdata);
177 $ParsedLyrics3['tag_offset_start'] = $info['avdataend'];
178 $ParsedLyrics3['raw']['lyrics3tagsize'] = $length;
179
180 } else {
181
182 $this->error('"LYRICSBEGIN" expected at '.$endoffset.' but found "'.substr($rawdata, 0, 11).'" instead');
183 return false;
184
185 }
186
187 }
188
189 switch ($version) {
190
191 case 1:
192 if (substr($rawdata, strlen($rawdata) - 9, 9) == 'LYRICSEND') {
193 $ParsedLyrics3['raw']['LYR'] = trim(substr($rawdata, 11, strlen($rawdata) - 11 - 9));
194 $this->Lyrics3LyricsTimestampParse($ParsedLyrics3);
195 } else {
196 $this->error('"LYRICSEND" expected at '.($this->ftell() - 11 + $length - 9).' but found "'.substr($rawdata, strlen($rawdata) - 9, 9).'" instead');
197 return false;
198 }
199 break;
200
201 case 2:
202 if (substr($rawdata, strlen($rawdata) - 9, 9) == 'LYRICS200') {
203 $ParsedLyrics3['raw']['unparsed'] = substr($rawdata, 11, strlen($rawdata) - 11 - 9 - 6); // LYRICSBEGIN + LYRICS200 + LSZ
204 $rawdata = $ParsedLyrics3['raw']['unparsed'];
205 while (strlen($rawdata) > 0) {
206 $fieldname = substr($rawdata, 0, 3);
207 $fieldsize = (int) substr($rawdata, 3, 5);
208 $ParsedLyrics3['raw'][$fieldname] = substr($rawdata, 8, $fieldsize);
209 $rawdata = substr($rawdata, 3 + 5 + $fieldsize);
210 }
211
212 if (isset($ParsedLyrics3['raw']['IND'])) {
213 $i = 0;
214 $flagnames = array('lyrics', 'timestamps', 'inhibitrandom');
215 foreach ($flagnames as $flagname) {
216 if (strlen($ParsedLyrics3['raw']['IND']) > $i++) {
217 $ParsedLyrics3['flags'][$flagname] = $this->IntString2Bool(substr($ParsedLyrics3['raw']['IND'], $i, 1 - 1));
218 }
219 }
220 }
221
222 $fieldnametranslation = array('ETT'=>'title', 'EAR'=>'artist', 'EAL'=>'album', 'INF'=>'comment', 'AUT'=>'author');
223 foreach ($fieldnametranslation as $key => $value) {
224 if (isset($ParsedLyrics3['raw'][$key])) {
225 $ParsedLyrics3['comments'][$value][] = trim($ParsedLyrics3['raw'][$key]);
226 }
227 }
228
229 if (isset($ParsedLyrics3['raw']['IMG'])) {
230 $imagestrings = explode("\r\n", $ParsedLyrics3['raw']['IMG']);
231 foreach ($imagestrings as $key => $imagestring) {
232 if (strpos($imagestring, '||') !== false) {
233 $imagearray = explode('||', $imagestring);
234 $ParsedLyrics3['images'][$key]['filename'] = $imagearray[0];
235 $ParsedLyrics3['images'][$key]['description'] = (isset($imagearray[1]) ? $imagearray[1] : '');
236 $ParsedLyrics3['images'][$key]['timestamp'] = $this->Lyrics3Timestamp2Seconds(isset($imagearray[2]) ? $imagearray[2] : '');
237 }
238 }
239 }
240 if (isset($ParsedLyrics3['raw']['LYR'])) {
241 $this->Lyrics3LyricsTimestampParse($ParsedLyrics3);
242 }
243 } else {
244 $this->error('"LYRICS200" expected at '.($this->ftell() - 11 + $length - 9).' but found "'.substr($rawdata, strlen($rawdata) - 9, 9).'" instead');
245 return false;
246 }
247 break;
248
249 default:
250 $this->error('Cannot process Lyrics3 version '.$version.' (only v1 and v2)');
251 return false;
252 }
253
254
255 if (isset($info['id3v1']['tag_offset_start']) && ($info['id3v1']['tag_offset_start'] <= $ParsedLyrics3['tag_offset_end'])) {
256 $this->warning('ID3v1 tag information ignored since it appears to be a false synch in Lyrics3 tag data');
257 unset($info['id3v1']);
258 foreach ($info['warning'] as $key => $value) {
259 if ($value == 'Some ID3v1 fields do not use NULL characters for padding') {
260 unset($info['warning'][$key]);
261 sort($info['warning']);
262 break;
263 }
264 }
265 }
266
267 $info['lyrics3'] = $ParsedLyrics3;
268
269 return true;
270 }
271
272 /**
273 * @param string $rawtimestamp
274 *
275 * @return int|false
276 */
277 public function Lyrics3Timestamp2Seconds($rawtimestamp) {
278 if (preg_match('#^\\[([0-9]{2}):([0-9]{2})\\]$#', $rawtimestamp, $regs)) {
279 return (int) (((int) $regs[1] * 60) + (int) $regs[2]);
280 }
281 return false;
282 }
283
284 /**
285 * @param array $Lyrics3data
286 *
287 * @return bool
288 */
289 public function Lyrics3LyricsTimestampParse(&$Lyrics3data) {
290 $lyricsarray = explode("\r\n", $Lyrics3data['raw']['LYR']);
291 $notimestamplyricsarray = array();
292 foreach ($lyricsarray as $key => $lyricline) {
293 $regs = array();
294 $thislinetimestamps = array();
295 while (preg_match('#^(\\[[0-9]{2}:[0-9]{2}\\])#', $lyricline, $regs)) {
296 $thislinetimestamps[] = $this->Lyrics3Timestamp2Seconds($regs[0]);
297 $lyricline = str_replace($regs[0], '', $lyricline);
298 }
299 $notimestamplyricsarray[$key] = $lyricline;
300 if (count($thislinetimestamps) > 0) {
301 sort($thislinetimestamps);
302 foreach ($thislinetimestamps as $timestampkey => $timestamp) {
303 if (isset($Lyrics3data['comments']['synchedlyrics'][$timestamp])) {
304 // timestamps only have a 1-second resolution, it's possible that multiple lines
305 // could have the same timestamp, if so, append
306 $Lyrics3data['comments']['synchedlyrics'][$timestamp] .= "\r\n".$lyricline;
307 } else {
308 $Lyrics3data['comments']['synchedlyrics'][$timestamp] = $lyricline;
309 }
310 }
311 }
312 }
313 $Lyrics3data['comments']['unsynchedlyrics'][0] = implode("\r\n", $notimestamplyricsarray);
314 if (isset($Lyrics3data['comments']['synchedlyrics']) && is_array($Lyrics3data['comments']['synchedlyrics'])) {
315 ksort($Lyrics3data['comments']['synchedlyrics']);
316 }
317 return true;
318 }
319
320 /**
321 * @param string $char
322 *
323 * @return bool|null
324 */
325 public function IntString2Bool($char) {
326 if ($char == '1') {
327 return true;
328 } elseif ($char == '0') {
329 return false;
330 }
331 return null;
332 }
333}
334
Ui Ux Design – Teachers Night Out

Get in Touch

© 2024 Teachers Night Out. All Rights Reserved.