PageRenderTime 55ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/getid3/getid3.lib.php

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