ILIAS  release_5-2 Revision v5.2.25-18-g3f80b828510
Helper.php
Go to the documentation of this file.
1<?php
2
3namespace GetId3\Lib;
4
7
10// available at http://getid3.sourceforge.net //
11// or http://www.getid3.org //
13// //
14// GetId3.lib.php - part of GetId3() //
15// See readme.txt for more details //
16// ///
18
26class Helper
27{
36 public static function PrintHexBytes($string, $hex = true, $spaces = true,
37 $htmlencoding = 'UTF-8')
38 {
39 $returnstring = '';
40 for ($i = 0; $i < strlen($string); $i++) {
41 if ($hex) {
42 $returnstring .= str_pad(dechex(ord($string{$i})), 2, '0',
43 STR_PAD_LEFT);
44 } else {
45 $returnstring .= ' ' . (preg_match("#[\x20-\x7E]#", $string{$i}) ? $string{$i} : 'ยค');
46 }
47 if ($spaces) {
48 $returnstring .= ' ';
49 }
50 }
51 if (!empty($htmlencoding)) {
52 if ($htmlencoding === true) {
53 $htmlencoding = 'UTF-8'; // prior to GetId3 v1.9.0 the function's 4th parameter was boolean
54 }
55 $returnstring = htmlentities($returnstring, ENT_QUOTES,
56 $htmlencoding);
57 }
58
59 return $returnstring;
60 }
61
67 public static function trunc($floatnumber)
68 {
69 // truncates a floating-point number at the decimal point
70 // returns int (if possible, otherwise float)
71 if ($floatnumber >= 1) {
72 $truncatednumber = floor($floatnumber);
73 } elseif ($floatnumber <= -1) {
74 $truncatednumber = ceil($floatnumber);
75 } else {
76 $truncatednumber = 0;
77 }
78 if (self::intValueSupported($truncatednumber)) {
79 $truncatednumber = (int) $truncatednumber;
80 }
81
82 return $truncatednumber;
83 }
84
91 public static function safe_inc(&$variable, $increment = 1)
92 {
93 if (isset($variable)) {
94 $variable += $increment;
95 } else {
96 $variable = $increment;
97 }
98
99 return true;
100 }
101
107 public static function CastAsInt($floatnum)
108 {
109 // convert to float if not already
110 $floatnum = (float) $floatnum;
111
112 // convert a float to type int, only if possible
113 if (self::trunc($floatnum) == $floatnum) {
114 // it's not floating point
115 if (self::intValueSupported($floatnum)) {
116 // it's within int range
117 $floatnum = (int) $floatnum;
118 }
119 }
120
121 return $floatnum;
122 }
123
130 public static function intValueSupported($num)
131 {
132 // check if integers are 64-bit
133 static $hasINT64 = null;
134 if ($hasINT64 === null) { // 10x faster than is_null()
135 $hasINT64 = is_int(pow(2, 31)); // 32-bit int are limited to (2^31)-1
136 if (!$hasINT64 && !defined('PHP_INT_MIN')) {
137 define('PHP_INT_MIN', ~PHP_INT_MAX);
138 }
139 }
140 // if integers are 64-bit - no other check required
141 if ($hasINT64 || (($num <= PHP_INT_MAX) && ($num >= PHP_INT_MIN))) {
142 return true;
143 }
144
145 return false;
146 }
147
153 public static function DecimalizeFraction($fraction)
154 {
155 list($numerator, $denominator) = explode('/', $fraction);
156
157 return $numerator / ($denominator ? $denominator : 1);
158 }
159
165 public static function DecimalBinary2Float($binarynumerator)
166 {
167 $numerator = self::Bin2Dec($binarynumerator);
168 $denominator = self::Bin2Dec('1' . str_repeat('0',
169 strlen($binarynumerator)));
170
171 return ($numerator / $denominator);
172 }
173
180 public static function NormalizeBinaryPoint($binarypointnumber, $maxbits = 52)
181 {
182 // http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/binary.html
183 if (strpos($binarypointnumber, '.') === false) {
184 $binarypointnumber = '0.' . $binarypointnumber;
185 } elseif ($binarypointnumber{0} == '.') {
186 $binarypointnumber = '0' . $binarypointnumber;
187 }
188 $exponent = 0;
189 while (($binarypointnumber{0} != '1') || (substr($binarypointnumber, 1,
190 1) != '.')) {
191 if (substr($binarypointnumber, 1, 1) == '.') {
192 $exponent--;
193 $binarypointnumber = substr($binarypointnumber, 2, 1) . '.' . substr($binarypointnumber,
194 3);
195 } else {
196 $pointpos = strpos($binarypointnumber, '.');
197 $exponent += ($pointpos - 1);
198 $binarypointnumber = str_replace('.', '', $binarypointnumber);
199 $binarypointnumber = $binarypointnumber{0} . '.' . substr($binarypointnumber,
200 1);
201 }
202 }
203 $binarypointnumber = str_pad(substr($binarypointnumber, 0, $maxbits + 2),
204 $maxbits + 2, '0', STR_PAD_RIGHT);
205
206 return array('normalized' => $binarypointnumber, 'exponent' => (int) $exponent);
207 }
208
214 public static function Float2BinaryDecimal($floatvalue)
215 {
216 // http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/binary.html
217 $maxbits = 128; // to how many bits of precision should the calculations be taken?
218 $intpart = self::trunc($floatvalue);
219 $floatpart = abs($floatvalue - $intpart);
220 $pointbitstring = '';
221 while (($floatpart != 0) && (strlen($pointbitstring) < $maxbits)) {
222 $floatpart *= 2;
223 $pointbitstring .= (string) self::trunc($floatpart);
224 $floatpart -= self::trunc($floatpart);
225 }
226 $binarypointnumber = decbin($intpart) . '.' . $pointbitstring;
227
228 return $binarypointnumber;
229 }
230
237 public static function Float2String($floatvalue, $bits)
238 {
239 // http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/ieee-expl.html
240 switch ($bits) {
241 case 32:
242 $exponentbits = 8;
243 $fractionbits = 23;
244 break;
245
246 case 64:
247 $exponentbits = 11;
248 $fractionbits = 52;
249 break;
250
251 default:
252 return false;
253 break;
254 }
255 if ($floatvalue >= 0) {
256 $signbit = '0';
257 } else {
258 $signbit = '1';
259 }
260 $normalizedbinary = self::NormalizeBinaryPoint(self::Float2BinaryDecimal($floatvalue),
261 $fractionbits);
262 $biasedexponent = pow(2, $exponentbits - 1) - 1 + $normalizedbinary['exponent']; // (127 or 1023) +/- exponent
263 $exponentbitstring = str_pad(decbin($biasedexponent), $exponentbits,
264 '0', STR_PAD_LEFT);
265 $fractionbitstring = str_pad(substr($normalizedbinary['normalized'], 2),
266 $fractionbits, '0', STR_PAD_RIGHT);
267
268 return self::BigEndian2String(self::Bin2Dec($signbit . $exponentbitstring . $fractionbitstring),
269 $bits % 8, false);
270 }
271
277 public static function LittleEndian2Float($byteword)
278 {
279 return self::BigEndian2Float(strrev($byteword));
280 }
281
290 public static function BigEndian2Float($byteword)
291 {
292 $bitword = self::BigEndian2Bin($byteword);
293 if (!$bitword) {
294 return 0;
295 }
296 $signbit = $bitword{0};
297
298 switch (strlen($byteword) * 8) {
299 case 32:
300 $exponentbits = 8;
301 $fractionbits = 23;
302 break;
303
304 case 64:
305 $exponentbits = 11;
306 $fractionbits = 52;
307 break;
308
309 case 80:
310 // 80-bit Apple SANE format
311 // http://www.mactech.com/articles/mactech/Vol.06/06.01/SANENormalized/
312 $exponentstring = substr($bitword, 1, 15);
313 $isnormalized = intval($bitword{16});
314 $fractionstring = substr($bitword, 17, 63);
315 $exponent = pow(2, self::Bin2Dec($exponentstring) - 16383);
316 $fraction = $isnormalized + self::DecimalBinary2Float($fractionstring);
317 $floatvalue = $exponent * $fraction;
318 if ($signbit == '1') {
319 $floatvalue *= -1;
320 }
321
322 return $floatvalue;
323 break;
324
325 default:
326 return false;
327 break;
328 }
329 $exponentstring = substr($bitword, 1, $exponentbits);
330 $fractionstring = substr($bitword, $exponentbits + 1, $fractionbits);
331 $exponent = self::Bin2Dec($exponentstring);
332 $fraction = self::Bin2Dec($fractionstring);
333
334 if (($exponent == (pow(2, $exponentbits) - 1)) && ($fraction != 0)) {
335 // Not a Number
336 $floatvalue = false;
337 } elseif (($exponent == (pow(2, $exponentbits) - 1)) && ($fraction == 0)) {
338 if ($signbit == '1') {
339 $floatvalue = '-infinity';
340 } else {
341 $floatvalue = '+infinity';
342 }
343 } elseif (($exponent == 0) && ($fraction == 0)) {
344 if ($signbit == '1') {
345 $floatvalue = -0;
346 } else {
347 $floatvalue = 0;
348 }
349 $floatvalue = ($signbit ? 0 : -0);
350 } elseif (($exponent == 0) && ($fraction != 0)) {
351 // These are 'unnormalized' values
352 $floatvalue = pow(2, (-1 * (pow(2, $exponentbits - 1) - 2))) * self::DecimalBinary2Float($fractionstring);
353 if ($signbit == '1') {
354 $floatvalue *= -1;
355 }
356 } elseif ($exponent != 0) {
357 $floatvalue = pow(2, ($exponent - (pow(2, $exponentbits - 1) - 1))) * (1 + self::DecimalBinary2Float($fractionstring));
358 if ($signbit == '1') {
359 $floatvalue *= -1;
360 }
361 }
362
363 return (float) $floatvalue;
364 }
365
374 public static function BigEndian2Int($byteword, $synchsafe = false,
375 $signed = false)
376 {
377 $intvalue = 0;
378 $bytewordlen = strlen($byteword);
379 if ($bytewordlen == 0) {
380 return false;
381 }
382 for ($i = 0; $i < $bytewordlen; $i++) {
383 if ($synchsafe) { // disregard MSB, effectively 7-bit bytes
384 //$intvalue = $intvalue | (ord($byteword{$i}) & 0x7F) << (($bytewordlen - 1 - $i) * 7); // faster, but runs into problems past 2^31 on 32-bit systems
385 $intvalue += (ord($byteword{$i}) & 0x7F) * pow(2,
386 ($bytewordlen - 1 - $i) * 7);
387 } else {
388 $intvalue += ord($byteword{$i}) * pow(256,
389 ($bytewordlen - 1 - $i));
390 }
391 }
392 if ($signed && !$synchsafe) {
393 // synchsafe ints are not allowed to be signed
394 if ($bytewordlen <= PHP_INT_SIZE) {
395 $signMaskBit = 0x80 << (8 * ($bytewordlen - 1));
396 if ($intvalue & $signMaskBit) {
397 $intvalue = 0 - ($intvalue & ($signMaskBit - 1));
398 }
399 } else {
400 throw new DefaultException('ERROR: Cannot have signed integers larger than ' . (8 * PHP_INT_SIZE) . '-bits (' . strlen($byteword) . ') in self::BigEndian2Int()');
401 }
402 }
403
404 return self::CastAsInt($intvalue);
405 }
406
413 public static function LittleEndian2Int($byteword, $signed = false)
414 {
415 return self::BigEndian2Int(strrev($byteword), false, $signed);
416 }
417
423 public static function BigEndian2Bin($byteword)
424 {
425 $binvalue = '';
426 $bytewordlen = strlen($byteword);
427 for ($i = 0; $i < $bytewordlen; $i++) {
428 $binvalue .= str_pad(decbin(ord($byteword{$i})), 8, '0',
429 STR_PAD_LEFT);
430 }
431
432 return $binvalue;
433 }
434
444 public static function BigEndian2String($number, $minbytes = 1,
445 $synchsafe = false, $signed = false)
446 {
447 if ($number < 0) {
448 throw new DefaultException('ERROR: self::BigEndian2String() does not support negative numbers');
449 }
450 $maskbyte = (($synchsafe || $signed) ? 0x7F : 0xFF);
451 $intstring = '';
452 if ($signed) {
453 if ($minbytes > PHP_INT_SIZE) {
454 throw new DefaultException('ERROR: Cannot have signed integers larger than ' . (8 * PHP_INT_SIZE) . '-bits in self::BigEndian2String()');
455 }
456 $number = $number & (0x80 << (8 * ($minbytes - 1)));
457 }
458 while ($number != 0) {
459 $quotient = ($number / ($maskbyte + 1));
460 $intstring = chr(ceil(($quotient - floor($quotient)) * $maskbyte)) . $intstring;
461 $number = floor($quotient);
462 }
463
464 return str_pad($intstring, $minbytes, "\x00", STR_PAD_LEFT);
465 }
466
472 public static function Dec2Bin($number)
473 {
474 while ($number >= 256) {
475 $bytes[] = (($number / 256) - (floor($number / 256))) * 256;
476 $number = floor($number / 256);
477 }
478 $bytes[] = $number;
479 $binstring = '';
480 for ($i = 0; $i < count($bytes); $i++) {
481 $binstring = (($i == count($bytes) - 1) ? decbin($bytes[$i]) : str_pad(decbin($bytes[$i]),
482 8,
483 '0',
484 STR_PAD_LEFT)) . $binstring;
485 }
486
487 return $binstring;
488 }
489
496 public static function Bin2Dec($binstring, $signed = false)
497 {
498 $signmult = 1;
499 if ($signed) {
500 if ($binstring{0} == '1') {
501 $signmult = -1;
502 }
503 $binstring = substr($binstring, 1);
504 }
505 $decvalue = 0;
506 for ($i = 0; $i < strlen($binstring); $i++) {
507 $decvalue += ((int) substr($binstring, strlen($binstring) - $i - 1,
508 1)) * pow(2, $i);
509 }
510
511 return self::CastAsInt($decvalue * $signmult);
512 }
513
519 public static function Bin2String($binstring)
520 {
521 // return 'hi' for input of '0110100001101001'
522 $string = '';
523 $binstringreversed = strrev($binstring);
524 for ($i = 0; $i < strlen($binstringreversed); $i += 8) {
525 $string = chr(self::Bin2Dec(strrev(substr($binstringreversed, $i, 8)))) . $string;
526 }
527
528 return $string;
529 }
530
538 public static function LittleEndian2String($number, $minbytes = 1,
539 $synchsafe = false)
540 {
541 $intstring = '';
542 while ($number > 0) {
543 if ($synchsafe) {
544 $intstring = $intstring . chr($number & 127);
545 $number >>= 7;
546 } else {
547 $intstring = $intstring . chr($number & 255);
548 $number >>= 8;
549 }
550 }
551
552 return str_pad($intstring, $minbytes, "\x00", STR_PAD_RIGHT);
553 }
554
561 public static function array_merge_clobber($array1, $array2)
562 {
563 // written by kcร˜hireability*com
564 // taken from http://www.php.net/manual/en/function.array-merge-recursive.php
565 if (!is_array($array1) || !is_array($array2)) {
566 return false;
567 }
568 $newarray = $array1;
569 foreach ($array2 as $key => $val) {
570 if (is_array($val) && isset($newarray[$key]) && is_array($newarray[$key])) {
571 $newarray[$key] = self::array_merge_clobber($newarray[$key],
572 $val);
573 } else {
574 $newarray[$key] = $val;
575 }
576 }
577
578 return $newarray;
579 }
580
587 public static function array_merge_noclobber($array1, $array2)
588 {
589 if (!is_array($array1) || !is_array($array2)) {
590 return false;
591 }
592 $newarray = $array1;
593 foreach ($array2 as $key => $val) {
594 if (is_array($val) && isset($newarray[$key]) && is_array($newarray[$key])) {
595 $newarray[$key] = self::array_merge_noclobber($newarray[$key],
596 $val);
597 } elseif (!isset($newarray[$key])) {
598 $newarray[$key] = $val;
599 }
600 }
601
602 return $newarray;
603 }
604
610 public static function ksort_recursive(&$theArray)
611 {
612 ksort($theArray);
613 foreach ($theArray as $key => $value) {
614 if (is_array($value)) {
615 self::ksort_recursive($theArray[$key]);
616 }
617 }
618
619 return true;
620 }
621
628 public static function fileextension($filename, $numextensions = 1)
629 {
630 if (strstr($filename, '.')) {
631 $reversedfilename = strrev($filename);
632 $offset = 0;
633 for ($i = 0; $i < $numextensions; $i++) {
634 $offset = strpos($reversedfilename, '.', $offset + 1);
635 if ($offset === false) {
636 return '';
637 }
638 }
639
640 return strrev(substr($reversedfilename, 0, $offset));
641 }
642
643 return '';
644 }
645
651 public static function PlaytimeString($seconds)
652 {
653 $sign = (($seconds < 0) ? '-' : '');
654 $seconds = round(abs($seconds));
655 $H = (int) floor($seconds / 3600);
656 $M = (int) floor(($seconds - (3600 * $H) ) / 60);
657 $S = (int) round($seconds - (3600 * $H) - (60 * $M));
658
659 return $sign . ($H ? $H . ':' : '') . ($H ? str_pad($M, 2, '0',
660 STR_PAD_LEFT) : intval($M)) . ':' . str_pad($S,
661 2,
662 0,
663 STR_PAD_LEFT);
664 }
665
671 public static function DateMac2Unix($macdate)
672 {
673 // Macintosh timestamp: seconds since 00:00h January 1, 1904
674 // UNIX timestamp: seconds since 00:00h January 1, 1970
675 return self::CastAsInt($macdate - 2082844800);
676 }
677
683 public static function FixedPoint8_8($rawdata)
684 {
685 return self::BigEndian2Int(substr($rawdata, 0, 1)) + (float) (self::BigEndian2Int(substr($rawdata,
686 1,
687 1)) / pow(2,
688 8));
689 }
690
696 public static function FixedPoint16_16($rawdata)
697 {
698 return self::BigEndian2Int(substr($rawdata, 0, 2)) + (float) (self::BigEndian2Int(substr($rawdata,
699 2,
700 2)) / pow(2,
701 16));
702 }
703
709 public static function FixedPoint2_30($rawdata)
710 {
711 $binarystring = self::BigEndian2Bin($rawdata);
712
713 return self::Bin2Dec(substr($binarystring, 0, 2)) + (float) (self::Bin2Dec(substr($binarystring,
714 2,
715 30)) / pow(2,
716 30));
717 }
718
726 public static function CreateDeepArray($ArrayPath, $Separator, $Value)
727 {
728 // assigns $Value to a nested array path:
729 // $foo = self::CreateDeepArray('/path/to/my', '/', 'file.txt')
730 // is the same as:
731 // $foo = array('path'=>array('to'=>'array('my'=>array('file.txt'))));
732 // or
733 // $foo['path']['to']['my'] = 'file.txt';
734 while ($ArrayPath && ($ArrayPath{0} == $Separator)) {
735 $ArrayPath = substr($ArrayPath, 1);
736 }
737 if (($pos = strpos($ArrayPath, $Separator)) !== false) {
738 $ReturnedArray[substr($ArrayPath, 0, $pos)] = self::CreateDeepArray(substr($ArrayPath,
739 $pos + 1),
740 $Separator,
741 $Value);
742 } else {
743 $ReturnedArray[$ArrayPath] = $Value;
744 }
745
746 return $ReturnedArray;
747 }
748
755 public static function array_max($arraydata, $returnkey = false)
756 {
757 $maxvalue = false;
758 $maxkey = false;
759 foreach ($arraydata as $key => $value) {
760 if (!is_array($value)) {
761 if ($value > $maxvalue) {
762 $maxvalue = $value;
763 $maxkey = $key;
764 }
765 }
766 }
767
768 return ($returnkey ? $maxkey : $maxvalue);
769 }
770
777 public static function array_min($arraydata, $returnkey = false)
778 {
779 $minvalue = false;
780 $minkey = false;
781 foreach ($arraydata as $key => $value) {
782 if (!is_array($value)) {
783 if ($value > $minvalue) {
784 $minvalue = $value;
785 $minkey = $key;
786 }
787 }
788 }
789
790 return ($returnkey ? $minkey : $minvalue);
791 }
792
798 public static function XML2array($XMLstring)
799 {
800 if (function_exists('simplexml_load_string')) {
801 if (function_exists('get_object_vars')) {
802 $XMLobject = simplexml_load_string($XMLstring);
803
804 return self::SimpleXMLelement2array($XMLobject);
805 }
806 }
807
808 return false;
809 }
810
816 public static function SimpleXMLelement2array($XMLobject)
817 {
818 if (!is_object($XMLobject) && !is_array($XMLobject)) {
819 return $XMLobject;
820 }
821 $XMLarray = (is_object($XMLobject) ? get_object_vars($XMLobject) : $XMLobject);
822 foreach ($XMLarray as $key => $value) {
823 $XMLarray[$key] = self::SimpleXMLelement2array($value);
824 }
825
826 return $XMLarray;
827 }
828
841 public static function hash_data($file, $offset, $end, $algorithm)
842 {
843 static $tempdir = '';
844 if (!self::intValueSupported($end)) {
845 return false;
846 }
847 switch ($algorithm) {
848 case 'md5':
849 $hash_function = 'md5_file';
850 $unix_call = 'md5sum';
851 $windows_call = 'md5sum.exe';
852 $hash_length = 32;
853 break;
854
855 case 'sha1':
856 $hash_function = 'sha1_file';
857 $unix_call = 'sha1sum';
858 $windows_call = 'sha1sum.exe';
859 $hash_length = 40;
860 break;
861
862 default:
863 throw new DefaultException('Invalid algorithm (' . $algorithm . ') in self::hash_data()');
864 break;
865 }
866 $size = $end - $offset;
867 while (true) {
869
870 // It seems that sha1sum.exe for Windows only works on physical files, does not accept piped data
871 // Fall back to create-temp-file method:
872 if ($algorithm == 'sha1') {
873 break;
874 }
875
876 $RequiredFiles = array('cygwin1.dll', 'head.exe', 'tail.exe', $windows_call);
877 foreach ($RequiredFiles as $required_file) {
878 if (!is_readable(GetId3Core::getHelperAppsDir() . $required_file)) {
879 // helper apps not available - fall back to old method
880 break 2;
881 }
882 }
883 $commandline = GetId3Core::getHelperAppsDir() . 'head.exe -c ' . $end . ' ' . escapeshellarg(str_replace('/',
884 DIRECTORY_SEPARATOR,
885 $file)) . ' | ';
886 $commandline .= GetId3Core::getHelperAppsDir() . 'tail.exe -c ' . $size . ' | ';
887 $commandline .= GetId3Core::getHelperAppsDir() . $windows_call;
888 } else {
889
890 $commandline = 'head -c' . $end . ' ' . escapeshellarg($file) . ' | ';
891 $commandline .= 'tail -c' . $size . ' | ';
892 $commandline .= $unix_call;
893 }
894 if (preg_match('#(1|ON)#i', ini_get('safe_mode'))) {
895 //throw new DefaultException('PHP running in Safe Mode - backtick operator not available, using slower non-system-call '.$algorithm.' algorithm');
896 break;
897 }
898
899 return substr(`$commandline`, 0, $hash_length);
900 }
901
902 if (empty($tempdir)) {
903 // yes this is ugly, feel free to suggest a better way
904 $getid3_temp = new GetId3Core();
905 $tempdir = $getid3_temp->tempdir;
906 unset($getid3_temp);
907 }
908 // try to create a temporary file in the system temp directory - invalid dirname should force to system temp dir
909 if (($data_filename = tempnam($tempdir, 'gI3')) === false) {
910 // can't find anywhere to create a temp file, just fail
911 return false;
912 }
913
914 // Init
915 $result = false;
916
917 // copy parts of file
918 try {
919 self::CopyFileParts($file, $data_filename, $offset, $end - $offset);
920 $result = $hash_function($data_filename);
921 } catch (DefaultException $e) {
922 throw new DefaultException('self::CopyFileParts() failed in getid_lib::hash_data(): ' . $e->getMessage());
923 }
924 unlink($data_filename);
925
926 return $result;
927 }
928
938 public static function CopyFileParts($filename_source, $filename_dest,
939 $offset, $length)
940 {
941 if (!self::intValueSupported($offset + $length)) {
942 throw new DefaultException('cannot copy file portion, it extends beyond the ' . round(PHP_INT_MAX / 1073741824) . 'GB limit');
943 }
944 if (is_readable($filename_source) && is_file($filename_source) && ($fp_src = fopen($filename_source,
945 'rb'))) {
946 if (($fp_dest = fopen($filename_dest, 'wb'))) {
947 if (fseek($fp_src, $offset, SEEK_SET) == 0) {
948 $byteslefttowrite = $length;
949 while (($byteslefttowrite > 0) && ($buffer = fread($fp_src,
950 min($byteslefttowrite,
952 $byteswritten = fwrite($fp_dest, $buffer,
953 $byteslefttowrite);
954 $byteslefttowrite -= $byteswritten;
955 }
956
957 return true;
958 } else {
959 throw new DefaultException('failed to seek to offset ' . $offset . ' in ' . $filename_source);
960 }
961 fclose($fp_dest);
962 } else {
963 throw new DefaultException('failed to create file for writing ' . $filename_dest);
964 }
965 fclose($fp_src);
966 } else {
967 throw new DefaultException('failed to open file for reading ' . $filename_source);
968 }
969
970 return false;
971 }
972
978 public static function iconv_fallback_int_utf8($charval)
979 {
980 if ($charval < 128) {
981 // 0bbbbbbb
982 $newcharstring = chr($charval);
983 } elseif ($charval < 2048) {
984 // 110bbbbb 10bbbbbb
985 $newcharstring = chr(($charval >> 6) | 0xC0);
986 $newcharstring .= chr(($charval & 0x3F) | 0x80);
987 } elseif ($charval < 65536) {
988 // 1110bbbb 10bbbbbb 10bbbbbb
989 $newcharstring = chr(($charval >> 12) | 0xE0);
990 $newcharstring .= chr(($charval >> 6) | 0xC0);
991 $newcharstring .= chr(($charval & 0x3F) | 0x80);
992 } else {
993 // 11110bbb 10bbbbbb 10bbbbbb 10bbbbbb
994 $newcharstring = chr(($charval >> 18) | 0xF0);
995 $newcharstring .= chr(($charval >> 12) | 0xC0);
996 $newcharstring .= chr(($charval >> 6) | 0xC0);
997 $newcharstring .= chr(($charval & 0x3F) | 0x80);
998 }
999
1000 return $newcharstring;
1001 }
1002
1010 public static function iconv_fallback_iso88591_utf8($string, $bom = false)
1011 {
1012 if (function_exists('utf8_encode')) {
1013 return utf8_encode($string);
1014 }
1015 // utf8_encode() unavailable, use GetId3Core()'s iconv_fallback() conversions (possibly PHP is compiled without XML support)
1016 $newcharstring = '';
1017 if ($bom) {
1018 $newcharstring .= "\xEF\xBB\xBF";
1019 }
1020 for ($i = 0; $i < strlen($string); $i++) {
1021 $charval = ord($string{$i});
1022 $newcharstring .= self::iconv_fallback_int_utf8($charval);
1023 }
1024
1025 return $newcharstring;
1026 }
1027
1035 public static function iconv_fallback_iso88591_utf16be($string, $bom = false)
1036 {
1037 $newcharstring = '';
1038 if ($bom) {
1039 $newcharstring .= "\xFE\xFF";
1040 }
1041 for ($i = 0; $i < strlen($string); $i++) {
1042 $newcharstring .= "\x00" . $string{$i};
1043 }
1044
1045 return $newcharstring;
1046 }
1047
1055 public static function iconv_fallback_iso88591_utf16le($string, $bom = false)
1056 {
1057 $newcharstring = '';
1058 if ($bom) {
1059 $newcharstring .= "\xFF\xFE";
1060 }
1061 for ($i = 0; $i < strlen($string); $i++) {
1062 $newcharstring .= $string{$i} . "\x00";
1063 }
1064
1065 return $newcharstring;
1066 }
1067
1074 public static function iconv_fallback_iso88591_utf16($string)
1075 {
1076 return self::iconv_fallback_iso88591_utf16le($string, true);
1077 }
1078
1085 public static function iconv_fallback_utf8_iso88591($string)
1086 {
1087 if (function_exists('utf8_decode')) {
1088 return utf8_decode($string);
1089 }
1090 // utf8_decode() unavailable, use GetId3Core()'s iconv_fallback() conversions (possibly PHP is compiled without XML support)
1091 $newcharstring = '';
1092 $offset = 0;
1093 $stringlength = strlen($string);
1094 while ($offset < $stringlength) {
1095 if ((ord($string{$offset}) | 0x07) == 0xF7) {
1096 // 11110bbb 10bbbbbb 10bbbbbb 10bbbbbb
1097 $charval = ((ord($string{($offset + 0)}) & 0x07) << 18) &
1098 ((ord($string{($offset + 1)}) & 0x3F) << 12) &
1099 ((ord($string{($offset + 2)}) & 0x3F) << 6) &
1100 (ord($string{($offset + 3)}) & 0x3F);
1101 $offset += 4;
1102 } elseif ((ord($string{$offset}) | 0x0F) == 0xEF) {
1103 // 1110bbbb 10bbbbbb 10bbbbbb
1104 $charval = ((ord($string{($offset + 0)}) & 0x0F) << 12) &
1105 ((ord($string{($offset + 1)}) & 0x3F) << 6) &
1106 (ord($string{($offset + 2)}) & 0x3F);
1107 $offset += 3;
1108 } elseif ((ord($string{$offset}) | 0x1F) == 0xDF) {
1109 // 110bbbbb 10bbbbbb
1110 $charval = ((ord($string{($offset + 0)}) & 0x1F) << 6) &
1111 (ord($string{($offset + 1)}) & 0x3F);
1112 $offset += 2;
1113 } elseif ((ord($string{$offset}) | 0x7F) == 0x7F) {
1114 // 0bbbbbbb
1115 $charval = ord($string{$offset});
1116 $offset += 1;
1117 } else {
1118 // error? throw some kind of warning here?
1119 $charval = false;
1120 $offset += 1;
1121 }
1122 if ($charval !== false) {
1123 $newcharstring .= (($charval < 256) ? chr($charval) : '?');
1124 }
1125 }
1126
1127 return $newcharstring;
1128 }
1129
1138 public static function iconv_fallback_utf8_utf16be($string, $bom = false)
1139 {
1140 $newcharstring = '';
1141 if ($bom) {
1142 $newcharstring .= "\xFE\xFF";
1143 }
1144 $offset = 0;
1145 $stringlength = strlen($string);
1146 while ($offset < $stringlength) {
1147 if ((ord($string{$offset}) | 0x07) == 0xF7) {
1148 // 11110bbb 10bbbbbb 10bbbbbb 10bbbbbb
1149 $charval = ((ord($string{($offset + 0)}) & 0x07) << 18) &
1150 ((ord($string{($offset + 1)}) & 0x3F) << 12) &
1151 ((ord($string{($offset + 2)}) & 0x3F) << 6) &
1152 (ord($string{($offset + 3)}) & 0x3F);
1153 $offset += 4;
1154 } elseif ((ord($string{$offset}) | 0x0F) == 0xEF) {
1155 // 1110bbbb 10bbbbbb 10bbbbbb
1156 $charval = ((ord($string{($offset + 0)}) & 0x0F) << 12) &
1157 ((ord($string{($offset + 1)}) & 0x3F) << 6) &
1158 (ord($string{($offset + 2)}) & 0x3F);
1159 $offset += 3;
1160 } elseif ((ord($string{$offset}) | 0x1F) == 0xDF) {
1161 // 110bbbbb 10bbbbbb
1162 $charval = ((ord($string{($offset + 0)}) & 0x1F) << 6) &
1163 (ord($string{($offset + 1)}) & 0x3F);
1164 $offset += 2;
1165 } elseif ((ord($string{$offset}) | 0x7F) == 0x7F) {
1166 // 0bbbbbbb
1167 $charval = ord($string{$offset});
1168 $offset += 1;
1169 } else {
1170 // error? throw some kind of warning here?
1171 $charval = false;
1172 $offset += 1;
1173 }
1174 if ($charval !== false) {
1175 $newcharstring .= (($charval < 65536) ? self::BigEndian2String($charval,
1176 2) : "\x00" . '?');
1177 }
1178 }
1179
1180 return $newcharstring;
1181 }
1182
1190 public static function iconv_fallback_utf8_utf16le($string, $bom = false)
1191 {
1192 $newcharstring = '';
1193 if ($bom) {
1194 $newcharstring .= "\xFF\xFE";
1195 }
1196 $offset = 0;
1197 $stringlength = strlen($string);
1198 while ($offset < $stringlength) {
1199 if ((ord($string{$offset}) | 0x07) == 0xF7) {
1200 // 11110bbb 10bbbbbb 10bbbbbb 10bbbbbb
1201 $charval = ((ord($string{($offset + 0)}) & 0x07) << 18) &
1202 ((ord($string{($offset + 1)}) & 0x3F) << 12) &
1203 ((ord($string{($offset + 2)}) & 0x3F) << 6) &
1204 (ord($string{($offset + 3)}) & 0x3F);
1205 $offset += 4;
1206 } elseif ((ord($string{$offset}) | 0x0F) == 0xEF) {
1207 // 1110bbbb 10bbbbbb 10bbbbbb
1208 $charval = ((ord($string{($offset + 0)}) & 0x0F) << 12) &
1209 ((ord($string{($offset + 1)}) & 0x3F) << 6) &
1210 (ord($string{($offset + 2)}) & 0x3F);
1211 $offset += 3;
1212 } elseif ((ord($string{$offset}) | 0x1F) == 0xDF) {
1213 // 110bbbbb 10bbbbbb
1214 $charval = ((ord($string{($offset + 0)}) & 0x1F) << 6) &
1215 (ord($string{($offset + 1)}) & 0x3F);
1216 $offset += 2;
1217 } elseif ((ord($string{$offset}) | 0x7F) == 0x7F) {
1218 // 0bbbbbbb
1219 $charval = ord($string{$offset});
1220 $offset += 1;
1221 } else {
1222 // error? maybe throw some warning here?
1223 $charval = false;
1224 $offset += 1;
1225 }
1226 if ($charval !== false) {
1227 $newcharstring .= (($charval < 65536) ? self::LittleEndian2String($charval,
1228 2) : '?' . "\x00");
1229 }
1230 }
1231
1232 return $newcharstring;
1233 }
1234
1241 public static function iconv_fallback_utf8_utf16($string)
1242 {
1243 return self::iconv_fallback_utf8_utf16le($string, true);
1244 }
1245
1252 public static function iconv_fallback_utf16be_utf8($string)
1253 {
1254 if (substr($string, 0, 2) == "\xFE\xFF") {
1255 // strip BOM
1256 $string = substr($string, 2);
1257 }
1258 $newcharstring = '';
1259 for ($i = 0; $i < strlen($string); $i += 2) {
1260 $charval = self::BigEndian2Int(substr($string, $i, 2));
1261 $newcharstring .= self::iconv_fallback_int_utf8($charval);
1262 }
1263
1264 return $newcharstring;
1265 }
1266
1273 public static function iconv_fallback_utf16le_utf8($string)
1274 {
1275 if (substr($string, 0, 2) == "\xFF\xFE") {
1276 // strip BOM
1277 $string = substr($string, 2);
1278 }
1279 $newcharstring = '';
1280 for ($i = 0; $i < strlen($string); $i += 2) {
1281 $charval = self::LittleEndian2Int(substr($string, $i, 2));
1282 $newcharstring .= self::iconv_fallback_int_utf8($charval);
1283 }
1284
1285 return $newcharstring;
1286 }
1287
1294 public static function iconv_fallback_utf16be_iso88591($string)
1295 {
1296 if (substr($string, 0, 2) == "\xFE\xFF") {
1297 // strip BOM
1298 $string = substr($string, 2);
1299 }
1300 $newcharstring = '';
1301 for ($i = 0; $i < strlen($string); $i += 2) {
1302 $charval = self::BigEndian2Int(substr($string, $i, 2));
1303 $newcharstring .= (($charval < 256) ? chr($charval) : '?');
1304 }
1305
1306 return $newcharstring;
1307 }
1308
1315 public static function iconv_fallback_utf16le_iso88591($string)
1316 {
1317 if (substr($string, 0, 2) == "\xFF\xFE") {
1318 // strip BOM
1319 $string = substr($string, 2);
1320 }
1321 $newcharstring = '';
1322 for ($i = 0; $i < strlen($string); $i += 2) {
1323 $charval = self::LittleEndian2Int(substr($string, $i, 2));
1324 $newcharstring .= (($charval < 256) ? chr($charval) : '?');
1325 }
1326
1327 return $newcharstring;
1328 }
1329
1336 public static function iconv_fallback_utf16_iso88591($string)
1337 {
1338 $bom = substr($string, 0, 2);
1339 if ($bom == "\xFE\xFF") {
1340 return self::iconv_fallback_utf16be_iso88591(substr($string, 2));
1341 } elseif ($bom == "\xFF\xFE") {
1342 return self::iconv_fallback_utf16le_iso88591(substr($string, 2));
1343 }
1344
1345 return $string;
1346 }
1347
1354 public static function iconv_fallback_utf16_utf8($string)
1355 {
1356 $bom = substr($string, 0, 2);
1357 if ($bom == "\xFE\xFF") {
1358 return self::iconv_fallback_utf16be_utf8(substr($string, 2));
1359 } elseif ($bom == "\xFF\xFE") {
1360 return self::iconv_fallback_utf16le_utf8(substr($string, 2));
1361 }
1362
1363 return $string;
1364 }
1365
1375 public static function iconv_fallback($in_charset, $out_charset, $string)
1376 {
1377
1378 if ($in_charset == $out_charset) {
1379 return $string;
1380 }
1381
1382 // iconv() availble
1383 if (function_exists('iconv')) {
1384 if ($converted_string = @iconv($in_charset,
1385 $out_charset . '//TRANSLIT', $string)) {
1386 switch ($out_charset) {
1387 case 'ISO-8859-1':
1388 $converted_string = rtrim($converted_string, "\x00");
1389 break;
1390 }
1391
1392 return $converted_string;
1393 }
1394
1395 // iconv() may sometimes fail with "illegal character in input string" error message
1396 // and return an empty string, but returning the unconverted string is more useful
1397 return $string;
1398 }
1399
1400
1401 // iconv() not available
1402 static $ConversionFunctionList = array();
1403 if (empty($ConversionFunctionList)) {
1404 $ConversionFunctionList['ISO-8859-1']['UTF-8'] = 'iconv_fallback_iso88591_utf8';
1405 $ConversionFunctionList['ISO-8859-1']['UTF-16'] = 'iconv_fallback_iso88591_utf16';
1406 $ConversionFunctionList['ISO-8859-1']['UTF-16BE'] = 'iconv_fallback_iso88591_utf16be';
1407 $ConversionFunctionList['ISO-8859-1']['UTF-16LE'] = 'iconv_fallback_iso88591_utf16le';
1408 $ConversionFunctionList['UTF-8']['ISO-8859-1'] = 'iconv_fallback_utf8_iso88591';
1409 $ConversionFunctionList['UTF-8']['UTF-16'] = 'iconv_fallback_utf8_utf16';
1410 $ConversionFunctionList['UTF-8']['UTF-16BE'] = 'iconv_fallback_utf8_utf16be';
1411 $ConversionFunctionList['UTF-8']['UTF-16LE'] = 'iconv_fallback_utf8_utf16le';
1412 $ConversionFunctionList['UTF-16']['ISO-8859-1'] = 'iconv_fallback_utf16_iso88591';
1413 $ConversionFunctionList['UTF-16']['UTF-8'] = 'iconv_fallback_utf16_utf8';
1414 $ConversionFunctionList['UTF-16LE']['ISO-8859-1'] = 'iconv_fallback_utf16le_iso88591';
1415 $ConversionFunctionList['UTF-16LE']['UTF-8'] = 'iconv_fallback_utf16le_utf8';
1416 $ConversionFunctionList['UTF-16BE']['ISO-8859-1'] = 'iconv_fallback_utf16be_iso88591';
1417 $ConversionFunctionList['UTF-16BE']['UTF-8'] = 'iconv_fallback_utf16be_utf8';
1418 }
1419 if (isset($ConversionFunctionList[strtoupper($in_charset)][strtoupper($out_charset)])) {
1420 $ConversionFunction = $ConversionFunctionList[strtoupper($in_charset)][strtoupper($out_charset)];
1421
1422 return self::$ConversionFunction($string);
1423 }
1424 throw new DefaultException('PHP does not have iconv() support - cannot convert from ' . $in_charset . ' to ' . $out_charset);
1425 }
1426
1433 public static function MultiByteCharString2HTML($string,
1434 $charset = 'ISO-8859-1')
1435 {
1436 $string = (string) $string; // in case trying to pass a numeric (float, int) string, would otherwise return an empty string
1437 $HTMLstring = '';
1438
1439 switch ($charset) {
1440 case '1251':
1441 case '1252':
1442 case '866':
1443 case '932':
1444 case '936':
1445 case '950':
1446 case 'BIG5':
1447 case 'BIG5-HKSCS':
1448 case 'cp1251':
1449 case 'cp1252':
1450 case 'cp866':
1451 case 'EUC-JP':
1452 case 'EUCJP':
1453 case 'GB2312':
1454 case 'ibm866':
1455 case 'ISO-8859-1':
1456 case 'ISO-8859-15':
1457 case 'ISO8859-1':
1458 case 'ISO8859-15':
1459 case 'KOI8-R':
1460 case 'koi8-ru':
1461 case 'koi8r':
1462 case 'Shift_JIS':
1463 case 'SJIS':
1464 case 'win-1251':
1465 case 'Windows-1251':
1466 case 'Windows-1252':
1467 $HTMLstring = htmlentities($string, ENT_COMPAT, $charset);
1468 break;
1469
1470 case 'UTF-8':
1471 $strlen = strlen($string);
1472 for ($i = 0; $i < $strlen; $i++) {
1473 $char_ord_val = ord($string{$i});
1474 $charval = 0;
1475 if ($char_ord_val < 0x80) {
1476 $charval = $char_ord_val;
1477 } elseif ((($char_ord_val & 0xF0) >> 4) == 0x0F && $i + 3 < $strlen) {
1478 $charval = (($char_ord_val & 0x07) << 18);
1479 $charval += ((ord($string{++$i}) & 0x3F) << 12);
1480 $charval += ((ord($string{++$i}) & 0x3F) << 6);
1481 $charval += (ord($string{++$i}) & 0x3F);
1482 } elseif ((($char_ord_val & 0xE0) >> 5) == 0x07 && $i + 2 < $strlen) {
1483 $charval = (($char_ord_val & 0x0F) << 12);
1484 $charval += ((ord($string{++$i}) & 0x3F) << 6);
1485 $charval += (ord($string{++$i}) & 0x3F);
1486 } elseif ((($char_ord_val & 0xC0) >> 6) == 0x03 && $i + 1 < $strlen) {
1487 $charval = (($char_ord_val & 0x1F) << 6);
1488 $charval += (ord($string{++$i}) & 0x3F);
1489 }
1490 if (($charval >= 32) && ($charval <= 127)) {
1491 $HTMLstring .= htmlentities(chr($charval));
1492 } else {
1493 $HTMLstring .= '&#' . $charval . ';';
1494 }
1495 }
1496 break;
1497
1498 case 'UTF-16LE':
1499 for ($i = 0; $i < strlen($string); $i += 2) {
1500 $charval = self::LittleEndian2Int(substr($string, $i, 2));
1501 if (($charval >= 32) && ($charval <= 127)) {
1502 $HTMLstring .= chr($charval);
1503 } else {
1504 $HTMLstring .= '&#' . $charval . ';';
1505 }
1506 }
1507 break;
1508
1509 case 'UTF-16BE':
1510 for ($i = 0; $i < strlen($string); $i += 2) {
1511 $charval = self::BigEndian2Int(substr($string, $i, 2));
1512 if (($charval >= 32) && ($charval <= 127)) {
1513 $HTMLstring .= chr($charval);
1514 } else {
1515 $HTMLstring .= '&#' . $charval . ';';
1516 }
1517 }
1518 break;
1519
1520 default:
1521 $HTMLstring = 'ERROR: Character set "' . $charset . '" not supported in MultiByteCharString2HTML()';
1522 break;
1523 }
1524
1525 return $HTMLstring;
1526 }
1527
1534 public static function RGADnameLookup($namecode)
1535 {
1536 static $RGADname = array();
1537 if (empty($RGADname)) {
1538 $RGADname[0] = 'not set';
1539 $RGADname[1] = 'Track Gain Adjustment';
1540 $RGADname[2] = 'Album Gain Adjustment';
1541 }
1542
1543 return (isset($RGADname[$namecode]) ? $RGADname[$namecode] : '');
1544 }
1545
1552 public static function RGADoriginatorLookup($originatorcode)
1553 {
1554 static $RGADoriginator = array();
1555 if (empty($RGADoriginator)) {
1556 $RGADoriginator[0] = 'unspecified';
1557 $RGADoriginator[1] = 'pre-set by artist/producer/mastering engineer';
1558 $RGADoriginator[2] = 'set by user';
1559 $RGADoriginator[3] = 'determined automatically';
1560 }
1561
1562 return (isset($RGADoriginator[$originatorcode]) ? $RGADoriginator[$originatorcode] : '');
1563 }
1564
1571 public static function RGADadjustmentLookup($rawadjustment, $signbit)
1572 {
1573 $adjustment = $rawadjustment / 10;
1574 if ($signbit == 1) {
1575 $adjustment *= -1;
1576 }
1577
1578 return (float) $adjustment;
1579 }
1580
1588 public static function RGADgainString($namecode, $originatorcode,
1589 $replaygain)
1590 {
1591 if ($replaygain < 0) {
1592 $signbit = '1';
1593 } else {
1594 $signbit = '0';
1595 }
1596 $storedreplaygain = intval(round($replaygain * 10));
1597 $gainstring = str_pad(decbin($namecode), 3, '0', STR_PAD_LEFT);
1598 $gainstring .= str_pad(decbin($originatorcode), 3, '0', STR_PAD_LEFT);
1599 $gainstring .= $signbit;
1600 $gainstring .= str_pad(decbin($storedreplaygain), 9, '0', STR_PAD_LEFT);
1601
1602 return $gainstring;
1603 }
1604
1610 public static function RGADamplitude2dB($amplitude)
1611 {
1612 return 20 * log10($amplitude);
1613 }
1614
1622 public static function GetDataImageSize($imgData, &$imageinfo)
1623 {
1624 static $tempdir = '';
1625 if (empty($tempdir)) {
1626 // yes this is ugly, feel free to suggest a better way
1627 $getid3_temp = new GetId3Core();
1628 $tempdir = $getid3_temp->tempdir;
1629 unset($getid3_temp);
1630 }
1631 $GetDataImageSize = false;
1632 if ($tempfilename = tempnam($tempdir, 'gI3')) {
1633 if (is_writable($tempfilename) && is_file($tempfilename) && ($tmp = fopen($tempfilename,
1634 'wb'))) {
1635 fwrite($tmp, $imgData);
1636 fclose($tmp);
1637 $GetDataImageSize = @GetImageSize($tempfilename, $imageinfo);
1638 }
1639 unlink($tempfilename);
1640 }
1641
1642 return $GetDataImageSize;
1643 }
1644
1651 public static function ImageTypesLookup($imagetypeid)
1652 {
1653 static $ImageTypesLookup = array();
1654 if (empty($ImageTypesLookup)) {
1655 $ImageTypesLookup[1] = 'gif';
1656 $ImageTypesLookup[2] = 'jpeg';
1657 $ImageTypesLookup[3] = 'png';
1658 $ImageTypesLookup[4] = 'swf';
1659 $ImageTypesLookup[5] = 'psd';
1660 $ImageTypesLookup[6] = 'bmp';
1661 $ImageTypesLookup[7] = 'tiff (little-endian)';
1662 $ImageTypesLookup[8] = 'tiff (big-endian)';
1663 $ImageTypesLookup[9] = 'jpc';
1664 $ImageTypesLookup[10] = 'jp2';
1665 $ImageTypesLookup[11] = 'jpx';
1666 $ImageTypesLookup[12] = 'jb2';
1667 $ImageTypesLookup[13] = 'swc';
1668 $ImageTypesLookup[14] = 'iff';
1669 }
1670
1671 return (isset($ImageTypesLookup[$imagetypeid]) ? $ImageTypesLookup[$imagetypeid] : '');
1672 }
1673
1679 public static function CopyTagsToComments(&$ThisFileInfo)
1680 {
1681
1682 // Copy all entries from ['tags'] into common ['comments']
1683 if (!empty($ThisFileInfo['tags'])) {
1684 foreach ($ThisFileInfo['tags'] as $tagtype => $tagarray) {
1685 foreach ($tagarray as $tagname => $tagdata) {
1686 foreach ($tagdata as $key => $value) {
1687 if (!empty($value)) {
1688 if (empty($ThisFileInfo['comments'][$tagname])) {
1689
1690 // fall through and append value
1691 } elseif ($tagtype == 'id3v1') {
1692
1693 $newvaluelength = strlen(trim($value));
1694 foreach ($ThisFileInfo['comments'][$tagname] as $existingkey => $existingvalue) {
1695 $oldvaluelength = strlen(trim($existingvalue));
1696 if (($newvaluelength <= $oldvaluelength) && (substr($existingvalue,
1697 0,
1698 $newvaluelength) == trim($value))) {
1699 // new value is identical but shorter-than (or equal-length to) one already in comments - skip
1700 break 2;
1701 }
1702 }
1703 } elseif (!is_array($value)) {
1704
1705 $newvaluelength = strlen(trim($value));
1706 foreach ($ThisFileInfo['comments'][$tagname] as $existingkey => $existingvalue) {
1707 $oldvaluelength = strlen(trim($existingvalue));
1708 if (($newvaluelength > $oldvaluelength) && (substr(trim($value),
1709 0,
1710 strlen($existingvalue)) == $existingvalue)) {
1711 $ThisFileInfo['comments'][$tagname][$existingkey] = trim($value);
1712 break 2;
1713 }
1714 }
1715 }
1716 if (is_array($value) || empty($ThisFileInfo['comments'][$tagname]) || !in_array(trim($value),
1717 $ThisFileInfo['comments'][$tagname])) {
1718 $value = (is_string($value) ? trim($value) : $value);
1719 $ThisFileInfo['comments'][$tagname][] = $value;
1720 }
1721 }
1722 }
1723 }
1724 }
1725
1726 // Copy to ['comments_html']
1727 foreach ($ThisFileInfo['comments'] as $field => $values) {
1728 if ($field == 'picture') {
1729 // pictures can take up a lot of space, and we don't need multiple copies of them
1730 // let there be a single copy in [comments][picture], and not elsewhere
1731 continue;
1732 }
1733 foreach ($values as $index => $value) {
1734 if (is_array($value)) {
1735 $ThisFileInfo['comments_html'][$field][$index] = $value;
1736 } else {
1737 $ThisFileInfo['comments_html'][$field][$index] = str_replace('&#0;',
1738 '',
1739 self::MultiByteCharString2HTML($value,
1740 $ThisFileInfo['encoding']));
1741 }
1742 }
1743 }
1744 }
1745
1746 return true;
1747 }
1748
1759 public static function EmbeddedLookup($key, $begin, $end, $file, $name)
1760 {
1761
1762 // Cached
1763 static $cache;
1764 if (isset($cache[$file][$name])) {
1765 return (isset($cache[$file][$name][$key]) ? $cache[$file][$name][$key] : '');
1766 }
1767
1768 // Init
1769 $keylength = strlen($key);
1770 $line_count = $end - $begin - 7;
1771
1772 // Open php file
1773 $fp = fopen($file, 'r');
1774
1775 // Discard $begin lines
1776 for ($i = 0; $i < ($begin + 3); $i++) {
1777 fgets($fp, 1024);
1778 }
1779
1780 // Loop thru line
1781 while (0 < $line_count--) {
1782
1783 // Read line
1784 $line = ltrim(fgets($fp, 1024), "\t ");
1785
1786 // METHOD A: only cache the matching key - less memory but slower on next lookup of not-previously-looked-up key
1787 //$keycheck = substr($line, 0, $keylength);
1788 //if ($key == $keycheck) {
1789 // $cache[$file][$name][$keycheck] = substr($line, $keylength + 1);
1790 // break;
1791 //}
1792 // METHOD B: cache all keys in this lookup - more memory but faster on next lookup of not-previously-looked-up key
1793 //$cache[$file][$name][substr($line, 0, $keylength)] = trim(substr($line, $keylength + 1));
1794 $explodedLine = explode("\t", $line, 2);
1795 $ThisKey = (isset($explodedLine[0]) ? $explodedLine[0] : '');
1796 $ThisValue = (isset($explodedLine[1]) ? $explodedLine[1] : '');
1797 $cache[$file][$name][$ThisKey] = trim($ThisValue);
1798 }
1799
1800 // Close and return
1801 fclose($fp);
1802
1803 return (isset($cache[$file][$name][$key]) ? $cache[$file][$name][$key] : '');
1804 }
1805
1811 public static function trimNullByte($string)
1812 {
1813 return trim($string, "\x00");
1814 }
1815
1823 public static function toCamelCase($origin, $cahrToReplace = '_', $capitaliseFirstChar = false)
1824 {
1825 if ($capitaliseFirstChar) {
1826 $origin = ucfirst($origin);
1827 }
1828 $func = create_function('$c', 'return strtoupper($c[1]);');
1829
1830 return preg_replace_callback('/' . $cahrToReplace . '([a-z])/', $func, $origin);
1831 }
1832}
$result
$size
Definition: RandomTest.php:79
An exception for terminatinating execution or to throw for unit testing.
GetId3() by James Heinrich info@getid3.org //.
Definition: GetId3Core.php:26
static environmentIsWindows()
const FREAD_BUFFER_SIZE
Definition: GetId3Core.php:63
static getHelperAppsDir()
Definition: GetId3Core.php:186
GetId3() by James Heinrich info@getid3.org //.
Definition: Helper.php:27
static safe_inc(&$variable, $increment=1)
Definition: Helper.php:91
static CopyFileParts($filename_source, $filename_dest, $offset, $length)
Definition: Helper.php:938
static Bin2Dec($binstring, $signed=false)
Definition: Helper.php:496
static Float2BinaryDecimal($floatvalue)
Definition: Helper.php:214
static array_merge_clobber($array1, $array2)
Definition: Helper.php:561
static toCamelCase($origin, $cahrToReplace='_', $capitaliseFirstChar=false)
Definition: Helper.php:1823
static BigEndian2Int($byteword, $synchsafe=false, $signed=false)
Definition: Helper.php:374
static iconv_fallback_utf16le_iso88591($string)
UTF-16LE => ISO-8859-1.
Definition: Helper.php:1315
static FixedPoint16_16($rawdata)
Definition: Helper.php:696
static RGADoriginatorLookup($originatorcode)
@staticvar array $RGADoriginator
Definition: Helper.php:1552
static Bin2String($binstring)
Definition: Helper.php:519
static iconv_fallback_utf16_iso88591($string)
UTF-16 (BOM) => ISO-8859-1.
Definition: Helper.php:1336
static DecimalizeFraction($fraction)
Definition: Helper.php:153
static iconv_fallback_utf8_utf16le($string, $bom=false)
UTF-8 => UTF-16LE.
Definition: Helper.php:1190
static iconv_fallback_utf16le_utf8($string)
UTF-16LE => UTF-8.
Definition: Helper.php:1273
static iconv_fallback_iso88591_utf16le($string, $bom=false)
ISO-8859-1 => UTF-16LE.
Definition: Helper.php:1055
static LittleEndian2Float($byteword)
Definition: Helper.php:277
static intValueSupported($num)
@staticvar null $hasINT64
Definition: Helper.php:130
static iconv_fallback_iso88591_utf16($string)
ISO-8859-1 => UTF-16LE (BOM)
Definition: Helper.php:1074
static Float2String($floatvalue, $bits)
Definition: Helper.php:237
static trimNullByte($string)
Definition: Helper.php:1811
static iconv_fallback_iso88591_utf16be($string, $bom=false)
ISO-8859-1 => UTF-16BE.
Definition: Helper.php:1035
static trunc($floatnumber)
Definition: Helper.php:67
static SimpleXMLelement2array($XMLobject)
Definition: Helper.php:816
static iconv_fallback_iso88591_utf8($string, $bom=false)
ISO-8859-1 => UTF-8.
Definition: Helper.php:1010
static RGADamplitude2dB($amplitude)
Definition: Helper.php:1610
static iconv_fallback_utf16be_iso88591($string)
UTF-16BE => ISO-8859-1.
Definition: Helper.php:1294
static array_min($arraydata, $returnkey=false)
Definition: Helper.php:777
static ImageTypesLookup($imagetypeid)
@staticvar array $ImageTypesLookup
Definition: Helper.php:1651
static iconv_fallback_utf16be_utf8($string)
UTF-16BE => UTF-8.
Definition: Helper.php:1252
static iconv_fallback($in_charset, $out_charset, $string)
@staticvar array $ConversionFunctionList
Definition: Helper.php:1375
static LittleEndian2String($number, $minbytes=1, $synchsafe=false)
Definition: Helper.php:538
static EmbeddedLookup($key, $begin, $end, $file, $name)
@staticvar type $cache
Definition: Helper.php:1759
static XML2array($XMLstring)
Definition: Helper.php:798
static fileextension($filename, $numextensions=1)
Definition: Helper.php:628
static DecimalBinary2Float($binarynumerator)
Definition: Helper.php:165
static iconv_fallback_utf8_utf16($string)
UTF-8 => UTF-16LE (BOM)
Definition: Helper.php:1241
static array_max($arraydata, $returnkey=false)
Definition: Helper.php:755
static iconv_fallback_utf8_iso88591($string)
UTF-8 => ISO-8859-1.
Definition: Helper.php:1085
static array_merge_noclobber($array1, $array2)
Definition: Helper.php:587
static hash_data($file, $offset, $end, $algorithm)
self::md5_data() - returns md5sum for a file from startuing position to absolute end position
Definition: Helper.php:841
static RGADgainString($namecode, $originatorcode, $replaygain)
Definition: Helper.php:1588
static BigEndian2Float($byteword)
ANSI/IEEE Standard 754-1985, Standard for Binary Floating Point Arithmetic.
Definition: Helper.php:290
static ksort_recursive(&$theArray)
Definition: Helper.php:610
static PlaytimeString($seconds)
Definition: Helper.php:651
static LittleEndian2Int($byteword, $signed=false)
Definition: Helper.php:413
static PrintHexBytes($string, $hex=true, $spaces=true, $htmlencoding='UTF-8')
Definition: Helper.php:36
static MultiByteCharString2HTML($string, $charset='ISO-8859-1')
Definition: Helper.php:1433
static CreateDeepArray($ArrayPath, $Separator, $Value)
Definition: Helper.php:726
static RGADadjustmentLookup($rawadjustment, $signbit)
Definition: Helper.php:1571
static Dec2Bin($number)
Definition: Helper.php:472
static iconv_fallback_utf8_utf16be($string, $bom=false)
UTF-8 => UTF-16BE.
Definition: Helper.php:1138
static iconv_fallback_int_utf8($charval)
Definition: Helper.php:978
static FixedPoint2_30($rawdata)
Definition: Helper.php:709
static BigEndian2Bin($byteword)
Definition: Helper.php:423
static CastAsInt($floatnum)
Definition: Helper.php:107
static GetDataImageSize($imgData, &$imageinfo)
@staticvar string $tempdir
Definition: Helper.php:1622
static RGADnameLookup($namecode)
@staticvar array $RGADname
Definition: Helper.php:1534
static NormalizeBinaryPoint($binarypointnumber, $maxbits=52)
Definition: Helper.php:180
static BigEndian2String($number, $minbytes=1, $synchsafe=false, $signed=false)
Definition: Helper.php:444
static CopyTagsToComments(&$ThisFileInfo)
Definition: Helper.php:1679
static FixedPoint8_8($rawdata)
Definition: Helper.php:683
static iconv_fallback_utf16_utf8($string)
UTF-16 (BOM) => UTF-8.
Definition: Helper.php:1354
static DateMac2Unix($macdate)
Definition: Helper.php:671
defined( 'APPLICATION_ENV')||define( 'APPLICATION_ENV'
Definition: bootstrap.php:27
if(!file_exists("$old.txt")) if( $old===$new) if(file_exists("$new.txt")) $file