PageRenderTime 3213ms CodeModel.GetById 164ms app.highlight 1688ms RepoModel.GetById 536ms app.codeStats 1ms

/common/libraries/plugin/getid3/demos/demo.mp3header.php

https://bitbucket.org/chamilo/chamilo/
PHP | 1785 lines | 1408 code | 218 blank | 159 comment | 411 complexity | 0509f104cfa1896cfa61831ca37dfb01 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1<?php
   2
   3if (!function_exists('PrintHexBytes')) {
   4	function PrintHexBytes($string) {
   5		$returnstring = '';
   6		for ($i = 0; $i < strlen($string); $i++) {
   7			$returnstring .= str_pad(dechex(ord(substr($string, $i, 1))), 2, '0', STR_PAD_LEFT).' ';
   8		}
   9		return $returnstring;
  10	}
  11}
  12
  13if (!function_exists('PrintTextBytes')) {
  14	function PrintTextBytes($string) {
  15		$returnstring = '';
  16		for ($i = 0; $i < strlen($string); $i++) {
  17			if (ord(substr($string, $i, 1)) <= 31) {
  18				$returnstring .= '   ';
  19			} else {
  20				$returnstring .= ' '.substr($string, $i, 1).' ';
  21			}
  22		}
  23		return $returnstring;
  24	}
  25}
  26
  27if (!function_exists('FixDBFields')) {
  28	function FixDBFields($text) {
  29		return mysql_escape_string($text);
  30	}
  31}
  32
  33if (!function_exists('FixTextFields')) {
  34	function FixTextFields($text) {
  35		$text = SafeStripSlashes($text);
  36		$text = htmlentities($text, ENT_QUOTES);
  37		return $text;
  38	}
  39}
  40
  41if (!function_exists('SafeStripSlashes')) {
  42	function SafeStripSlashes($text) {
  43		if (get_magic_quotes_gpc()) {
  44			return stripslashes($text);
  45		}
  46		return $text;
  47	}
  48}
  49
  50
  51if (!function_exists('table_var_dump')) {
  52	function table_var_dump($variable) {
  53		$returnstring = '';
  54		switch (gettype($variable)) {
  55			case 'array':
  56				$returnstring .= '<TABLE BORDER="1" CELLSPACING="0" CELLPADDING="2">';
  57				foreach ($variable as $key => $value) {
  58					$returnstring .= '<TR><TD VALIGN="TOP"><B>'.str_replace(chr(0), ' ', $key).'</B></TD>';
  59					$returnstring .= '<TD VALIGN="TOP">'.gettype($value);
  60					if (is_array($value)) {
  61						$returnstring .= '&nbsp;('.count($value).')';
  62					} elseif (is_string($value)) {
  63						$returnstring .= '&nbsp;('.strlen($value).')';
  64					}
  65					if (($key == 'data') && isset($variable['image_mime']) && isset($variable['dataoffset'])) {
  66						require_once(GETID3_INCLUDEPATH.'getid3.getimagesize.php');
  67						$imageinfo = array();
  68						$imagechunkcheck = GetDataImageSize($value, $imageinfo);
  69						$DumpedImageSRC = (!empty($_REQUEST['filename']) ? $_REQUEST['filename'] : '.getid3').'.'.$variable['dataoffset'].'.'.ImageTypesLookup($imagechunkcheck[2]);
  70						if ($tempimagefile = fopen($DumpedImageSRC, 'wb')) {
  71							fwrite($tempimagefile, $value);
  72							fclose($tempimagefile);
  73						}
  74						$returnstring .= '</TD><TD><IMG SRC="'.$DumpedImageSRC.'" WIDTH="'.$imagechunkcheck[0].'" HEIGHT="'.$imagechunkcheck[1].'"></TD></TR>';
  75					} else {
  76						$returnstring .= '</TD><TD>'.table_var_dump($value).'</TD></TR>';
  77					}
  78				}
  79				$returnstring .= '</TABLE>';
  80				break;
  81
  82			case 'boolean':
  83				$returnstring .= ($variable ? 'TRUE' : 'FALSE');
  84				break;
  85
  86			case 'integer':
  87			case 'double':
  88			case 'float':
  89				$returnstring .= $variable;
  90				break;
  91
  92			case 'object':
  93			case 'null':
  94				$returnstring .= string_var_dump($variable);
  95				break;
  96
  97			case 'string':
  98				$variable = str_replace(chr(0), ' ', $variable);
  99				$varlen = strlen($variable);
 100				for ($i = 0; $i < $varlen; $i++) {
 101					if (ereg('['.chr(0x0A).chr(0x0D).' -;0-9A-Za-z]', $variable{$i})) {
 102						$returnstring .= $variable{$i};
 103					} else {
 104						$returnstring .= '&#'.str_pad(ord($variable{$i}), 3, '0', STR_PAD_LEFT).';';
 105					}
 106				}
 107				$returnstring = nl2br($returnstring);
 108				break;
 109
 110			default:
 111				require_once(GETID3_INCLUDEPATH.'getid3.getimagesize.php');
 112				$imageinfo = array();
 113				$imagechunkcheck = GetDataImageSize(substr($variable, 0, FREAD_BUFFER_SIZE), $imageinfo);
 114
 115				if (($imagechunkcheck[2] >= 1) && ($imagechunkcheck[2] <= 3)) {
 116					$returnstring .= '<TABLE BORDER="1" CELLSPACING="0" CELLPADDING="2">';
 117					$returnstring .= '<TR><TD><B>type</B></TD><TD>'.ImageTypesLookup($imagechunkcheck[2]).'</TD></TR>';
 118					$returnstring .= '<TR><TD><B>width</B></TD><TD>'.number_format($imagechunkcheck[0]).' px</TD></TR>';
 119					$returnstring .= '<TR><TD><B>height</B></TD><TD>'.number_format($imagechunkcheck[1]).' px</TD></TR>';
 120					$returnstring .= '<TR><TD><B>size</B></TD><TD>'.number_format(strlen($variable)).' bytes</TD></TR></TABLE>';
 121				} else {
 122					$returnstring .= nl2br(htmlspecialchars(str_replace(chr(0), ' ', $variable)));
 123				}
 124				break;
 125		}
 126		return $returnstring;
 127	}
 128}
 129
 130if (!function_exists('string_var_dump')) {
 131	function string_var_dump($variable) {
 132		ob_start();
 133		var_dump($variable);
 134		$dumpedvariable = ob_get_contents();
 135		ob_end_clean();
 136		return $dumpedvariable;
 137	}
 138}
 139
 140if (!function_exists('fileextension')) {
 141	function fileextension($filename, $numextensions=1) {
 142		if (strstr($filename, '.')) {
 143			$reversedfilename = strrev($filename);
 144			$offset = 0;
 145			for ($i = 0; $i < $numextensions; $i++) {
 146				$offset = strpos($reversedfilename, '.', $offset + 1);
 147				if ($offset === false) {
 148					return '';
 149				}
 150			}
 151			return strrev(substr($reversedfilename, 0, $offset));
 152		}
 153		return '';
 154	}
 155}
 156
 157if (!function_exists('RemoveAccents')) {
 158	function RemoveAccents($string) {
 159		// return strtr($string, '&#x160;&#x152;&#x17D;&#x161;&#x153;&#x17E;&#x;???ÁÂ?Ä??Ç?É?Ë?ÍÎ????ÓÔ?Ö??Ú?ÜÝß?áâ?ä??ç?é?ë?íî????óô?ö??ú?üý?', 'SOZsozYYuAAAAAAACEEEEIIIIDNOOOOOOUUUUYsaaaaaaaceeeeiiiionoooooouuuuyy');
 160		// Revised version by marksteward@hotmail.com
 161		return strtr(strtr($string, '&#x160;&#x17D;&#x161;&#x17E;&#x;?ÁÂ?Ä?Ç?É?Ë?ÍÎ???ÓÔ?Ö??Ú?ÜÝ?áâ?ä?ç?é?ë?íî???óô?ö??ú?üý?', 'SZszYAAAAAACEEEEIIIINOOOOOOUUUUYaaaaaaceeeeiiiinoooooouuuuyy'), array('?' => 'TH', '?' => 'th', '?' => 'DH', '?' => 'dh', 'ß' => 'ss', '&#x152;' => 'OE', '&#x153;' => 'oe', '?' => 'AE', '?' => 'ae', '?' => 'u'));
 162	}
 163}
 164
 165if (!function_exists('MoreNaturalSort')) {
 166	function MoreNaturalSort($ar1, $ar2) {
 167		if ($ar1 === $ar2) {
 168			return 0;
 169		}
 170		$len1     = strlen($ar1);
 171		$len2     = strlen($ar2);
 172		$shortest = min($len1, $len2);
 173		if (substr($ar1, 0, $shortest) === substr($ar2, 0, $shortest)) {
 174			// the shorter argument is the beginning of the longer one, like "str" and "string"
 175			if ($len1 < $len2) {
 176				return -1;
 177			} elseif ($len1 > $len2) {
 178				return 1;
 179			}
 180			return 0;
 181		}
 182		$ar1 = RemoveAccents(strtolower(trim($ar1)));
 183		$ar2 = RemoveAccents(strtolower(trim($ar2)));
 184		$translatearray = array('\''=>'', '"'=>'', '_'=>' ', '('=>'', ')'=>'', '-'=>' ', '  '=>' ', '.'=>'', ','=>'');
 185		foreach ($translatearray as $key => $val) {
 186			$ar1 = str_replace($key, $val, $ar1);
 187			$ar2 = str_replace($key, $val, $ar2);
 188		}
 189
 190		if ($ar1 < $ar2) {
 191			return -1;
 192		} elseif ($ar1 > $ar2) {
 193			return 1;
 194		}
 195		return 0;
 196	}
 197}
 198
 199if (!function_exists('trunc')) {
 200	function trunc($floatnumber) {
 201		// truncates a floating-point number at the decimal point
 202		// returns int (if possible, otherwise float)
 203		if ($floatnumber >= 1) {
 204			$truncatednumber = floor($floatnumber);
 205		} elseif ($floatnumber <= -1) {
 206			$truncatednumber = ceil($floatnumber);
 207		} else {
 208			$truncatednumber = 0;
 209		}
 210		if ($truncatednumber <= pow(2, 30)) {
 211			$truncatednumber = (int) $truncatednumber;
 212		}
 213		return $truncatednumber;
 214	}
 215}
 216
 217if (!function_exists('CastAsInt')) {
 218	function CastAsInt($floatnum) {
 219		// convert to float if not already
 220		$floatnum = (float) $floatnum;
 221
 222		// convert a float to type int, only if possible
 223		if (trunc($floatnum) == $floatnum) {
 224			// it's not floating point
 225			if ($floatnum <= pow(2, 30)) {
 226				// it's within int range
 227				$floatnum = (int) $floatnum;
 228			}
 229		}
 230		return $floatnum;
 231	}
 232}
 233
 234if (!function_exists('getmicrotime')) {
 235	function getmicrotime() {
 236		list($usec, $sec) = explode(' ', microtime());
 237		return ((float) $usec + (float) $sec);
 238	}
 239}
 240
 241if (!function_exists('DecimalBinary2Float')) {
 242	function DecimalBinary2Float($binarynumerator) {
 243		$numerator   = Bin2Dec($binarynumerator);
 244		$denominator = Bin2Dec(str_repeat('1', strlen($binarynumerator)));
 245		return ($numerator / $denominator);
 246	}
 247}
 248
 249if (!function_exists('NormalizeBinaryPoint')) {
 250	function NormalizeBinaryPoint($binarypointnumber, $maxbits=52) {
 251		// http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/binary.html
 252		if (strpos($binarypointnumber, '.') === false) {
 253			$binarypointnumber = '0.'.$binarypointnumber;
 254		} elseif ($binarypointnumber{0} == '.') {
 255			$binarypointnumber = '0'.$binarypointnumber;
 256		}
 257		$exponent = 0;
 258		while (($binarypointnumber{0} != '1') || (substr($binarypointnumber, 1, 1) != '.')) {
 259			if (substr($binarypointnumber, 1, 1) == '.') {
 260				$exponent--;
 261				$binarypointnumber = substr($binarypointnumber, 2, 1).'.'.substr($binarypointnumber, 3);
 262			} else {
 263				$pointpos = strpos($binarypointnumber, '.');
 264				$exponent += ($pointpos - 1);
 265				$binarypointnumber = str_replace('.', '', $binarypointnumber);
 266				$binarypointnumber = $binarypointnumber{0}.'.'.substr($binarypointnumber, 1);
 267			}
 268		}
 269		$binarypointnumber = str_pad(substr($binarypointnumber, 0, $maxbits + 2), $maxbits + 2, '0', STR_PAD_RIGHT);
 270		return array('normalized'=>$binarypointnumber, 'exponent'=>(int) $exponent);
 271	}
 272}
 273
 274if (!function_exists('Float2BinaryDecimal')) {
 275	function Float2BinaryDecimal($floatvalue) {
 276		// http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/binary.html
 277		$maxbits = 128; // to how many bits of precision should the calculations be taken?
 278		$intpart   = trunc($floatvalue);
 279		$floatpart = abs($floatvalue - $intpart);
 280		$pointbitstring = '';
 281		while (($floatpart != 0) && (strlen($pointbitstring) < $maxbits)) {
 282			$floatpart *= 2;
 283			$pointbitstring .= (string) trunc($floatpart);
 284			$floatpart -= trunc($floatpart);
 285		}
 286		$binarypointnumber = decbin($intpart).'.'.$pointbitstring;
 287		return $binarypointnumber;
 288	}
 289}
 290
 291if (!function_exists('Float2String')) {
 292	function Float2String($floatvalue, $bits) {
 293		// http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/ieee-expl.html
 294		switch ($bits) {
 295			case 32:
 296				$exponentbits = 8;
 297				$fractionbits = 23;
 298				break;
 299
 300			case 64:
 301				$exponentbits = 11;
 302				$fractionbits = 52;
 303				break;
 304
 305			default:
 306				return false;
 307				break;
 308		}
 309		if ($floatvalue >= 0) {
 310			$signbit = '0';
 311		} else {
 312			$signbit = '1';
 313		}
 314		$normalizedbinary  = NormalizeBinaryPoint(Float2BinaryDecimal($floatvalue), $fractionbits);
 315		$biasedexponent    = pow(2, $exponentbits - 1) - 1 + $normalizedbinary['exponent']; // (127 or 1023) +/- exponent
 316		$exponentbitstring = str_pad(decbin($biasedexponent), $exponentbits, '0', STR_PAD_LEFT);
 317		$fractionbitstring = str_pad(substr($normalizedbinary['normalized'], 2), $fractionbits, '0', STR_PAD_RIGHT);
 318
 319		return BigEndian2String(Bin2Dec($signbit.$exponentbitstring.$fractionbitstring), $bits % 8, false);
 320	}
 321}
 322
 323if (!function_exists('LittleEndian2Float')) {
 324	function LittleEndian2Float($byteword) {
 325		return BigEndian2Float(strrev($byteword));
 326	}
 327}
 328
 329if (!function_exists('BigEndian2Float')) {
 330	function BigEndian2Float($byteword) {
 331		// ANSI/IEEE Standard 754-1985, Standard for Binary Floating Point Arithmetic
 332		// http://www.psc.edu/general/software/packages/ieee/ieee.html
 333		// http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/ieee.html
 334
 335		$bitword = BigEndian2Bin($byteword);
 336		$signbit = $bitword{0};
 337
 338		switch (strlen($byteword) * 8) {
 339			case 32:
 340				$exponentbits = 8;
 341				$fractionbits = 23;
 342				break;
 343
 344			case 64:
 345				$exponentbits = 11;
 346				$fractionbits = 52;
 347				break;
 348
 349			case 80:
 350				$exponentbits = 16;
 351				$fractionbits = 64;
 352				break;
 353
 354			default:
 355				return false;
 356				break;
 357		}
 358		$exponentstring = substr($bitword, 1, $exponentbits - 1);
 359		$fractionstring = substr($bitword, $exponentbits, $fractionbits);
 360		$exponent = Bin2Dec($exponentstring);
 361		$fraction = Bin2Dec($fractionstring);
 362
 363		if (($exponentbits == 16) && ($fractionbits == 64)) {
 364			// 80-bit
 365			// As used in Apple AIFF for sample_rate
 366			// A bit of a hack, but it works ;)
 367			return pow(2, ($exponent  - 16382)) * DecimalBinary2Float($fractionstring);
 368		}
 369
 370
 371		if (($exponent == (pow(2, $exponentbits) - 1)) && ($fraction != 0)) {
 372			// Not a Number
 373			$floatvalue = false;
 374		} elseif (($exponent == (pow(2, $exponentbits) - 1)) && ($fraction == 0)) {
 375			if ($signbit == '1') {
 376				$floatvalue = '-infinity';
 377			} else {
 378				$floatvalue = '+infinity';
 379			}
 380		} elseif (($exponent == 0) && ($fraction == 0)) {
 381			if ($signbit == '1') {
 382				$floatvalue = -0;
 383			} else {
 384				$floatvalue = 0;
 385			}
 386			$floatvalue = ($signbit ? 0 : -0);
 387		} elseif (($exponent == 0) && ($fraction != 0)) {
 388			// These are 'unnormalized' values
 389			$floatvalue = pow(2, (-1 * (pow(2, $exponentbits - 1) - 2))) * DecimalBinary2Float($fractionstring);
 390			if ($signbit == '1') {
 391				$floatvalue *= -1;
 392			}
 393		} elseif ($exponent != 0) {
 394			$floatvalue = pow(2, ($exponent - (pow(2, $exponentbits - 1) - 1))) * (1 + DecimalBinary2Float($fractionstring));
 395			if ($signbit == '1') {
 396				$floatvalue *= -1;
 397			}
 398		}
 399		return (float) $floatvalue;
 400	}
 401}
 402
 403if (!function_exists('BigEndian2Int')) {
 404	function BigEndian2Int($byteword, $synchsafe=false, $signed=false) {
 405		$intvalue = 0;
 406		$bytewordlen = strlen($byteword);
 407		for ($i = 0; $i < $bytewordlen; $i++) {
 408			if ($synchsafe) { // disregard MSB, effectively 7-bit bytes
 409				$intvalue = $intvalue | (ord($byteword{$i}) & 0x7F) << (($bytewordlen - 1 - $i) * 7);
 410			} else {
 411				$intvalue += ord($byteword{$i}) * pow(256, ($bytewordlen - 1 - $i));
 412			}
 413		}
 414		if ($signed && !$synchsafe) {
 415			// synchsafe ints are not allowed to be signed
 416			switch ($bytewordlen) {
 417				case 1:
 418				case 2:
 419				case 3:
 420				case 4:
 421					$signmaskbit = 0x80 << (8 * ($bytewordlen - 1));
 422					if ($intvalue & $signmaskbit) {
 423						$intvalue = 0 - ($intvalue & ($signmaskbit - 1));
 424					}
 425					break;
 426
 427				default:
 428					die('ERROR: Cannot have signed integers larger than 32-bits in BigEndian2Int()');
 429					break;
 430			}
 431		}
 432		return CastAsInt($intvalue);
 433	}
 434}
 435
 436if (!function_exists('LittleEndian2Int')) {
 437	function LittleEndian2Int($byteword, $signed=false) {
 438		return BigEndian2Int(strrev($byteword), false, $signed);
 439	}
 440}
 441
 442if (!function_exists('BigEndian2Bin')) {
 443	function BigEndian2Bin($byteword) {
 444		$binvalue = '';
 445		$bytewordlen = strlen($byteword);
 446		for ($i = 0; $i < $bytewordlen; $i++) {
 447			$binvalue .= str_pad(decbin(ord($byteword{$i})), 8, '0', STR_PAD_LEFT);
 448		}
 449		return $binvalue;
 450	}
 451}
 452
 453if (!function_exists('BigEndian2String')) {
 454	function BigEndian2String($number, $minbytes=1, $synchsafe=false, $signed=false) {
 455		if ($number < 0) {
 456			return false;
 457		}
 458		$maskbyte = (($synchsafe || $signed) ? 0x7F : 0xFF);
 459		$intstring = '';
 460		if ($signed) {
 461			if ($minbytes > 4) {
 462				die('ERROR: Cannot have signed integers larger than 32-bits in BigEndian2String()');
 463			}
 464			$number = $number & (0x80 << (8 * ($minbytes - 1)));
 465		}
 466		while ($number != 0) {
 467			$quotient = ($number / ($maskbyte + 1));
 468			$intstring = chr(ceil(($quotient - floor($quotient)) * $maskbyte)).$intstring;
 469			$number = floor($quotient);
 470		}
 471		return str_pad($intstring, $minbytes, chr(0), STR_PAD_LEFT);
 472	}
 473}
 474
 475if (!function_exists('Dec2Bin')) {
 476	function Dec2Bin($number) {
 477		while ($number >= 256) {
 478			$bytes[] = (($number / 256) - (floor($number / 256))) * 256;
 479			$number = floor($number / 256);
 480		}
 481		$bytes[] = $number;
 482		$binstring = '';
 483		for ($i = 0; $i < count($bytes); $i++) {
 484			$binstring = (($i == count($bytes) - 1) ? decbin($bytes[$i]) : str_pad(decbin($bytes[$i]), 8, '0', STR_PAD_LEFT)).$binstring;
 485		}
 486		return $binstring;
 487	}
 488}
 489
 490if (!function_exists('Bin2Dec')) {
 491	function Bin2Dec($binstring) {
 492		$decvalue = 0;
 493		for ($i = 0; $i < strlen($binstring); $i++) {
 494			$decvalue += ((int) substr($binstring, strlen($binstring) - $i - 1, 1)) * pow(2, $i);
 495		}
 496		return CastAsInt($decvalue);
 497	}
 498}
 499
 500if (!function_exists('Bin2String')) {
 501	function Bin2String($binstring) {
 502		// return 'hi' for input of '0110100001101001'
 503		$string = '';
 504		$binstringreversed = strrev($binstring);
 505		for ($i = 0; $i < strlen($binstringreversed); $i += 8) {
 506			$string = chr(Bin2Dec(strrev(substr($binstringreversed, $i, 8)))).$string;
 507		}
 508		return $string;
 509	}
 510}
 511
 512if (!function_exists('LittleEndian2String')) {
 513	function LittleEndian2String($number, $minbytes=1, $synchsafe=false) {
 514		$intstring = '';
 515		while ($number > 0) {
 516			if ($synchsafe) {
 517				$intstring = $intstring.chr($number & 127);
 518				$number >>= 7;
 519			} else {
 520				$intstring = $intstring.chr($number & 255);
 521				$number >>= 8;
 522			}
 523		}
 524		return str_pad($intstring, $minbytes, chr(0), STR_PAD_RIGHT);
 525	}
 526}
 527
 528if (!function_exists('Bool2IntString')) {
 529	function Bool2IntString($intvalue) {
 530		return ($intvalue ? '1' : '0');
 531	}
 532}
 533
 534if (!function_exists('IntString2Bool')) {
 535	function IntString2Bool($char) {
 536		if ($char == '1') {
 537			return true;
 538		} elseif ($char == '0') {
 539			return false;
 540		}
 541		return null;
 542	}
 543}
 544
 545if (!function_exists('InverseBoolean')) {
 546	function InverseBoolean($value) {
 547		return ($value ? false : true);
 548	}
 549}
 550
 551if (!function_exists('DeUnSynchronise')) {
 552	function DeUnSynchronise($data) {
 553		return str_replace(chr(0xFF).chr(0x00), chr(0xFF), $data);
 554	}
 555}
 556
 557if (!function_exists('Unsynchronise')) {
 558	function Unsynchronise($data) {
 559		// Whenever a false synchronisation is found within the tag, one zeroed
 560		// byte is inserted after the first false synchronisation byte. The
 561		// format of a correct sync that should be altered by ID3 encoders is as
 562		// follows:
 563		//      %11111111 111xxxxx
 564		// And should be replaced with:
 565		//      %11111111 00000000 111xxxxx
 566		// This has the side effect that all $FF 00 combinations have to be
 567		// altered, so they won't be affected by the decoding process. Therefore
 568		// all the $FF 00 combinations have to be replaced with the $FF 00 00
 569		// combination during the unsynchronisation.
 570
 571		$data = str_replace(chr(0xFF).chr(0x00), chr(0xFF).chr(0x00).chr(0x00), $data);
 572		$unsyncheddata = '';
 573		for ($i = 0; $i < strlen($data); $i++) {
 574			$thischar = $data{$i};
 575			$unsyncheddata .= $thischar;
 576			if ($thischar == chr(255)) {
 577				$nextchar = ord(substr($data, $i + 1, 1));
 578				if (($nextchar | 0xE0) == 0xE0) {
 579					// previous byte = 11111111, this byte = 111?????
 580					$unsyncheddata .= chr(0);
 581				}
 582			}
 583		}
 584		return $unsyncheddata;
 585	}
 586}
 587
 588if (!function_exists('is_hash')) {
 589	function is_hash($var) {
 590		// written by dev-null@christophe.vg
 591		// taken from http://www.php.net/manual/en/function.array-merge-recursive.php
 592		if (is_array($var)) {
 593			$keys = array_keys($var);
 594			$all_num = true;
 595			for ($i = 0; $i < count($keys); $i++) {
 596				if (is_string($keys[$i])) {
 597					return true;
 598				}
 599			}
 600		}
 601		return false;
 602	}
 603}
 604
 605if (!function_exists('array_join_merge')) {
 606	function array_join_merge($arr1, $arr2) {
 607		// written by dev-null@christophe.vg
 608		// taken from http://www.php.net/manual/en/function.array-merge-recursive.php
 609		if (is_array($arr1) && is_array($arr2)) {
 610			// the same -> merge
 611			$new_array = array();
 612
 613			if (is_hash($arr1) && is_hash($arr2)) {
 614				// hashes -> merge based on keys
 615				$keys = array_merge(array_keys($arr1), array_keys($arr2));
 616				foreach ($keys as $key) {
 617					$new_array[$key] = array_join_merge(@$arr1[$key], @$arr2[$key]);
 618				}
 619			} else {
 620				// two real arrays -> merge
 621				$new_array = array_reverse(array_unique(array_reverse(array_merge($arr1,$arr2))));
 622			}
 623			return $new_array;
 624		} else {
 625			// not the same ... take new one if defined, else the old one stays
 626			return $arr2 ? $arr2 : $arr1;
 627		}
 628	}
 629}
 630
 631if (!function_exists('array_merge_clobber')) {
 632	function array_merge_clobber($array1, $array2) {
 633		// written by kc@hireability.com
 634		// taken from http://www.php.net/manual/en/function.array-merge-recursive.php
 635		if (!is_array($array1) || !is_array($array2)) {
 636			return false;
 637		}
 638		$newarray = $array1;
 639		foreach ($array2 as $key => $val) {
 640			if (is_array($val) && isset($newarray[$key]) && is_array($newarray[$key])) {
 641				$newarray[$key] = array_merge_clobber($newarray[$key], $val);
 642			} else {
 643				$newarray[$key] = $val;
 644			}
 645		}
 646		return $newarray;
 647	}
 648}
 649
 650if (!function_exists('array_merge_noclobber')) {
 651	function array_merge_noclobber($array1, $array2) {
 652		if (!is_array($array1) || !is_array($array2)) {
 653			return false;
 654		}
 655		$newarray = $array1;
 656		foreach ($array2 as $key => $val) {
 657			if (is_array($val) && isset($newarray[$key]) && is_array($newarray[$key])) {
 658				$newarray[$key] = array_merge_noclobber($newarray[$key], $val);
 659			} elseif (!isset($newarray[$key])) {
 660				$newarray[$key] = $val;
 661			}
 662		}
 663		return $newarray;
 664	}
 665}
 666
 667if (!function_exists('RoughTranslateUnicodeToASCII')) {
 668	function RoughTranslateUnicodeToASCII($rawdata, $frame_textencoding) {
 669		// rough translation of data for application that can't handle Unicode data
 670
 671		$tempstring = '';
 672		switch ($frame_textencoding) {
 673			case 0: // ISO-8859-1. Terminated with $00.
 674				$asciidata = $rawdata;
 675				break;
 676
 677			case 1: // UTF-16 encoded Unicode with BOM. Terminated with $00 00.
 678				$asciidata = $rawdata;
 679				if (substr($asciidata, 0, 2) == chr(0xFF).chr(0xFE)) {
 680					// remove BOM, only if present (it should be, but...)
 681					$asciidata = substr($asciidata, 2);
 682				}
 683				if (substr($asciidata, strlen($asciidata) - 2, 2) == chr(0).chr(0)) {
 684					$asciidata = substr($asciidata, 0, strlen($asciidata) - 2); // remove terminator, only if present (it should be, but...)
 685				}
 686				for ($i = 0; $i < strlen($asciidata); $i += 2) {
 687					if ((ord($asciidata{$i}) <= 0x7F) || (ord($asciidata{$i}) >= 0xA0)) {
 688						$tempstring .= $asciidata{$i};
 689					} else {
 690						$tempstring .= '?';
 691					}
 692				}
 693				$asciidata = $tempstring;
 694				break;
 695
 696			case 2: // UTF-16BE encoded Unicode without BOM. Terminated with $00 00.
 697				$asciidata = $rawdata;
 698				if (substr($asciidata, strlen($asciidata) - 2, 2) == chr(0).chr(0)) {
 699					$asciidata = substr($asciidata, 0, strlen($asciidata) - 2); // remove terminator, only if present (it should be, but...)
 700				}
 701				for ($i = 0; $i < strlen($asciidata); $i += 2) {
 702					if ((ord($asciidata{$i}) <= 0x7F) || (ord($asciidata{$i}) >= 0xA0)) {
 703						$tempstring .= $asciidata{$i};
 704					} else {
 705						$tempstring .= '?';
 706					}
 707				}
 708				$asciidata = $tempstring;
 709				break;
 710
 711			case 3: // UTF-8 encoded Unicode. Terminated with $00.
 712				$asciidata = utf8_decode($rawdata);
 713				break;
 714
 715			case 255: // Unicode, Big-Endian. Terminated with $00 00.
 716				$asciidata = $rawdata;
 717				if (substr($asciidata, strlen($asciidata) - 2, 2) == chr(0).chr(0)) {
 718					$asciidata = substr($asciidata, 0, strlen($asciidata) - 2); // remove terminator, only if present (it should be, but...)
 719				}
 720				for ($i = 0; ($i + 1) < strlen($asciidata); $i += 2) {
 721					if ((ord($asciidata{($i + 1)}) <= 0x7F) || (ord($asciidata{($i + 1)}) >= 0xA0)) {
 722						$tempstring .= $asciidata{($i + 1)};
 723					} else {
 724						$tempstring .= '?';
 725					}
 726				}
 727				$asciidata = $tempstring;
 728				break;
 729
 730
 731			default:
 732				// shouldn't happen, but in case $frame_textencoding is not 1 <= $frame_textencoding <= 4
 733				// just pass the data through unchanged.
 734				$asciidata = $rawdata;
 735				break;
 736		}
 737		if (substr($asciidata, strlen($asciidata) - 1, 1) == chr(0)) {
 738			// remove null terminator, if present
 739			$asciidata = NoNullString($asciidata);
 740		}
 741		return $asciidata;
 742		// return str_replace(chr(0), '', $asciidata); // just in case any nulls slipped through
 743	}
 744}
 745
 746if (!function_exists('PlaytimeString')) {
 747	function PlaytimeString($playtimeseconds) {
 748		$contentseconds = round((($playtimeseconds / 60) - floor($playtimeseconds / 60)) * 60);
 749		$contentminutes = floor($playtimeseconds / 60);
 750		if ($contentseconds >= 60) {
 751			$contentseconds -= 60;
 752			$contentminutes++;
 753		}
 754		return number_format($contentminutes).':'.str_pad($contentseconds, 2, 0, STR_PAD_LEFT);
 755	}
 756}
 757
 758if (!function_exists('CloseMatch')) {
 759	function CloseMatch($value1, $value2, $tolerance) {
 760		return (abs($value1 - $value2) <= $tolerance);
 761	}
 762}
 763
 764if (!function_exists('ID3v1matchesID3v2')) {
 765	function ID3v1matchesID3v2($id3v1, $id3v2) {
 766
 767		$requiredindices = array('title', 'artist', 'album', 'year', 'genre', 'comment');
 768		foreach ($requiredindices as $requiredindex) {
 769			if (!isset($id3v1["$requiredindex"])) {
 770				$id3v1["$requiredindex"] = '';
 771			}
 772			if (!isset($id3v2["$requiredindex"])) {
 773				$id3v2["$requiredindex"] = '';
 774			}
 775		}
 776
 777		if (trim($id3v1['title']) != trim(substr($id3v2['title'], 0, 30))) {
 778			return false;
 779		}
 780		if (trim($id3v1['artist']) != trim(substr($id3v2['artist'], 0, 30))) {
 781			return false;
 782		}
 783		if (trim($id3v1['album']) != trim(substr($id3v2['album'], 0, 30))) {
 784			return false;
 785		}
 786		if (trim($id3v1['year']) != trim(substr($id3v2['year'], 0, 4))) {
 787			return false;
 788		}
 789		if (trim($id3v1['genre']) != trim($id3v2['genre'])) {
 790			return false;
 791		}
 792		if (isset($id3v1['track'])) {
 793			if (!isset($id3v1['track']) || (trim($id3v1['track']) != trim($id3v2['track']))) {
 794				return false;
 795			}
 796			if (trim($id3v1['comment']) != trim(substr($id3v2['comment'], 0, 28))) {
 797				return false;
 798			}
 799		} else {
 800			if (trim($id3v1['comment']) != trim(substr($id3v2['comment'], 0, 30))) {
 801				return false;
 802			}
 803		}
 804		return true;
 805	}
 806}
 807
 808if (!function_exists('FILETIMEtoUNIXtime')) {
 809	function FILETIMEtoUNIXtime($FILETIME, $round=true) {
 810		// FILETIME is a 64-bit unsigned integer representing
 811		// the number of 100-nanosecond intervals since January 1, 1601
 812		// UNIX timestamp is number of seconds since January 1, 1970
 813		// 116444736000000000 = 10000000 * 60 * 60 * 24 * 365 * 369 + 89 leap days
 814		if ($round) {
 815			return round(($FILETIME - 116444736000000000) / 10000000);
 816		}
 817		return ($FILETIME - 116444736000000000) / 10000000;
 818	}
 819}
 820
 821if (!function_exists('GUIDtoBytestring')) {
 822	function GUIDtoBytestring($GUIDstring) {
 823		// Microsoft defines these 16-byte (128-bit) GUIDs in the strangest way:
 824		// first 4 bytes are in little-endian order
 825		// next 2 bytes are appended in little-endian order
 826		// next 2 bytes are appended in little-endian order
 827		// next 2 bytes are appended in big-endian order
 828		// next 6 bytes are appended in big-endian order
 829
 830		// AaBbCcDd-EeFf-GgHh-IiJj-KkLlMmNnOoPp is stored as this 16-byte string:
 831		// $Dd $Cc $Bb $Aa $Ff $Ee $Hh $Gg $Ii $Jj $Kk $Ll $Mm $Nn $Oo $Pp
 832
 833		$hexbytecharstring  = chr(hexdec(substr($GUIDstring,  6, 2)));
 834		$hexbytecharstring .= chr(hexdec(substr($GUIDstring,  4, 2)));
 835		$hexbytecharstring .= chr(hexdec(substr($GUIDstring,  2, 2)));
 836		$hexbytecharstring .= chr(hexdec(substr($GUIDstring,  0, 2)));
 837
 838		$hexbytecharstring .= chr(hexdec(substr($GUIDstring, 11, 2)));
 839		$hexbytecharstring .= chr(hexdec(substr($GUIDstring,  9, 2)));
 840
 841		$hexbytecharstring .= chr(hexdec(substr($GUIDstring, 16, 2)));
 842		$hexbytecharstring .= chr(hexdec(substr($GUIDstring, 14, 2)));
 843
 844		$hexbytecharstring .= chr(hexdec(substr($GUIDstring, 19, 2)));
 845		$hexbytecharstring .= chr(hexdec(substr($GUIDstring, 21, 2)));
 846
 847		$hexbytecharstring .= chr(hexdec(substr($GUIDstring, 24, 2)));
 848		$hexbytecharstring .= chr(hexdec(substr($GUIDstring, 26, 2)));
 849		$hexbytecharstring .= chr(hexdec(substr($GUIDstring, 28, 2)));
 850		$hexbytecharstring .= chr(hexdec(substr($GUIDstring, 30, 2)));
 851		$hexbytecharstring .= chr(hexdec(substr($GUIDstring, 32, 2)));
 852		$hexbytecharstring .= chr(hexdec(substr($GUIDstring, 34, 2)));
 853
 854		return $hexbytecharstring;
 855	}
 856}
 857
 858if (!function_exists('BytestringToGUID')) {
 859	function BytestringToGUID($Bytestring) {
 860		$GUIDstring  = str_pad(dechex(ord($Bytestring{3})),  2, '0', STR_PAD_LEFT);
 861		$GUIDstring .= str_pad(dechex(ord($Bytestring{2})),  2, '0', STR_PAD_LEFT);
 862		$GUIDstring .= str_pad(dechex(ord($Bytestring{1})),  2, '0', STR_PAD_LEFT);
 863		$GUIDstring .= str_pad(dechex(ord($Bytestring{0})),  2, '0', STR_PAD_LEFT);
 864		$GUIDstring .= '-';
 865		$GUIDstring .= str_pad(dechex(ord($Bytestring{5})),  2, '0', STR_PAD_LEFT);
 866		$GUIDstring .= str_pad(dechex(ord($Bytestring{4})),  2, '0', STR_PAD_LEFT);
 867		$GUIDstring .= '-';
 868		$GUIDstring .= str_pad(dechex(ord($Bytestring{7})),  2, '0', STR_PAD_LEFT);
 869		$GUIDstring .= str_pad(dechex(ord($Bytestring{6})),  2, '0', STR_PAD_LEFT);
 870		$GUIDstring .= '-';
 871		$GUIDstring .= str_pad(dechex(ord($Bytestring{8})),  2, '0', STR_PAD_LEFT);
 872		$GUIDstring .= str_pad(dechex(ord($Bytestring{9})),  2, '0', STR_PAD_LEFT);
 873		$GUIDstring .= '-';
 874		$GUIDstring .= str_pad(dechex(ord($Bytestring{10})), 2, '0', STR_PAD_LEFT);
 875		$GUIDstring .= str_pad(dechex(ord($Bytestring{11})), 2, '0', STR_PAD_LEFT);
 876		$GUIDstring .= str_pad(dechex(ord($Bytestring{12})), 2, '0', STR_PAD_LEFT);
 877		$GUIDstring .= str_pad(dechex(ord($Bytestring{13})), 2, '0', STR_PAD_LEFT);
 878		$GUIDstring .= str_pad(dechex(ord($Bytestring{14})), 2, '0', STR_PAD_LEFT);
 879		$GUIDstring .= str_pad(dechex(ord($Bytestring{15})), 2, '0', STR_PAD_LEFT);
 880
 881		return strtoupper($GUIDstring);
 882	}
 883}
 884
 885if (!function_exists('BitrateColor')) {
 886	function BitrateColor($bitrate) {
 887		$bitrate /= 3; // scale from 1-768kbps to 1-256kbps
 888		$bitrate--;    // scale from 1-256kbps to 0-255kbps
 889		$bitrate = max($bitrate, 0);
 890		$bitrate = min($bitrate, 255);
 891		//$bitrate = max($bitrate, 32);
 892		//$bitrate = min($bitrate, 143);
 893		//$bitrate = ($bitrate * 2) - 32;
 894
 895		$Rcomponent = max(255 - ($bitrate * 2), 0);
 896		$Gcomponent = max(($bitrate * 2) - 255, 0);
 897		if ($bitrate > 127) {
 898			$Bcomponent = max((255 - $bitrate) * 2, 0);
 899		} else {
 900			$Bcomponent = max($bitrate * 2, 0);
 901		}
 902		return str_pad(dechex($Rcomponent), 2, '0', STR_PAD_LEFT).str_pad(dechex($Gcomponent), 2, '0', STR_PAD_LEFT).str_pad(dechex($Bcomponent), 2, '0', STR_PAD_LEFT);
 903	}
 904}
 905
 906if (!function_exists('BitrateText')) {
 907	function BitrateText($bitrate) {
 908		return '<SPAN STYLE="color: #'.BitrateColor($bitrate).'">'.round($bitrate).' kbps</SPAN>';
 909	}
 910}
 911
 912if (!function_exists('image_type_to_mime_type')) {
 913	function image_type_to_mime_type($imagetypeid) {
 914		// only available in PHP v4.3.0+
 915		static $image_type_to_mime_type = array();
 916		if (empty($image_type_to_mime_type)) {
 917			$image_type_to_mime_type[1]  = 'image/gif';                     // GIF
 918			$image_type_to_mime_type[2]  = 'image/jpeg';                    // JPEG
 919			$image_type_to_mime_type[3]  = 'image/png';                     // PNG
 920			$image_type_to_mime_type[4]  = 'application/x-shockwave-flash'; // Flash
 921			$image_type_to_mime_type[5]  = 'image/psd';                     // PSD
 922			$image_type_to_mime_type[6]  = 'image/bmp';                     // BMP
 923			$image_type_to_mime_type[7]  = 'image/tiff';                    // TIFF: little-endian (Intel)
 924			$image_type_to_mime_type[8]  = 'image/tiff';                    // TIFF: big-endian (Motorola)
 925			//$image_type_to_mime_type[9]  = 'image/jpc';                   // JPC
 926			//$image_type_to_mime_type[10] = 'image/jp2';                   // JPC
 927			//$image_type_to_mime_type[11] = 'image/jpx';                   // JPC
 928			//$image_type_to_mime_type[12] = 'image/jb2';                   // JPC
 929			$image_type_to_mime_type[13] = 'application/x-shockwave-flash'; // Shockwave
 930			$image_type_to_mime_type[14] = 'image/iff';                     // IFF
 931		}
 932		return (isset($image_type_to_mime_type[$imagetypeid]) ? $image_type_to_mime_type[$imagetypeid] : 'application/octet-stream');
 933	}
 934}
 935
 936if (!function_exists('utf8_decode')) {
 937	// PHP has this function built-in if it's configured with the --with-xml option
 938	// This version of the function is only provided in case XML isn't installed
 939	function utf8_decode($utf8text) {
 940		// http://www.php.net/manual/en/function.utf8-encode.php
 941		// bytes  bits  representation
 942		//   1     7    0bbbbbbb
 943		//   2     11   110bbbbb 10bbbbbb
 944		//   3     16   1110bbbb 10bbbbbb 10bbbbbb
 945		//   4     21   11110bbb 10bbbbbb 10bbbbbb 10bbbbbb
 946
 947		$utf8length = strlen($utf8text);
 948		$decodedtext = '';
 949		for ($i = 0; $i < $utf8length; $i++) {
 950			if ((ord($utf8text{$i}) & 0x80) == 0) {
 951				$decodedtext .= $utf8text{$i};
 952			} elseif ((ord($utf8text{$i}) & 0xF0) == 0xF0) {
 953				$decodedtext .= '?';
 954				$i += 3;
 955			} elseif ((ord($utf8text{$i}) & 0xE0) == 0xE0) {
 956				$decodedtext .= '?';
 957				$i += 2;
 958			} elseif ((ord($utf8text{$i}) & 0xC0) == 0xC0) {
 959				//   2     11   110bbbbb 10bbbbbb
 960				$decodedchar = Bin2Dec(substr(Dec2Bin(ord($utf8text{$i})), 3, 5).substr(Dec2Bin(ord($utf8text{($i + 1)})), 2, 6));
 961				if ($decodedchar <= 255) {
 962					$decodedtext .= chr($decodedchar);
 963				} else {
 964					$decodedtext .= '?';
 965				}
 966				$i += 1;
 967			}
 968		}
 969		return $decodedtext;
 970	}
 971}
 972
 973if (!function_exists('DateMac2Unix')) {
 974	function DateMac2Unix($macdate) {
 975		// Macintosh timestamp: seconds since 00:00h January 1, 1904
 976		// UNIX timestamp:      seconds since 00:00h January 1, 1970
 977		return CastAsInt($macdate - 2082844800);
 978	}
 979}
 980
 981
 982if (!function_exists('FixedPoint8_8')) {
 983	function FixedPoint8_8($rawdata) {
 984		return BigEndian2Int(substr($rawdata, 0, 1)) + (float) (BigEndian2Int(substr($rawdata, 1, 1)) / pow(2, 8));
 985	}
 986}
 987
 988
 989if (!function_exists('FixedPoint16_16')) {
 990	function FixedPoint16_16($rawdata) {
 991		return BigEndian2Int(substr($rawdata, 0, 2)) + (float) (BigEndian2Int(substr($rawdata, 2, 2)) / pow(2, 16));
 992	}
 993}
 994
 995
 996if (!function_exists('FixedPoint2_30')) {
 997	function FixedPoint2_30($rawdata) {
 998		$binarystring = BigEndian2Bin($rawdata);
 999		return Bin2Dec(substr($binarystring, 0, 2)) + (float) (Bin2Dec(substr($binarystring, 2, 30)) / pow(2, 30));
1000	}
1001}
1002
1003
1004if (!function_exists('Pascal2String')) {
1005	function Pascal2String($pascalstring) {
1006		// Pascal strings have 1 byte at the beginning saying how many chars are in the string
1007		return substr($pascalstring, 1);
1008	}
1009}
1010
1011if (!function_exists('NoNullString')) {
1012	function NoNullString($nullterminatedstring) {
1013		// remove the single null terminator on null terminated strings
1014		if (substr($nullterminatedstring, strlen($nullterminatedstring) - 1, 1) === chr(0)) {
1015			return substr($nullterminatedstring, 0, strlen($nullterminatedstring) - 1);
1016		}
1017		return $nullterminatedstring;
1018	}
1019}
1020
1021if (!function_exists('FileSizeNiceDisplay')) {
1022	function FileSizeNiceDisplay($filesize, $precision=2) {
1023		if ($filesize < 1000) {
1024			$sizeunit  = 'bytes';
1025			$precision = 0;
1026		} else {
1027			$filesize /= 1024;
1028			$sizeunit = 'kB';
1029		}
1030		if ($filesize >= 1000) {
1031			$filesize /= 1024;
1032			$sizeunit = 'MB';
1033		}
1034		if ($filesize >= 1000) {
1035			$filesize /= 1024;
1036			$sizeunit = 'GB';
1037		}
1038		return number_format($filesize, $precision).' '.$sizeunit;
1039	}
1040}
1041
1042if (!function_exists('DOStime2UNIXtime')) {
1043	function DOStime2UNIXtime($DOSdate, $DOStime) {
1044		// wFatDate
1045		// Specifies the MS-DOS date. The date is a packed 16-bit value with the following format:
1046		// Bits      Contents
1047		// 0-4    Day of the month (1-31)
1048		// 5-8    Month (1 = January, 2 = February, and so on)
1049		// 9-15   Year offset from 1980 (add 1980 to get actual year)
1050
1051		$UNIXday    =  ($DOSdate & 0x001F);
1052		$UNIXmonth  = (($DOSdate & 0x01E0) >> 5);
1053		$UNIXyear   = (($DOSdate & 0xFE00) >> 9) + 1980;
1054
1055		// wFatTime
1056		// Specifies the MS-DOS time. The time is a packed 16-bit value with the following format:
1057		// Bits   Contents
1058		// 0-4    Second divided by 2
1059		// 5-10   Minute (0-59)
1060		// 11-15  Hour (0-23 on a 24-hour clock)
1061
1062		$UNIXsecond =  ($DOStime & 0x001F) * 2;
1063		$UNIXminute = (($DOStime & 0x07E0) >> 5);
1064		$UNIXhour   = (($DOStime & 0xF800) >> 11);
1065
1066		return mktime($UNIXhour, $UNIXminute, $UNIXsecond, $UNIXmonth, $UNIXday, $UNIXyear);
1067	}
1068}
1069
1070if (!function_exists('CreateDeepArray')) {
1071	function CreateDeepArray($ArrayPath, $Separator, $Value) {
1072		// assigns $Value to a nested array path:
1073		//   $foo = CreateDeepArray('/path/to/my', '/', 'file.txt')
1074		// is the same as:
1075		//   $foo = array('path'=>array('to'=>'array('my'=>array('file.txt'))));
1076		// or
1077		//   $foo['path']['to']['my'] = 'file.txt';
1078		while ($ArrayPath{0} == $Separator) {
1079			$ArrayPath = substr($ArrayPath, 1);
1080		}
1081		if (($pos = strpos($ArrayPath, $Separator)) !== false) {
1082			$ReturnedArray[substr($ArrayPath, 0, $pos)] = CreateDeepArray(substr($ArrayPath, $pos + 1), $Separator, $Value);
1083		} else {
1084			$ReturnedArray["$ArrayPath"] = $Value;
1085		}
1086		return $ReturnedArray;
1087	}
1088}
1089
1090if (!function_exists('md5_file')) {
1091	// Allan Hansen <ah@artemis.dk>
1092	// md5_file() exists in PHP 4.2.0.
1093	// The following works under UNIX only, but dies on windows
1094	function md5_file($file) {
1095		if (substr(php_uname(), 0, 7) == 'Windows') {
1096			die('PHP 4.2.0 or newer required for md5_file()');
1097		}
1098
1099		$file = str_replace('`', '\\`', $file);
1100		if (ereg("^([0-9a-f]{32})[ \t\n\r]", `md5sum "$file"`, $r)) {
1101			return $r[1];
1102		}
1103		return false;
1104	}
1105}
1106
1107if (!function_exists('md5_data')) {
1108	// Allan Hansen <ah@artemis.dk>
1109	// md5_data() - returns md5sum for a file from startuing position to absolute end position
1110
1111	function md5_data($file, $offset, $end, $invertsign=false) {
1112		// first try and create a temporary file in the same directory as the file being scanned
1113		if (($dataMD5filename = tempnam(dirname($file), eregi_replace('[^[:alnum:]]', '', basename($file)))) === false) {
1114			// if that fails, create a temporary file in the system temp directory
1115			if (($dataMD5filename = tempnam('/tmp', 'getID3')) === false) {
1116				// if that fails, create a temporary file in the current directory
1117				if (($dataMD5filename = tempnam('.', eregi_replace('[^[:alnum:]]', '', basename($file)))) === false) {
1118					// can't find anywhere to create a temp file, just die
1119					return false;
1120				}
1121			}
1122		}
1123		$md5 = false;
1124		set_time_limit(max(filesize($file) / 1000000, 30));
1125
1126		// copy parts of file
1127		if ($fp = @fopen($file, 'rb')) {
1128
1129			if ($MD5fp = @fopen($dataMD5filename, 'wb')) {
1130
1131				if ($invertsign) {
1132					// Load conversion lookup strings for 8-bit unsigned->signed conversion below
1133	                $from = '';
1134	                $to   = '';
1135					for ($i = 0; $i < 128; $i++) {
1136						$from .= chr($i);
1137						$to   .= chr($i + 128);
1138					}
1139					for ($i = 128; $i < 256; $i++) {
1140						$from .= chr($i);
1141						$to   .= chr($i - 128);
1142					}
1143				}
1144
1145				fseek($fp, $offset, SEEK_SET);
1146				$byteslefttowrite = $end - $offset;
1147				while (($byteslefttowrite > 0) && ($buffer = fread($fp, FREAD_BUFFER_SIZE))) {
1148					if ($invertsign) {
1149						// Possibly FLAC-specific (?)
1150						// FLAC calculates the MD5sum of the source data of 8-bit files
1151						// not on the actual byte values in the source file, but of those
1152						// values converted from unsigned to signed, or more specifcally,
1153						// with the MSB inverted. ex: 01 -> 81; F5 -> 75; etc
1154
1155						// Therefore, 8-bit WAV data has to be converted before getting the
1156						// md5_data value so as to match the FLAC value
1157
1158						// Flip the MSB for each byte in the buffer before copying
1159						$buffer = strtr($buffer, $from, $to);
1160					}
1161					$byteswritten = fwrite($MD5fp, $buffer, $byteslefttowrite);
1162					$byteslefttowrite -= $byteswritten;
1163				}
1164				fclose($MD5fp);
1165				$md5 = md5_file($dataMD5filename);
1166
1167			}
1168			fclose($fp);
1169
1170		}
1171		unlink($dataMD5filename);
1172		return $md5;
1173	}
1174}
1175
1176if (!function_exists('TwosCompliment2Decimal')) {
1177	function TwosCompliment2Decimal($BinaryValue) {
1178		// http://sandbox.mc.edu/~bennet/cs110/tc/tctod.html
1179		// First check if the number is negative or positive by looking at the sign bit.
1180		// If it is positive, simply convert it to decimal.
1181		// If it is negative, make it positive by inverting the bits and adding one.
1182		// Then, convert the result to decimal.
1183		// The negative of this number is the value of the original binary.
1184
1185		if ($BinaryValue & 0x80) {
1186
1187			// negative number
1188			return (0 - ((~$BinaryValue & 0xFF) + 1));
1189
1190		} else {
1191
1192			// positive number
1193			return $BinaryValue;
1194
1195		}
1196
1197	}
1198}
1199
1200if (!function_exists('LastArrayElement')) {
1201	function LastArrayElement($MyArray) {
1202		if (!is_array($MyArray)) {
1203			return false;
1204		}
1205		if (empty($MyArray)) {
1206			return null;
1207		}
1208		foreach ($MyArray as $key => $value) {
1209		}
1210		return $value;
1211	}
1212}
1213
1214if (!function_exists('safe_inc')) {
1215	function safe_inc(&$variable, $increment=1) {
1216		if (isset($variable)) {
1217			$variable += $increment;
1218		} else {
1219			$variable = $increment;
1220		}
1221		return true;
1222	}
1223}
1224
1225if (!function_exists('CalculateCompressionRatioVideo')) {
1226	function CalculateCompressionRatioVideo(&$ThisFileInfo) {
1227		if (empty($ThisFileInfo['video'])) {
1228			return false;
1229		}
1230		if (empty($ThisFileInfo['video']['resolution_x']) || empty($ThisFileInfo['video']['resolution_y'])) {
1231			return false;
1232		}
1233		if (empty($ThisFileInfo['video']['bits_per_sample'])) {
1234			return false;
1235		}
1236
1237		switch ($ThisFileInfo['video']['dataformat']) {
1238			case 'bmp':
1239			case 'gif':
1240			case 'jpeg':
1241			case 'jpg':
1242			case 'png':
1243			case 'tiff':
1244				$FrameRate = 1;
1245				$PlaytimeSeconds = 1;
1246				$BitrateCompressed = $ThisFileInfo['filesize'] * 8;
1247				break;
1248
1249			default:
1250				if (!empty($ThisFileInfo['video']['frame_rate'])) {
1251					$FrameRate = $ThisFileInfo['video']['frame_rate'];
1252				} else {
1253					return false;
1254				}
1255				if (!empty($ThisFileInfo['playtime_seconds'])) {
1256					$PlaytimeSeconds = $ThisFileInfo['playtime_seconds'];
1257				} else {
1258					return false;
1259				}
1260				if (!empty($ThisFileInfo['video']['bitrate'])) {
1261					$BitrateCompressed = $ThisFileInfo['video']['bitrate'];
1262				} else {
1263					return false;
1264				}
1265				break;
1266		}
1267		$BitrateUncompressed = $ThisFileInfo['video']['resolution_x'] * $ThisFileInfo['video']['resolution_y'] * $ThisFileInfo['video']['bits_per_sample'] * $FrameRate;
1268
1269		$ThisFileInfo['video']['compression_ratio'] = $BitrateCompressed / $BitrateUncompressed;
1270		return true;
1271	}
1272}
1273
1274if (!function_exists('CalculateCompressionRatioAudio')) {
1275	function CalculateCompressionRatioAudio(&$ThisFileInfo) {
1276		if (empty($ThisFileInfo['audio']['bitrate']) || empty($ThisFileInfo['audio']['channels']) || empty($ThisFileInfo['audio']['sample_rate']) || empty($ThisFileInfo['audio']['bits_per_sample'])) {
1277			return false;
1278		}
1279		$ThisFileInfo['audio']['compression_ratio'] = $ThisFileInfo['audio']['bitrate'] / ($ThisFileInfo['audio']['channels'] * $ThisFileInfo['audio']['sample_rate'] * $ThisFileInfo['audio']['bits_per_sample']);
1280		return true;
1281	}
1282}
1283
1284if (!function_exists('IsValidMIMEstring')) {
1285	function IsValidMIMEstring($mimestring) {
1286	    if ((strlen($mimestring) >= 3) && (strpos($mimestring, '/') > 0) && (strpos($mimestring, '/') < (strlen($mimestring) - 1))) {
1287			return true;
1288	    }
1289	    return false;
1290	}
1291}
1292
1293if (!function_exists('IsWithinBitRange')) {
1294	function IsWithinBitRange($number, $maxbits, $signed=false) {
1295	    if ($signed) {
1296			if (($number > (0 - pow(2, $maxbits - 1))) && ($number <= pow(2, $maxbits - 1))) {
1297				return true;
1298			}
1299	    } else {
1300			if (($number >= 0) && ($number <= pow(2, $maxbits))) {
1301				return true;
1302			}
1303	    }
1304	    return false;
1305	}
1306}
1307
1308if (!function_exists('safe_parse_url')) {
1309	function safe_parse_url($url) {
1310	    $parts = @parse_url($url);
1311	    $parts['scheme'] = (isset($parts['scheme']) ? $parts['scheme'] : '');
1312	    $parts['host']   = (isset($parts['host'])   ? $parts['host']   : '');
1313	    $parts['user']   = (isset($parts['user'])   ? $parts['user']   : '');
1314	    $parts['pass']   = (isset($parts['pass'])   ? $parts['pass']   : '');
1315	    $parts['path']   = (isset($parts['path'])   ? $parts['path']   : '');
1316	    $parts['query']  = (isset($parts['query'])  ? $parts['query']  : '');
1317	    return $parts;
1318	}
1319}
1320
1321if (!function_exists('IsValidURL')) {
1322	function IsValidURL($url, $allowUserPass=false) {
1323	    if ($url == '') {
1324			return false;
1325	    }
1326	    if ($allowUserPass !== true) {
1327			if (strstr($url, '@')) {
1328				// in the format http://user:pass@example.com  or http://user@example.com
1329				// but could easily be somebody incorrectly entering an email address in place of a URL
1330				return false;
1331			}
1332	    }
1333	    if ($parts = safe_parse_url($url)) {
1334			if (($parts['scheme'] != 'http') && ($parts['scheme'] != 'https') && ($parts['scheme'] != 'ftp') && ($parts['scheme'] != 'gopher')) {
1335				return false;
1336			} elseif (!eregi("^[[:alnum:]]([-.]?[0-9a-z])*\.[a-z]{2,3}$", $parts['host'], $regs) && !IsValidDottedIP($parts['host'])) {
1337				return false;
1338			} elseif (!eregi("^([[:alnum:]-]|[\_])*$", $parts['user'], $regs)) {
1339				return false;
1340			} elseif (!eregi("^([[:alnum:]-]|[\_])*$", $parts['pass'], $regs)) {
1341				return false;
1342			} elseif (!eregi("^[[:alnum:]/_\.@~-]*$", $parts['path'], $regs)) {
1343				return false;
1344			} elseif (!eregi("^[[:alnum:]?&=+:;_()%#/,\.-]*$", $parts['query'], $regs)) {
1345				return false;
1346			} else {
1347				return true;
1348			}
1349		}
1350		return false;
1351	}
1352}
1353
1354echo '<FORM ACTION="'.$_SERVER['PHP_SELF'].'" METHOD="POST">';
1355echo 'Enter 4 hex bytes of MPEG-audio header (ie <I>FF FA 92 44</I>)<BR>';
1356echo '<INPUT TYPE="TEXT" NAME="HeaderHexBytes" VALUE="'.(isset($_POST['HeaderHexBytes']) ? strtoupper($_POST['HeaderHexBytes']) : '').'" SIZE="11" MAXLENGTH="11">';
1357echo '<INPUT TYPE="SUBMIT" NAME="Analyze" VALUE="Analyze"></FORM>';
1358echo '<HR>';
1359
1360echo '<FORM ACTION="'.$_SERVER['PHP_SELF'].'" METHOD="POST">';
1361echo 'Generate a MPEG-audio 4-byte header from these values:<BR>';
1362echo '<TABLE BORDER="0">';
1363
1364$MPEGgenerateValues = array(
1365								'version'=>array('1', '2', '2.5'),
1366								'layer'=>array('I', 'II', 'III'),
1367								'protection'=>array('Y', 'N'),
1368								'bitrate'=>array('free', '8', '16', '24', '32', '40', '48', '56', '64', '80', '96', '112', '128', '144', '160', '176', '192', '224', '256', '288', '320', '352', '384', '416', '448'),
1369								'frequency'=>array('8000', '11025', '12000', '16000', '22050', '24000', '32000', '44100', '48000'),
1370								'padding'=>array('Y', 'N'),
1371								'private'=>array('Y', 'N'),
1372								'channelmode'=>array('stereo', 'joint stereo', 'dual channel', 'mono'),
1373								'modeextension'=>array('none', 'IS', 'MS', 'IS+MS', '4-31', '8-31', '12-31', '16-31'),
1374								'copyright'=>array('Y', 'N'),
1375								'original'=>array('Y', 'N'),
1376								'emphasis'=>array('none', '50/15ms', 'CCIT J.17')
1377							);
1378
1379foreach ($MPEGgenerateValues as $name => $dataarray) {
1380    echo '<TR><TH>'.$name.':</TH><TD><SELECT NAME="'.$name.'">';
1381    foreach ($dataarray as $key => $value) {
1382		echo '<OPTION'.((isset($_POST["$name"]) && ($_POST["$name"] == $value)) ? ' SELECTED' : '').'>'.$value.'</OPTION>';
1383    }
1384    echo '</SELECT></TD></TR>';
1385}
1386
1387if (isset($_POST['bitrate'])) {
1388	echo '<TR><TH>Frame Length:</TH><TD>'.(int) MPEGaudioFrameLength($_POST['bitrate'], $_POST['version'], $_POST['layer'], (($_POST['padding'] == 'Y') ? '1' : '0'), $_POST['frequency']).'</TD></TR>';
1389}
1390echo '</TABLE>';
1391echo '<INPUT TYPE="SUBMIT" NAME="Generate" VALUE="Generate"></FORM>';
1392echo '<HR>';
1393
1394
1395if (isset($_POST['Analyze']) && $_POST['HeaderHexBytes']) {
1396
1397    $headerbytearray = explode(' ', $_POST['HeaderHexBytes']);
1398    if (count($headerbytearray) != 4) {
1399		die('Invalid byte pattern');
1400    }
1401    $headerstring = '';
1402    foreach ($headerbytearray as $textbyte) {
1403		$headerstring .= chr(hexdec($textbyte));
1404    }
1405
1406    $MP3fileInfo['error'] = '';
1407
1408    $MPEGheaderRawArray = MPEGaudioHeaderDecode(substr($headerstring, 0, 4));
1409
1410    if (MPEGaudioHeaderValid($MPEGheaderRawArray, true)) {
1411
1412		$MP3fileInfo['raw'] = $MPEGheaderRawArray;
1413
1414		$MP3fileInfo['version']              = MPEGaudioVersionLookup($MP3fileInfo['raw']['version']);
1415		$MP3fileInfo['layer']                = MPEGaudioLayerLookup($MP3fileInfo['raw']['layer']);
1416		$MP3fileInfo['protection']           = MPEGaudioCRCLookup($MP3fileInfo['raw']['protection']);
1417		$MP3fileInfo['bitrate']              = MPEGaudioBitrateLookup($MP3fileInfo['version'], $MP3fileInfo['layer'], $MP3fileInfo['raw']['bitrate']);
1418		$MP3fileInfo['frequency']            = MPEGaudioFrequencyLookup($MP3fileInfo['version'], $MP3fileInfo['raw']['sample_rate']);
1419		$MP3fileInfo['padding']              = (bool) $MP3fileInfo['raw']['padding'];
1420		$MP3fileInfo['private']              = (bool) $MP3fileInfo['raw']['private'];
1421		$MP3fileInfo['channelmode']          = MPEGaudioChannelModeLookup($MP3fileInfo['raw']['channelmode']);
1422		$MP3fileInfo['channels']             = (($MP3fileInfo['channelmode'] == 'mono') ? 1 : 2);
1423		$MP3fileInfo['modeextension']        = MPEGaudioModeExtensionLookup($MP3fileInfo['layer'], $MP3fileInfo['raw']['modeextension']);
1424		$MP3fileInfo['copyright']            = (bool) $MP3fileInfo['raw']['copyright'];
1425		$MP3fileInfo['original']             = (bool) $MP3fileInfo['raw']['original'];
1426		$MP3fileInfo['emphasis']             = MPEGaudioEmphasisLookup($MP3fileInfo['raw']['emphasis']);
1427
1428		if ($MP3fileInfo['protection']) {
1429			$MP3fileInfo['crc'] = BigEndian2Int(substr($headerstring, 4, 2));
1430		}
1431
1432		if ($MP3fileInfo['frequency'] > 0) {
1433			$MP3fileInfo['framelength'] = MPEGaudioFrameLength($MP3fileInfo['bitrate'], $MP3fileInfo['version'], $MP3fileInfo['layer'], (int) $MP3fileInfo['padding'], $MP3fileInfo['frequency']);
1434		}
1435		if ($MP3fileInfo['bitrate'] != 'free') {
1436			$MP3fileInfo['bitrate'] *= 1000;
1437		}
1438
1439    } else {
1440
1441		$MP3fileInfo['error'] .= "\n".'Invalid MPEG audio header';
1442
1443    }
1444
1445    if (!$MP3fileInfo['error']) {
1446		unset($MP3fileInfo['error']);
1447    }
1448
1449    echo table_var_dump($MP3fileInfo);
1450
1451} elseif (isset($_POST['Generate'])) {
1452
1453    // AAAA AAAA  AAAB BCCD  EEEE FFGH  IIJJ KLMM
1454
1455    $headerbitstream  = '11111111111';                               // A - Frame sync (all bits set)
1456
1457    $MPEGversionLookup = array('2.5'=>'00', '2'=>'10', '1'=>'11');
1458    $headerbitstream .= $MPEGversionLookup[$_POST['version']];       // B - MPEG Audio version ID
1459
1460    $MPEGlayerLookup = array('III'=>'01', 'II'=>'10', 'I'=>'11');
1461    $headerbitstream .= $MPEGlayerLookup[$_POST['layer']];           // C - Layer description
1462
1463    $headerbitstream .= (($_POST['protection'] == 'Y') ? '0' : '1'); // D - Protection bit
1464
1465    $MPEGaudioBitrateLookup['1']['I']     = array('free'=>'0000', '32'=>'0001', '64'=>'0010', '96'=>'0011', '128'=>'0100', '160'=>'0101', '192'=>'0110', '224'=>'0111', '256'=>'1000', '288'=>'1001', '320'=>'1010', '352'=>'1011', '384'=>'1100', '416'=>'1101', '448'=>'1110');
1466    $MPEGaudioBitrateLookup['1']['II']    = array('free'=>'0000', '32'=>'0001', '48'=>'0010', '56'=>'0011',  '64'=>'0100',  '80'=>'0101',  '96'=>'0110', '112'=>'0111', '128'=>'1000', '160'=>'1001', '192'=>'1010', '224'=>'1011', '256'=>'1100', '320'=>'1101', '384'=>'1110');
1467    $MPEGaudioBitrateLookup['1']['III']   = array('free'=>'0000', '32'=>'0001', '40'=>'0010', '48'=>'0011',  '56'=>'0100',  '64'=>'0101',  '80'=>'0110',  '96'=>'0111', '112'=>'1000', '128'=>'1001', '160'=>'1010', '192'=>'1011', '224'=>'1100', '256'=>'1101', '320'=>'1110');
1468    $MPEGaudioBitrateLookup['2']['I']     = array('free'=>'0000', '32'=>'0001', '48'=>'0010', '56'=>'0011',  '64'=>'0100',  '80'=>'0101',  '96'=>'0110', '112'=>'0111', '128'=>'1000', '144'=>'1001', '160'=>'1010', '176'=>'1011', '192'=>'1100', '224'=>'1101', '256'=>'1110');
1469    $MPEGaudioBitrateLookup['2']['II']    = array('free'=>'0000',  '8'=>'0001', '16'=>'0010', '24'=>'0011',  '32'=>'0100',  '40'=>'0101',  '48'=>'0110', 

Large files files are truncated, but you can click here to view the full file