PageRenderTime 57ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 1ms

/mc_podcast/getid3/getid3.lib.php

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