source: branches/MootoolsFileManager-Update/plugins/MootoolsFileManager/mootools-filemanager/Assets/Connector/Assets/getid3/getid3.lib.php @ 1302

Last change on this file since 1302 was 1302, checked in by gogo, 9 years ago

Updates to http://www.github.com/sleemanj/mootools-filemanager from GerHoblett?

http://www.github.com/GerHoblett/

Changes to said updates by gogo (sleemanj @ github)

Modifications to MootoolsFileManager? to work with those updates, some courtesy of GerHoblett?, some sleemanj

GerHoblett? provided a large diff which accomplished the goal in a quite different way. It has merit, however I have opted for a less-affecting path in so far as Xinha's "way" is concerned, namely, not splitting the config for a single plugin into several calls to backend config passing functions which seemed a little cumbersome.

Instead I take the option of using POST to send backend data around, at the minor expense of an extra round trip when displaying thumbnails (for each one). This could be reduced by checking for thumbnail existence and returning the thumbnail name directly in "onView" rather than the backend request to generate said thumbnail.

Still to do, is to make the preview pane thumbnail also work.


File size: 38.8 KB
Line 
1<?php
2/////////////////////////////////////////////////////////////////
3/// getID3() by James Heinrich <info@getid3.org>               //
4//  available at http://getid3.sourceforge.net                 //
5//            or http://www.getid3.org                         //
6/////////////////////////////////////////////////////////////////
7//                                                             //
8// getid3.lib.php - part of getID3()                           //
9// See readme.txt for more details                             //
10//                                                            ///
11/////////////////////////////////////////////////////////////////
12
13
14class getid3_lib
15{
16
17        static function PrintHexBytes($string, $hex=true, $spaces=true, $htmlsafe=true) {
18                $returnstring = '';
19                for ($i = 0; $i < strlen($string); $i++) {
20                        if ($hex) {
21                                $returnstring .= str_pad(dechex(ord($string{$i})), 2, '0', STR_PAD_LEFT);
22                        } else {
23                                $returnstring .= ' '.(preg_match("#[\x20-\x7E]#", $string{$i}) ? $string{$i} : '€');
24                        }
25                        if ($spaces) {
26                                $returnstring .= ' ';
27                        }
28                }
29                if ($htmlsafe) {
30                        $returnstring = htmlentities($returnstring);
31                }
32                return $returnstring;
33        }
34
35        static function trunc($floatnumber) {
36                // truncates a floating-point number at the decimal point
37                // returns int (if possible, otherwise float)
38                if ($floatnumber >= 1) {
39                        $truncatednumber = floor($floatnumber);
40                } elseif ($floatnumber <= -1) {
41                        $truncatednumber = ceil($floatnumber);
42                } else {
43                        $truncatednumber = 0;
44                }
45                if (getid3_lib::intValueSupported($truncatednumber)) {
46                        $truncatednumber = (int) $truncatednumber;
47                }
48                return $truncatednumber;
49        }
50
51
52        static function safe_inc(&$variable, $increment=1) {
53                if (isset($variable)) {
54                        $variable += $increment;
55                } else {
56                        $variable = $increment;
57                }
58                return true;
59        }
60
61        static function CastAsInt($floatnum) {
62                // convert to float if not already
63                $floatnum = (float) $floatnum;
64
65                // convert a float to type int, only if possible
66                if (getid3_lib::trunc($floatnum) == $floatnum) {
67                        // it's not floating point
68                        if (getid3_lib::intValueSupported($floatnum)) {
69                                // it's within int range
70                                $floatnum = (int) $floatnum;
71                        }
72                }
73                return $floatnum;
74        }
75
76        public static function intValueSupported($num) {
77                // check if integers are 64-bit
78                static $hasINT64 = null;
79                if ($hasINT64 === null) { // 10x faster than is_null()
80                        $hasINT64 = is_int(pow(2, 31)); // 32-bit int are limited to (2^31)-1
81                        if (!$hasINT64 && !defined('PHP_INT_MIN')) {
82                                define('PHP_INT_MIN', ~PHP_INT_MAX);
83                        }
84                }
85                // if integers are 64-bit - no other check required
86                if ($hasINT64 || (($num <= PHP_INT_MAX) && ($num >= PHP_INT_MIN))) {
87                        return true;
88                }
89                return false;
90        }
91
92        static function DecimalizeFraction($fraction) {
93                list($numerator, $denominator) = explode('/', $fraction);
94                return $numerator / ($denominator ? $denominator : 1);
95        }
96
97
98        static function DecimalBinary2Float($binarynumerator) {
99                $numerator   = getid3_lib::Bin2Dec($binarynumerator);
100                $denominator = getid3_lib::Bin2Dec('1'.str_repeat('0', strlen($binarynumerator)));
101                return ($numerator / $denominator);
102        }
103
104
105        static function NormalizeBinaryPoint($binarypointnumber, $maxbits=52) {
106                // http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/binary.html
107                if (strpos($binarypointnumber, '.') === false) {
108                        $binarypointnumber = '0.'.$binarypointnumber;
109                } elseif ($binarypointnumber{0} == '.') {
110                        $binarypointnumber = '0'.$binarypointnumber;
111                }
112                $exponent = 0;
113                while (($binarypointnumber{0} != '1') || (substr($binarypointnumber, 1, 1) != '.')) {
114                        if (substr($binarypointnumber, 1, 1) == '.') {
115                                $exponent--;
116                                $binarypointnumber = substr($binarypointnumber, 2, 1).'.'.substr($binarypointnumber, 3);
117                        } else {
118                                $pointpos = strpos($binarypointnumber, '.');
119                                $exponent += ($pointpos - 1);
120                                $binarypointnumber = str_replace('.', '', $binarypointnumber);
121                                $binarypointnumber = $binarypointnumber{0}.'.'.substr($binarypointnumber, 1);
122                        }
123                }
124                $binarypointnumber = str_pad(substr($binarypointnumber, 0, $maxbits + 2), $maxbits + 2, '0', STR_PAD_RIGHT);
125                return array('normalized'=>$binarypointnumber, 'exponent'=>(int) $exponent);
126        }
127
128
129        static function Float2BinaryDecimal($floatvalue) {
130                // http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/binary.html
131                $maxbits = 128; // to how many bits of precision should the calculations be taken?
132                $intpart   = getid3_lib::trunc($floatvalue);
133                $floatpart = abs($floatvalue - $intpart);
134                $pointbitstring = '';
135                while (($floatpart != 0) && (strlen($pointbitstring) < $maxbits)) {
136                        $floatpart *= 2;
137                        $pointbitstring .= (string) getid3_lib::trunc($floatpart);
138                        $floatpart -= getid3_lib::trunc($floatpart);
139                }
140                $binarypointnumber = decbin($intpart).'.'.$pointbitstring;
141                return $binarypointnumber;
142        }
143
144
145        static function Float2String($floatvalue, $bits) {
146                // http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/ieee-expl.html
147                switch ($bits) {
148                        case 32:
149                                $exponentbits = 8;
150                                $fractionbits = 23;
151                                break;
152
153                        case 64:
154                                $exponentbits = 11;
155                                $fractionbits = 52;
156                                break;
157
158                        default:
159                                return false;
160                                break;
161                }
162                if ($floatvalue >= 0) {
163                        $signbit = '0';
164                } else {
165                        $signbit = '1';
166                }
167                $normalizedbinary  = getid3_lib::NormalizeBinaryPoint(getid3_lib::Float2BinaryDecimal($floatvalue), $fractionbits);
168                $biasedexponent    = pow(2, $exponentbits - 1) - 1 + $normalizedbinary['exponent']; // (127 or 1023) +/- exponent
169                $exponentbitstring = str_pad(decbin($biasedexponent), $exponentbits, '0', STR_PAD_LEFT);
170                $fractionbitstring = str_pad(substr($normalizedbinary['normalized'], 2), $fractionbits, '0', STR_PAD_RIGHT);
171
172                return getid3_lib::BigEndian2String(getid3_lib::Bin2Dec($signbit.$exponentbitstring.$fractionbitstring), $bits % 8, false);
173        }
174
175
176        static function LittleEndian2Float($byteword) {
177                return getid3_lib::BigEndian2Float(strrev($byteword));
178        }
179
180
181        static function BigEndian2Float($byteword) {
182                // ANSI/IEEE Standard 754-1985, Standard for Binary Floating Point Arithmetic
183                // http://www.psc.edu/general/software/packages/ieee/ieee.html
184                // http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/ieee.html
185
186                $bitword = getid3_lib::BigEndian2Bin($byteword);
187                if (!$bitword) {
188                        return 0;
189                }
190                $signbit = $bitword{0};
191
192                switch (strlen($byteword) * 8) {
193                        case 32:
194                                $exponentbits = 8;
195                                $fractionbits = 23;
196                                break;
197
198                        case 64:
199                                $exponentbits = 11;
200                                $fractionbits = 52;
201                                break;
202
203                        case 80:
204                                // 80-bit Apple SANE format
205                                // http://www.mactech.com/articles/mactech/Vol.06/06.01/SANENormalized/
206                                $exponentstring = substr($bitword, 1, 15);
207                                $isnormalized = intval($bitword{16});
208                                $fractionstring = substr($bitword, 17, 63);
209                                $exponent = pow(2, getid3_lib::Bin2Dec($exponentstring) - 16383);
210                                $fraction = $isnormalized + getid3_lib::DecimalBinary2Float($fractionstring);
211                                $floatvalue = $exponent * $fraction;
212                                if ($signbit == '1') {
213                                        $floatvalue *= -1;
214                                }
215                                return $floatvalue;
216                                break;
217
218                        default:
219                                return false;
220                                break;
221                }
222                $exponentstring = substr($bitword, 1, $exponentbits);
223                $fractionstring = substr($bitword, $exponentbits + 1, $fractionbits);
224                $exponent = getid3_lib::Bin2Dec($exponentstring);
225                $fraction = getid3_lib::Bin2Dec($fractionstring);
226
227                if (($exponent == (pow(2, $exponentbits) - 1)) && ($fraction != 0)) {
228                        // Not a Number
229                        $floatvalue = false;
230                } elseif (($exponent == (pow(2, $exponentbits) - 1)) && ($fraction == 0)) {
231                        if ($signbit == '1') {
232                                $floatvalue = '-infinity';
233                        } else {
234                                $floatvalue = '+infinity';
235                        }
236                } elseif (($exponent == 0) && ($fraction == 0)) {
237                        if ($signbit == '1') {
238                                $floatvalue = -0;
239                        } else {
240                                $floatvalue = 0;
241                        }
242                        $floatvalue = ($signbit ? 0 : -0);
243                } elseif (($exponent == 0) && ($fraction != 0)) {
244                        // These are 'unnormalized' values
245                        $floatvalue = pow(2, (-1 * (pow(2, $exponentbits - 1) - 2))) * getid3_lib::DecimalBinary2Float($fractionstring);
246                        if ($signbit == '1') {
247                                $floatvalue *= -1;
248                        }
249                } elseif ($exponent != 0) {
250                        $floatvalue = pow(2, ($exponent - (pow(2, $exponentbits - 1) - 1))) * (1 + getid3_lib::DecimalBinary2Float($fractionstring));
251                        if ($signbit == '1') {
252                                $floatvalue *= -1;
253                        }
254                }
255                return (float) $floatvalue;
256        }
257
258
259        static function BigEndian2Int($byteword, $synchsafe=false, $signed=false) {
260                $intvalue = 0;
261                $bytewordlen = strlen($byteword);
262                if ($bytewordlen == 0) {
263                        return false;
264                }
265                for ($i = 0; $i < $bytewordlen; $i++) {
266                        if ($synchsafe) { // disregard MSB, effectively 7-bit bytes
267                                $intvalue = $intvalue | (ord($byteword{$i}) & 0x7F) << (($bytewordlen - 1 - $i) * 7);
268                        } else {
269                                $intvalue += ord($byteword{$i}) * pow(256, ($bytewordlen - 1 - $i));
270                        }
271                }
272                if ($signed && !$synchsafe) {
273                        // synchsafe ints are not allowed to be signed
274                        if ($bytewordlen <= PHP_INT_SIZE) {
275                                $signMaskBit = 0x80 << (8 * ($bytewordlen - 1));
276                                if ($intvalue & $signMaskBit) {
277                                        $intvalue = 0 - ($intvalue & ($signMaskBit - 1));
278                                }
279                        } else {
280                                throw new Exception('ERROR: Cannot have signed integers larger than '.(8 * PHP_INT_SIZE).'-bits ('.strlen($byteword).') in getid3_lib::BigEndian2Int()');
281                                break;
282                        }
283                }
284                return getid3_lib::CastAsInt($intvalue);
285        }
286
287
288        static function LittleEndian2Int($byteword, $signed=false) {
289                return getid3_lib::BigEndian2Int(strrev($byteword), false, $signed);
290        }
291
292
293        static function BigEndian2Bin($byteword) {
294                $binvalue = '';
295                $bytewordlen = strlen($byteword);
296                for ($i = 0; $i < $bytewordlen; $i++) {
297                        $binvalue .= str_pad(decbin(ord($byteword{$i})), 8, '0', STR_PAD_LEFT);
298                }
299                return $binvalue;
300        }
301
302
303        static function BigEndian2String($number, $minbytes=1, $synchsafe=false, $signed=false) {
304                if ($number < 0) {
305                        throw new Exception('ERROR: getid3_lib::BigEndian2String() does not support negative numbers');
306                }
307                $maskbyte = (($synchsafe || $signed) ? 0x7F : 0xFF);
308                $intstring = '';
309                if ($signed) {
310                        if ($minbytes > PHP_INT_SIZE) {
311                                throw new Exception('ERROR: Cannot have signed integers larger than '.(8 * PHP_INT_SIZE).'-bits in getid3_lib::BigEndian2String()');
312                        }
313                        $number = $number & (0x80 << (8 * ($minbytes - 1)));
314                }
315                while ($number != 0) {
316                        $quotient = ($number / ($maskbyte + 1));
317                        $intstring = chr(ceil(($quotient - floor($quotient)) * $maskbyte)).$intstring;
318                        $number = floor($quotient);
319                }
320                return str_pad($intstring, $minbytes, "\x00", STR_PAD_LEFT);
321        }
322
323
324        static function Dec2Bin($number) {
325                while ($number >= 256) {
326                        $bytes[] = (($number / 256) - (floor($number / 256))) * 256;
327                        $number = floor($number / 256);
328                }
329                $bytes[] = $number;
330                $binstring = '';
331                for ($i = 0; $i < count($bytes); $i++) {
332                        $binstring = (($i == count($bytes) - 1) ? decbin($bytes[$i]) : str_pad(decbin($bytes[$i]), 8, '0', STR_PAD_LEFT)).$binstring;
333                }
334                return $binstring;
335        }
336
337
338        static function Bin2Dec($binstring, $signed=false) {
339                $signmult = 1;
340                if ($signed) {
341                        if ($binstring{0} == '1') {
342                                $signmult = -1;
343                        }
344                        $binstring = substr($binstring, 1);
345                }
346                $decvalue = 0;
347                for ($i = 0; $i < strlen($binstring); $i++) {
348                        $decvalue += ((int) substr($binstring, strlen($binstring) - $i - 1, 1)) * pow(2, $i);
349                }
350                return getid3_lib::CastAsInt($decvalue * $signmult);
351        }
352
353
354        static function Bin2String($binstring) {
355                // return 'hi' for input of '0110100001101001'
356                $string = '';
357                $binstringreversed = strrev($binstring);
358                for ($i = 0; $i < strlen($binstringreversed); $i += 8) {
359                        $string = chr(getid3_lib::Bin2Dec(strrev(substr($binstringreversed, $i, 8)))).$string;
360                }
361                return $string;
362        }
363
364
365        static function LittleEndian2String($number, $minbytes=1, $synchsafe=false) {
366                $intstring = '';
367                while ($number > 0) {
368                        if ($synchsafe) {
369                                $intstring = $intstring.chr($number & 127);
370                                $number >>= 7;
371                        } else {
372                                $intstring = $intstring.chr($number & 255);
373                                $number >>= 8;
374                        }
375                }
376                return str_pad($intstring, $minbytes, "\x00", STR_PAD_RIGHT);
377        }
378
379
380        static function array_merge_clobber($array1, $array2) {
381                // written by kcØhireability*com
382                // taken from http://www.php.net/manual/en/function.array-merge-recursive.php
383                if (!is_array($array1) || !is_array($array2)) {
384                        return false;
385                }
386                $newarray = $array1;
387                foreach ($array2 as $key => $val) {
388                        if (is_array($val) && isset($newarray[$key]) && is_array($newarray[$key])) {
389                                $newarray[$key] = getid3_lib::array_merge_clobber($newarray[$key], $val);
390                        } else {
391                                $newarray[$key] = $val;
392                        }
393                }
394                return $newarray;
395        }
396
397
398        static function array_merge_noclobber($array1, $array2) {
399                if (!is_array($array1) || !is_array($array2)) {
400                        return false;
401                }
402                $newarray = $array1;
403                foreach ($array2 as $key => $val) {
404                        if (is_array($val) && isset($newarray[$key]) && is_array($newarray[$key])) {
405                                $newarray[$key] = getid3_lib::array_merge_noclobber($newarray[$key], $val);
406                        } elseif (!isset($newarray[$key])) {
407                                $newarray[$key] = $val;
408                        }
409                }
410                return $newarray;
411        }
412
413
414        static function fileextension($filename, $numextensions=1) {
415                if (strstr($filename, '.')) {
416                        $reversedfilename = strrev($filename);
417                        $offset = 0;
418                        for ($i = 0; $i < $numextensions; $i++) {
419                                $offset = strpos($reversedfilename, '.', $offset + 1);
420                                if ($offset === false) {
421                                        return '';
422                                }
423                        }
424                        return strrev(substr($reversedfilename, 0, $offset));
425                }
426                return '';
427        }
428
429
430        static function PlaytimeString($playtimeseconds) {
431                $sign = (($playtimeseconds < 0) ? '-' : '');
432                $playtimeseconds = abs($playtimeseconds);
433                $contentseconds = round((($playtimeseconds / 60) - floor($playtimeseconds / 60)) * 60);
434                $contentminutes = floor($playtimeseconds / 60);
435                if ($contentseconds >= 60) {
436                        $contentseconds -= 60;
437                        $contentminutes++;
438                }
439                return $sign.intval($contentminutes).':'.str_pad($contentseconds, 2, 0, STR_PAD_LEFT);
440        }
441
442
443        static function DateMac2Unix($macdate) {
444                // Macintosh timestamp: seconds since 00:00h January 1, 1904
445                // UNIX timestamp:      seconds since 00:00h January 1, 1970
446                return getid3_lib::CastAsInt($macdate - 2082844800);
447        }
448
449
450        static function FixedPoint8_8($rawdata) {
451                return getid3_lib::BigEndian2Int(substr($rawdata, 0, 1)) + (float) (getid3_lib::BigEndian2Int(substr($rawdata, 1, 1)) / pow(2, 8));
452        }
453
454
455        static function FixedPoint16_16($rawdata) {
456                return getid3_lib::BigEndian2Int(substr($rawdata, 0, 2)) + (float) (getid3_lib::BigEndian2Int(substr($rawdata, 2, 2)) / pow(2, 16));
457        }
458
459
460        static function FixedPoint2_30($rawdata) {
461                $binarystring = getid3_lib::BigEndian2Bin($rawdata);
462                return getid3_lib::Bin2Dec(substr($binarystring, 0, 2)) + (float) (getid3_lib::Bin2Dec(substr($binarystring, 2, 30)) / pow(2, 30));
463        }
464
465
466        static function CreateDeepArray($ArrayPath, $Separator, $Value) {
467                // assigns $Value to a nested array path:
468                //   $foo = getid3_lib::CreateDeepArray('/path/to/my', '/', 'file.txt')
469                // is the same as:
470                //   $foo = array('path'=>array('to'=>'array('my'=>array('file.txt'))));
471                // or
472                //   $foo['path']['to']['my'] = 'file.txt';
473                while ($ArrayPath && ($ArrayPath{0} == $Separator)) {
474                        $ArrayPath = substr($ArrayPath, 1);
475                }
476                if (($pos = strpos($ArrayPath, $Separator)) !== false) {
477                        $ReturnedArray[substr($ArrayPath, 0, $pos)] = getid3_lib::CreateDeepArray(substr($ArrayPath, $pos + 1), $Separator, $Value);
478                } else {
479                        $ReturnedArray[$ArrayPath] = $Value;
480                }
481                return $ReturnedArray;
482        }
483
484        static function array_max($arraydata, $returnkey=false) {
485                $maxvalue = false;
486                $maxkey = false;
487                foreach ($arraydata as $key => $value) {
488                        if (!is_array($value)) {
489                                if ($value > $maxvalue) {
490                                        $maxvalue = $value;
491                                        $maxkey = $key;
492                                }
493                        }
494                }
495                return ($returnkey ? $maxkey : $maxvalue);
496        }
497
498        static function array_min($arraydata, $returnkey=false) {
499                $minvalue = false;
500                $minkey = false;
501                foreach ($arraydata as $key => $value) {
502                        if (!is_array($value)) {
503                                if ($value > $minvalue) {
504                                        $minvalue = $value;
505                                        $minkey = $key;
506                                }
507                        }
508                }
509                return ($returnkey ? $minkey : $minvalue);
510        }
511
512
513        // Allan Hansen <ahØartemis*dk>
514        // getid3_lib::md5_data() - returns md5sum for a file from startuing position to absolute end position
515        static function hash_data($file, $offset, $end, $algorithm) {
516                if (!getid3_lib::intValueSupported($end)) {
517                        return false;
518                }
519                switch ($algorithm) {
520                        case 'md5':
521                                $hash_function = 'md5_file';
522                                $unix_call     = 'md5sum';
523                                $windows_call  = 'md5sum.exe';
524                                $hash_length   = 32;
525                                break;
526
527                        case 'sha1':
528                                $hash_function = 'sha1_file';
529                                $unix_call     = 'sha1sum';
530                                $windows_call  = 'sha1sum.exe';
531                                $hash_length   = 40;
532                                break;
533
534                        default:
535                                throw new Exception('Invalid algorithm ('.$algorithm.') in getid3_lib::hash_data()');
536                                break;
537                }
538                $size = $end - $offset;
539                while (true) {
540                        if (GETID3_OS_ISWINDOWS) {
541
542                                // It seems that sha1sum.exe for Windows only works on physical files, does not accept piped data
543                                // Fall back to create-temp-file method:
544                                if ($algorithm == 'sha1') {
545                                        break;
546                                }
547
548                                $RequiredFiles = array('cygwin1.dll', 'head.exe', 'tail.exe', $windows_call);
549                                foreach ($RequiredFiles as $required_file) {
550                                        if (!is_readable(GETID3_HELPERAPPSDIR.$required_file)) {
551                                                // helper apps not available - fall back to old method
552                                                break;
553                                        }
554                                }
555                                $commandline  = GETID3_HELPERAPPSDIR.'head.exe -c '.$end.' "'.escapeshellarg(str_replace('/', DIRECTORY_SEPARATOR, $file)).'" | ';
556                                $commandline .= GETID3_HELPERAPPSDIR.'tail.exe -c '.$size.' | ';
557                                $commandline .= GETID3_HELPERAPPSDIR.$windows_call;
558
559                        } else {
560
561                                $commandline  = 'head -c'.$end.' '.escapeshellarg($file).' | ';
562                                $commandline .= 'tail -c'.$size.' | ';
563                                $commandline .= $unix_call;
564
565                        }
566                        if (preg_match('#(1|ON)#i', ini_get('safe_mode'))) {
567                                $ThisFileInfo['warning'][] = 'PHP running in Safe Mode - backtick operator not available, using slower non-system-call '.$algorithm.' algorithm';
568                                break;
569                        }
570                        return substr(`$commandline`, 0, $hash_length);
571                }
572
573                // try to create a temporary file in the system temp directory - invalid dirname should force to system temp dir
574                if (($data_filename = tempnam(GETID3_TEMP_DIR, 'getID3')) === false) {
575                        // can't find anywhere to create a temp file, just die
576                        return false;
577                }
578
579                // Init
580                $result = false;
581
582                // copy parts of file
583                ob_start();
584                if ($fp = fopen($file, 'rb')) {
585                        ob_end_clean();
586                        ob_start();
587                        if ($fp_data = fopen($data_filename, 'wb')) {
588                                fseek($fp, $offset, SEEK_SET);
589                                $byteslefttowrite = $end - $offset;
590                                while (($byteslefttowrite > 0) && ($buffer = fread($fp, GETID3_FREAD_BUFFER_SIZE))) {
591                                        $byteswritten = fwrite($fp_data, $buffer, $byteslefttowrite);
592                                        $byteslefttowrite -= $byteswritten;
593                                }
594                                fclose($fp_data);
595                                $result = $hash_function($data_filename);
596                        } else {
597                                $errormessage = ob_get_contents();
598                                ob_end_clean();
599                        }
600                        fclose($fp);
601                } else {
602                        $errormessage = ob_get_contents();
603                        ob_end_clean();
604                }
605                unlink($data_filename);
606                return $result;
607        }
608
609
610        static function iconv_fallback_int_utf8($charval) {
611                if ($charval < 128) {
612                        // 0bbbbbbb
613                        $newcharstring = chr($charval);
614                } elseif ($charval < 2048) {
615                        // 110bbbbb 10bbbbbb
616                        $newcharstring  = chr(($charval >>   6) | 0xC0);
617                        $newcharstring .= chr(($charval & 0x3F) | 0x80);
618                } elseif ($charval < 65536) {
619                        // 1110bbbb 10bbbbbb 10bbbbbb
620                        $newcharstring  = chr(($charval >>  12) | 0xE0);
621                        $newcharstring .= chr(($charval >>   6) | 0xC0);
622                        $newcharstring .= chr(($charval & 0x3F) | 0x80);
623                } else {
624                        // 11110bbb 10bbbbbb 10bbbbbb 10bbbbbb
625                        $newcharstring  = chr(($charval >>  18) | 0xF0);
626                        $newcharstring .= chr(($charval >>  12) | 0xC0);
627                        $newcharstring .= chr(($charval >>   6) | 0xC0);
628                        $newcharstring .= chr(($charval & 0x3F) | 0x80);
629                }
630                return $newcharstring;
631        }
632
633        // ISO-8859-1 => UTF-8
634        static function iconv_fallback_iso88591_utf8($string, $bom=false) {
635                if (function_exists('utf8_encode')) {
636                        return utf8_encode($string);
637                }
638                // utf8_encode() unavailable, use getID3()'s iconv_fallback() conversions (possibly PHP is compiled without XML support)
639                $newcharstring = '';
640                if ($bom) {
641                        $newcharstring .= "\xEF\xBB\xBF";
642                }
643                for ($i = 0; $i < strlen($string); $i++) {
644                        $charval = ord($string{$i});
645                        $newcharstring .= getid3_lib::iconv_fallback_int_utf8($charval);
646                }
647                return $newcharstring;
648        }
649
650        // ISO-8859-1 => UTF-16BE
651        static function iconv_fallback_iso88591_utf16be($string, $bom=false) {
652                $newcharstring = '';
653                if ($bom) {
654                        $newcharstring .= "\xFE\xFF";
655                }
656                for ($i = 0; $i < strlen($string); $i++) {
657                        $newcharstring .= "\x00".$string{$i};
658                }
659                return $newcharstring;
660        }
661
662        // ISO-8859-1 => UTF-16LE
663        static function iconv_fallback_iso88591_utf16le($string, $bom=false) {
664                $newcharstring = '';
665                if ($bom) {
666                        $newcharstring .= "\xFF\xFE";
667                }
668                for ($i = 0; $i < strlen($string); $i++) {
669                        $newcharstring .= $string{$i}."\x00";
670                }
671                return $newcharstring;
672        }
673
674        // ISO-8859-1 => UTF-16LE (BOM)
675        static function iconv_fallback_iso88591_utf16($string) {
676                return getid3_lib::iconv_fallback_iso88591_utf16le($string, true);
677        }
678
679        // UTF-8 => ISO-8859-1
680        static function iconv_fallback_utf8_iso88591($string) {
681                if (function_exists('utf8_decode')) {
682                        return utf8_decode($string);
683                }
684                // utf8_decode() unavailable, use getID3()'s iconv_fallback() conversions (possibly PHP is compiled without XML support)
685                $newcharstring = '';
686                $offset = 0;
687                $stringlength = strlen($string);
688                while ($offset < $stringlength) {
689                        if ((ord($string{$offset}) | 0x07) == 0xF7) {
690                                // 11110bbb 10bbbbbb 10bbbbbb 10bbbbbb
691                                $charval = ((ord($string{($offset + 0)}) & 0x07) << 18) &
692                                                   ((ord($string{($offset + 1)}) & 0x3F) << 12) &
693                                                   ((ord($string{($offset + 2)}) & 0x3F) <<  6) &
694                                                        (ord($string{($offset + 3)}) & 0x3F);
695                                $offset += 4;
696                        } elseif ((ord($string{$offset}) | 0x0F) == 0xEF) {
697                                // 1110bbbb 10bbbbbb 10bbbbbb
698                                $charval = ((ord($string{($offset + 0)}) & 0x0F) << 12) &
699                                                   ((ord($string{($offset + 1)}) & 0x3F) <<  6) &
700                                                        (ord($string{($offset + 2)}) & 0x3F);
701                                $offset += 3;
702                        } elseif ((ord($string{$offset}) | 0x1F) == 0xDF) {
703                                // 110bbbbb 10bbbbbb
704                                $charval = ((ord($string{($offset + 0)}) & 0x1F) <<  6) &
705                                                        (ord($string{($offset + 1)}) & 0x3F);
706                                $offset += 2;
707                        } elseif ((ord($string{$offset}) | 0x7F) == 0x7F) {
708                                // 0bbbbbbb
709                                $charval = ord($string{$offset});
710                                $offset += 1;
711                        } else {
712                                // error? throw some kind of warning here?
713                                $charval = false;
714                                $offset += 1;
715                        }
716                        if ($charval !== false) {
717                                $newcharstring .= (($charval < 256) ? chr($charval) : '?');
718                        }
719                }
720                return $newcharstring;
721        }
722
723        // UTF-8 => UTF-16BE
724        static function iconv_fallback_utf8_utf16be($string, $bom=false) {
725                $newcharstring = '';
726                if ($bom) {
727                        $newcharstring .= "\xFE\xFF";
728                }
729                $offset = 0;
730                $stringlength = strlen($string);
731                while ($offset < $stringlength) {
732                        if ((ord($string{$offset}) | 0x07) == 0xF7) {
733                                // 11110bbb 10bbbbbb 10bbbbbb 10bbbbbb
734                                $charval = ((ord($string{($offset + 0)}) & 0x07) << 18) &
735                                                   ((ord($string{($offset + 1)}) & 0x3F) << 12) &
736                                                   ((ord($string{($offset + 2)}) & 0x3F) <<  6) &
737                                                        (ord($string{($offset + 3)}) & 0x3F);
738                                $offset += 4;
739                        } elseif ((ord($string{$offset}) | 0x0F) == 0xEF) {
740                                // 1110bbbb 10bbbbbb 10bbbbbb
741                                $charval = ((ord($string{($offset + 0)}) & 0x0F) << 12) &
742                                                   ((ord($string{($offset + 1)}) & 0x3F) <<  6) &
743                                                        (ord($string{($offset + 2)}) & 0x3F);
744                                $offset += 3;
745                        } elseif ((ord($string{$offset}) | 0x1F) == 0xDF) {
746                                // 110bbbbb 10bbbbbb
747                                $charval = ((ord($string{($offset + 0)}) & 0x1F) <<  6) &
748                                                        (ord($string{($offset + 1)}) & 0x3F);
749                                $offset += 2;
750                        } elseif ((ord($string{$offset}) | 0x7F) == 0x7F) {
751                                // 0bbbbbbb
752                                $charval = ord($string{$offset});
753                                $offset += 1;
754                        } else {
755                                // error? throw some kind of warning here?
756                                $charval = false;
757                                $offset += 1;
758                        }
759                        if ($charval !== false) {
760                                $newcharstring .= (($charval < 65536) ? getid3_lib::BigEndian2String($charval, 2) : "\x00".'?');
761                        }
762                }
763                return $newcharstring;
764        }
765
766        // UTF-8 => UTF-16LE
767        static function iconv_fallback_utf8_utf16le($string, $bom=false) {
768                $newcharstring = '';
769                if ($bom) {
770                        $newcharstring .= "\xFF\xFE";
771                }
772                $offset = 0;
773                $stringlength = strlen($string);
774                while ($offset < $stringlength) {
775                        if ((ord($string{$offset}) | 0x07) == 0xF7) {
776                                // 11110bbb 10bbbbbb 10bbbbbb 10bbbbbb
777                                $charval = ((ord($string{($offset + 0)}) & 0x07) << 18) &
778                                                   ((ord($string{($offset + 1)}) & 0x3F) << 12) &
779                                                   ((ord($string{($offset + 2)}) & 0x3F) <<  6) &
780                                                        (ord($string{($offset + 3)}) & 0x3F);
781                                $offset += 4;
782                        } elseif ((ord($string{$offset}) | 0x0F) == 0xEF) {
783                                // 1110bbbb 10bbbbbb 10bbbbbb
784                                $charval = ((ord($string{($offset + 0)}) & 0x0F) << 12) &
785                                                   ((ord($string{($offset + 1)}) & 0x3F) <<  6) &
786                                                        (ord($string{($offset + 2)}) & 0x3F);
787                                $offset += 3;
788                        } elseif ((ord($string{$offset}) | 0x1F) == 0xDF) {
789                                // 110bbbbb 10bbbbbb
790                                $charval = ((ord($string{($offset + 0)}) & 0x1F) <<  6) &
791                                                        (ord($string{($offset + 1)}) & 0x3F);
792                                $offset += 2;
793                        } elseif ((ord($string{$offset}) | 0x7F) == 0x7F) {
794                                // 0bbbbbbb
795                                $charval = ord($string{$offset});
796                                $offset += 1;
797                        } else {
798                                // error? maybe throw some warning here?
799                                $charval = false;
800                                $offset += 1;
801                        }
802                        if ($charval !== false) {
803                                $newcharstring .= (($charval < 65536) ? getid3_lib::LittleEndian2String($charval, 2) : '?'."\x00");
804                        }
805                }
806                return $newcharstring;
807        }
808
809        // UTF-8 => UTF-16LE (BOM)
810        static function iconv_fallback_utf8_utf16($string) {
811                return getid3_lib::iconv_fallback_utf8_utf16le($string, true);
812        }
813
814        // UTF-16BE => UTF-8
815        static function iconv_fallback_utf16be_utf8($string) {
816                if (substr($string, 0, 2) == "\xFE\xFF") {
817                        // strip BOM
818                        $string = substr($string, 2);
819                }
820                $newcharstring = '';
821                for ($i = 0; $i < strlen($string); $i += 2) {
822                        $charval = getid3_lib::BigEndian2Int(substr($string, $i, 2));
823                        $newcharstring .= getid3_lib::iconv_fallback_int_utf8($charval);
824                }
825                return $newcharstring;
826        }
827
828        // UTF-16LE => UTF-8
829        static function iconv_fallback_utf16le_utf8($string) {
830                if (substr($string, 0, 2) == "\xFF\xFE") {
831                        // strip BOM
832                        $string = substr($string, 2);
833                }
834                $newcharstring = '';
835                for ($i = 0; $i < strlen($string); $i += 2) {
836                        $charval = getid3_lib::LittleEndian2Int(substr($string, $i, 2));
837                        $newcharstring .= getid3_lib::iconv_fallback_int_utf8($charval);
838                }
839                return $newcharstring;
840        }
841
842        // UTF-16BE => ISO-8859-1
843        static function iconv_fallback_utf16be_iso88591($string) {
844                if (substr($string, 0, 2) == "\xFE\xFF") {
845                        // strip BOM
846                        $string = substr($string, 2);
847                }
848                $newcharstring = '';
849                for ($i = 0; $i < strlen($string); $i += 2) {
850                        $charval = getid3_lib::BigEndian2Int(substr($string, $i, 2));
851                        $newcharstring .= (($charval < 256) ? chr($charval) : '?');
852                }
853                return $newcharstring;
854        }
855
856        // UTF-16LE => ISO-8859-1
857        static function iconv_fallback_utf16le_iso88591($string) {
858                if (substr($string, 0, 2) == "\xFF\xFE") {
859                        // strip BOM
860                        $string = substr($string, 2);
861                }
862                $newcharstring = '';
863                for ($i = 0; $i < strlen($string); $i += 2) {
864                        $charval = getid3_lib::LittleEndian2Int(substr($string, $i, 2));
865                        $newcharstring .= (($charval < 256) ? chr($charval) : '?');
866                }
867                return $newcharstring;
868        }
869
870        // UTF-16 (BOM) => ISO-8859-1
871        static function iconv_fallback_utf16_iso88591($string) {
872                $bom = substr($string, 0, 2);
873                if ($bom == "\xFE\xFF") {
874                        return getid3_lib::iconv_fallback_utf16be_iso88591(substr($string, 2));
875                } elseif ($bom == "\xFF\xFE") {
876                        return getid3_lib::iconv_fallback_utf16le_iso88591(substr($string, 2));
877                }
878                return $string;
879        }
880
881        // UTF-16 (BOM) => UTF-8
882        static function iconv_fallback_utf16_utf8($string) {
883                $bom = substr($string, 0, 2);
884                if ($bom == "\xFE\xFF") {
885                        return getid3_lib::iconv_fallback_utf16be_utf8(substr($string, 2));
886                } elseif ($bom == "\xFF\xFE") {
887                        return getid3_lib::iconv_fallback_utf16le_utf8(substr($string, 2));
888                }
889                return $string;
890        }
891
892        static function iconv_fallback($in_charset, $out_charset, $string) {
893
894                if ($in_charset == $out_charset) {
895                        return $string;
896                }
897
898                // iconv() availble
899                if (function_exists('iconv')) {
900
901                        ob_start();
902                        if ($converted_string = @iconv($in_charset, $out_charset.'//TRANSLIT', $string)) {
903                                ob_end_clean();
904                                switch ($out_charset) {
905                                        case 'ISO-8859-1':
906                                                $converted_string = rtrim($converted_string, "\x00");
907                                                break;
908                                }
909                                return $converted_string;
910                        } else {
911                                $errormessage = ob_get_contents();
912                                ob_end_clean();
913                        }
914
915                        // iconv() may sometimes fail with "illegal character in input string" error message
916                        // and return an empty string, but returning the unconverted string is more useful
917                        return $string;
918                }
919
920
921                // iconv() not available
922                static $ConversionFunctionList = array();
923                if (empty($ConversionFunctionList)) {
924                        $ConversionFunctionList['ISO-8859-1']['UTF-8']    = 'iconv_fallback_iso88591_utf8';
925                        $ConversionFunctionList['ISO-8859-1']['UTF-16']   = 'iconv_fallback_iso88591_utf16';
926                        $ConversionFunctionList['ISO-8859-1']['UTF-16BE'] = 'iconv_fallback_iso88591_utf16be';
927                        $ConversionFunctionList['ISO-8859-1']['UTF-16LE'] = 'iconv_fallback_iso88591_utf16le';
928                        $ConversionFunctionList['UTF-8']['ISO-8859-1']    = 'iconv_fallback_utf8_iso88591';
929                        $ConversionFunctionList['UTF-8']['UTF-16']        = 'iconv_fallback_utf8_utf16';
930                        $ConversionFunctionList['UTF-8']['UTF-16BE']      = 'iconv_fallback_utf8_utf16be';
931                        $ConversionFunctionList['UTF-8']['UTF-16LE']      = 'iconv_fallback_utf8_utf16le';
932                        $ConversionFunctionList['UTF-16']['ISO-8859-1']   = 'iconv_fallback_utf16_iso88591';
933                        $ConversionFunctionList['UTF-16']['UTF-8']        = 'iconv_fallback_utf16_utf8';
934                        $ConversionFunctionList['UTF-16LE']['ISO-8859-1'] = 'iconv_fallback_utf16le_iso88591';
935                        $ConversionFunctionList['UTF-16LE']['UTF-8']      = 'iconv_fallback_utf16le_utf8';
936                        $ConversionFunctionList['UTF-16BE']['ISO-8859-1'] = 'iconv_fallback_utf16be_iso88591';
937                        $ConversionFunctionList['UTF-16BE']['UTF-8']      = 'iconv_fallback_utf16be_utf8';
938                }
939                if (isset($ConversionFunctionList[strtoupper($in_charset)][strtoupper($out_charset)])) {
940                        $ConversionFunction = $ConversionFunctionList[strtoupper($in_charset)][strtoupper($out_charset)];
941                        return getid3_lib::$ConversionFunction($string);
942                }
943                throw new Exception('PHP does not have iconv() support - cannot convert from '.$in_charset.' to '.$out_charset);
944        }
945
946
947        static function MultiByteCharString2HTML($string, $charset='ISO-8859-1') {
948                $HTMLstring = '';
949
950                switch ($charset) {
951                        case '1251':
952                        case '1252':
953                        case '866':
954                        case '932':
955                        case '936':
956                        case '950':
957                        case 'BIG5':
958                        case 'BIG5-HKSCS':
959                        case 'cp1251':
960                        case 'cp1252':
961                        case 'cp866':
962                        case 'EUC-JP':
963                        case 'EUCJP':
964                        case 'GB2312':
965                        case 'ibm866':
966                        case 'ISO-8859-1':
967                        case 'ISO-8859-15':
968                        case 'ISO8859-1':
969                        case 'ISO8859-15':
970                        case 'KOI8-R':
971                        case 'koi8-ru':
972                        case 'koi8r':
973                        case 'Shift_JIS':
974                        case 'SJIS':
975                        case 'win-1251':
976                        case 'Windows-1251':
977                        case 'Windows-1252':
978                                $HTMLstring = htmlentities($string, ENT_COMPAT, $charset);
979                                break;
980
981                        case 'UTF-8':
982                                $strlen = strlen($string);
983                                for ($i = 0; $i < $strlen; $i++) {
984                                        $char_ord_val = ord($string{$i});
985                                        $charval = 0;
986                                        if ($char_ord_val < 0x80) {
987                                                $charval = $char_ord_val;
988                                        } elseif ((($char_ord_val & 0xF0) >> 4) == 0x0F  &&  $i+3 < $strlen) {
989                                                $charval  = (($char_ord_val & 0x07) << 18);
990                                                $charval += ((ord($string{++$i}) & 0x3F) << 12);
991                                                $charval += ((ord($string{++$i}) & 0x3F) << 6);
992                                                $charval +=  (ord($string{++$i}) & 0x3F);
993                                        } elseif ((($char_ord_val & 0xE0) >> 5) == 0x07  &&  $i+2 < $strlen) {
994                                                $charval  = (($char_ord_val & 0x0F) << 12);
995                                                $charval += ((ord($string{++$i}) & 0x3F) << 6);
996                                                $charval +=  (ord($string{++$i}) & 0x3F);
997                                        } elseif ((($char_ord_val & 0xC0) >> 6) == 0x03  &&  $i+1 < $strlen) {
998                                                $charval  = (($char_ord_val & 0x1F) << 6);
999                                                $charval += (ord($string{++$i}) & 0x3F);
1000                                        }
1001                                        if (($charval >= 32) && ($charval <= 127)) {
1002                                                $HTMLstring .= htmlentities(chr($charval));
1003                                        } else {
1004                                                $HTMLstring .= '&#'.$charval.';';
1005                                        }
1006                                }
1007                                break;
1008
1009                        case 'UTF-16LE':
1010                                for ($i = 0; $i < strlen($string); $i += 2) {
1011                                        $charval = getid3_lib::LittleEndian2Int(substr($string, $i, 2));
1012                                        if (($charval >= 32) && ($charval <= 127)) {
1013                                                $HTMLstring .= chr($charval);
1014                                        } else {
1015                                                $HTMLstring .= '&#'.$charval.';';
1016                                        }
1017                                }
1018                                break;
1019
1020                        case 'UTF-16BE':
1021                                for ($i = 0; $i < strlen($string); $i += 2) {
1022                                        $charval = getid3_lib::BigEndian2Int(substr($string, $i, 2));
1023                                        if (($charval >= 32) && ($charval <= 127)) {
1024                                                $HTMLstring .= chr($charval);
1025                                        } else {
1026                                                $HTMLstring .= '&#'.$charval.';';
1027                                        }
1028                                }
1029                                break;
1030
1031                        default:
1032                                $HTMLstring = 'ERROR: Character set "'.$charset.'" not supported in MultiByteCharString2HTML()';
1033                                break;
1034                }
1035                return $HTMLstring;
1036        }
1037
1038
1039
1040        static function RGADnameLookup($namecode) {
1041                static $RGADname = array();
1042                if (empty($RGADname)) {
1043                        $RGADname[0] = 'not set';
1044                        $RGADname[1] = 'Track Gain Adjustment';
1045                        $RGADname[2] = 'Album Gain Adjustment';
1046                }
1047
1048                return (isset($RGADname[$namecode]) ? $RGADname[$namecode] : '');
1049        }
1050
1051
1052        static function RGADoriginatorLookup($originatorcode) {
1053                static $RGADoriginator = array();
1054                if (empty($RGADoriginator)) {
1055                        $RGADoriginator[0] = 'unspecified';
1056                        $RGADoriginator[1] = 'pre-set by artist/producer/mastering engineer';
1057                        $RGADoriginator[2] = 'set by user';
1058                        $RGADoriginator[3] = 'determined automatically';
1059                }
1060
1061                return (isset($RGADoriginator[$originatorcode]) ? $RGADoriginator[$originatorcode] : '');
1062        }
1063
1064
1065        static function RGADadjustmentLookup($rawadjustment, $signbit) {
1066                $adjustment = $rawadjustment / 10;
1067                if ($signbit == 1) {
1068                        $adjustment *= -1;
1069                }
1070                return (float) $adjustment;
1071        }
1072
1073
1074        static function RGADgainString($namecode, $originatorcode, $replaygain) {
1075                if ($replaygain < 0) {
1076                        $signbit = '1';
1077                } else {
1078                        $signbit = '0';
1079                }
1080                $storedreplaygain = intval(round($replaygain * 10));
1081                $gainstring  = str_pad(decbin($namecode), 3, '0', STR_PAD_LEFT);
1082                $gainstring .= str_pad(decbin($originatorcode), 3, '0', STR_PAD_LEFT);
1083                $gainstring .= $signbit;
1084                $gainstring .= str_pad(decbin($storedreplaygain), 9, '0', STR_PAD_LEFT);
1085
1086                return $gainstring;
1087        }
1088
1089        static function RGADamplitude2dB($amplitude) {
1090                return 20 * log10($amplitude);
1091        }
1092
1093
1094        static function GetDataImageSize($imgData, &$imageinfo) {
1095                $GetDataImageSize = false;
1096                if ($tempfilename = tempnam(GETID3_TEMP_DIR, 'getID3')) {
1097                        ob_start();
1098                        if ($tmp = fopen($tempfilename, 'wb')) {
1099                                ob_end_clean();
1100                                fwrite($tmp, $imgData);
1101                                fclose($tmp);
1102                                ob_start();
1103                                $GetDataImageSize = GetImageSize($tempfilename, $imageinfo);
1104                                $errormessage = ob_get_contents();
1105                                ob_end_clean();
1106                        } else {
1107                                $errormessage = ob_get_contents();
1108                                ob_end_clean();
1109                        }
1110                        unlink($tempfilename);
1111                }
1112                return $GetDataImageSize;
1113        }
1114
1115        static function ImageTypesLookup($imagetypeid) {
1116                static $ImageTypesLookup = array();
1117                if (empty($ImageTypesLookup)) {
1118                        $ImageTypesLookup[1]  = 'gif';
1119                        $ImageTypesLookup[2]  = 'jpeg';
1120                        $ImageTypesLookup[3]  = 'png';
1121                        $ImageTypesLookup[4]  = 'swf';
1122                        $ImageTypesLookup[5]  = 'psd';
1123                        $ImageTypesLookup[6]  = 'bmp';
1124                        $ImageTypesLookup[7]  = 'tiff (little-endian)';
1125                        $ImageTypesLookup[8]  = 'tiff (big-endian)';
1126                        $ImageTypesLookup[9]  = 'jpc';
1127                        $ImageTypesLookup[10] = 'jp2';
1128                        $ImageTypesLookup[11] = 'jpx';
1129                        $ImageTypesLookup[12] = 'jb2';
1130                        $ImageTypesLookup[13] = 'swc';
1131                        $ImageTypesLookup[14] = 'iff';
1132                }
1133                return (isset($ImageTypesLookup[$imagetypeid]) ? $ImageTypesLookup[$imagetypeid] : '');
1134        }
1135
1136        static function CopyTagsToComments(&$ThisFileInfo) {
1137
1138                // Copy all entries from ['tags'] into common ['comments']
1139                if (!empty($ThisFileInfo['tags'])) {
1140                        foreach ($ThisFileInfo['tags'] as $tagtype => $tagarray) {
1141                                foreach ($tagarray as $tagname => $tagdata) {
1142                                        foreach ($tagdata as $key => $value) {
1143                                                if (!empty($value)) {
1144                                                        if (empty($ThisFileInfo['comments'][$tagname])) {
1145
1146                                                                // fall through and append value
1147
1148                                                        } elseif ($tagtype == 'id3v1') {
1149
1150                                                                $newvaluelength = strlen(trim($value));
1151                                                                foreach ($ThisFileInfo['comments'][$tagname] as $existingkey => $existingvalue) {
1152                                                                        $oldvaluelength = strlen(trim($existingvalue));
1153                                                                        if (($newvaluelength <= $oldvaluelength) && (substr($existingvalue, 0, $newvaluelength) == trim($value))) {
1154                                                                                // new value is identical but shorter-than (or equal-length to) one already in comments - skip
1155                                                                                break 2;
1156                                                                        }
1157                                                                }
1158
1159                                                        } elseif (!is_array($value)) {
1160
1161                                                                $newvaluelength = strlen(trim($value));
1162                                                                foreach ($ThisFileInfo['comments'][$tagname] as $existingkey => $existingvalue) {
1163                                                                        $oldvaluelength = strlen(trim($existingvalue));
1164                                                                        if (($newvaluelength > $oldvaluelength) && (substr(trim($value), 0, strlen($existingvalue)) == $existingvalue)) {
1165                                                                                $ThisFileInfo['comments'][$tagname][$existingkey] = trim($value);
1166                                                                                break 2;
1167                                                                        }
1168                                                                }
1169
1170                                                        }
1171                                                        if (is_array($value) || empty($ThisFileInfo['comments'][$tagname]) || !in_array(trim($value), $ThisFileInfo['comments'][$tagname])) {
1172                                                                $value = (is_string($value) ? trim($value) : $value);
1173                                                                $ThisFileInfo['comments'][$tagname][] = $value;
1174                                                        }
1175                                                }
1176                                        }
1177                                }
1178                        }
1179
1180                        // Copy to ['comments_html']
1181                        foreach ($ThisFileInfo['comments'] as $field => $values) {
1182                                foreach ($values as $index => $value) {
1183                                        if (is_array($value)) {
1184                                                $ThisFileInfo['comments_html'][$field][$index] = $value;
1185                                        } else {
1186                                                $ThisFileInfo['comments_html'][$field][$index] = str_replace('&#0;', '', getid3_lib::MultiByteCharString2HTML($value, $ThisFileInfo['encoding']));
1187                                        }
1188                                }
1189                        }
1190                }
1191        }
1192
1193
1194        static function EmbeddedLookup($key, $begin, $end, $file, $name) {
1195
1196                // Cached
1197                static $cache;
1198                if (isset($cache[$file][$name])) {
1199                        return (isset($cache[$file][$name][$key]) ? $cache[$file][$name][$key] : '');
1200                }
1201
1202                // Init
1203                $keylength  = strlen($key);
1204                $line_count = $end - $begin - 7;
1205
1206                // Open php file
1207                $fp = fopen($file, 'r');
1208
1209                // Discard $begin lines
1210                for ($i = 0; $i < ($begin + 3); $i++) {
1211                        fgets($fp, 1024);
1212                }
1213
1214                // Loop thru line
1215                while (0 < $line_count--) {
1216
1217                        // Read line
1218                        $line = ltrim(fgets($fp, 1024), "\t ");
1219
1220                        // METHOD A: only cache the matching key - less memory but slower on next lookup of not-previously-looked-up key
1221                        //$keycheck = substr($line, 0, $keylength);
1222                        //if ($key == $keycheck)  {
1223                        //      $cache[$file][$name][$keycheck] = substr($line, $keylength + 1);
1224                        //      break;
1225                        //}
1226
1227                        // METHOD B: cache all keys in this lookup - more memory but faster on next lookup of not-previously-looked-up key
1228                        //$cache[$file][$name][substr($line, 0, $keylength)] = trim(substr($line, $keylength + 1));
1229                        $explodedLine = explode("\t", $line, 2);
1230                        $ThisKey   = (isset($explodedLine[0]) ? $explodedLine[0] : '');
1231                        $ThisValue = (isset($explodedLine[1]) ? $explodedLine[1] : '');
1232                        $cache[$file][$name][$ThisKey] = trim($ThisValue);
1233                }
1234
1235                // Close and return
1236                fclose($fp);
1237                return (isset($cache[$file][$name][$key]) ? $cache[$file][$name][$key] : '');
1238        }
1239
1240        static function IncludeDependency($filename, $sourcefile, $DieOnFailure=false) {
1241                global $GETID3_ERRORARRAY;
1242
1243                if (file_exists($filename)) {
1244                        if (include_once($filename)) {
1245                                return true;
1246                        } else {
1247                                $diemessage = basename($sourcefile).' depends on '.$filename.', which has errors';
1248                        }
1249                } else {
1250                        $diemessage = basename($sourcefile).' depends on '.$filename.', which is missing';
1251                }
1252                if ($DieOnFailure) {
1253                        throw new Exception($diemessage);
1254                } else {
1255                        $GETID3_ERRORARRAY[] = $diemessage;
1256                }
1257                return false;
1258        }
1259
1260}
1261
1262?>
Note: See TracBrowser for help on using the repository browser.