wp/wp-includes/ID3/module.audio-video.quicktime.php
changeset 5 5e2f62d02dcd
parent 0 d970ebf37754
child 7 cf61fcea0001
equal deleted inserted replaced
4:346c88efed21 5:5e2f62d02dcd
     1 <?php
     1 <?php
     2 /////////////////////////////////////////////////////////////////
     2 /////////////////////////////////////////////////////////////////
     3 /// getID3() by James Heinrich <info@getid3.org>               //
     3 /// getID3() by James Heinrich <info@getid3.org>               //
     4 //  available at http://getid3.sourceforge.net                 //
     4 //  available at http://getid3.sourceforge.net                 //
     5 //            or http://www.getid3.org                         //
     5 //            or http://www.getid3.org                         //
       
     6 //          also https://github.com/JamesHeinrich/getID3       //
     6 /////////////////////////////////////////////////////////////////
     7 /////////////////////////////////////////////////////////////////
     7 // See readme.txt for more details                             //
     8 // See readme.txt for more details                             //
     8 /////////////////////////////////////////////////////////////////
     9 /////////////////////////////////////////////////////////////////
     9 //                                                             //
    10 //                                                             //
    10 // module.audio-video.quicktime.php                            //
    11 // module.audio-video.quicktime.php                            //
    28 
    29 
    29 		$info['fileformat'] = 'quicktime';
    30 		$info['fileformat'] = 'quicktime';
    30 		$info['quicktime']['hinting']    = false;
    31 		$info['quicktime']['hinting']    = false;
    31 		$info['quicktime']['controller'] = 'standard'; // may be overridden if 'ctyp' atom is present
    32 		$info['quicktime']['controller'] = 'standard'; // may be overridden if 'ctyp' atom is present
    32 
    33 
    33 		fseek($this->getid3->fp, $info['avdataoffset'], SEEK_SET);
    34 		$this->fseek($info['avdataoffset']);
    34 
    35 
    35 		$offset      = 0;
    36 		$offset      = 0;
    36 		$atomcounter = 0;
    37 		$atomcounter = 0;
    37 
    38 
    38 		while ($offset < $info['avdataend']) {
    39 		while ($offset < $info['avdataend']) {
    39 			if (!getid3_lib::intValueSupported($offset)) {
    40 			if (!getid3_lib::intValueSupported($offset)) {
    40 				$info['error'][] = 'Unable to parse atom at offset '.$offset.' because beyond '.round(PHP_INT_MAX / 1073741824).'GB limit of PHP filesystem functions';
    41 				$info['error'][] = 'Unable to parse atom at offset '.$offset.' because beyond '.round(PHP_INT_MAX / 1073741824).'GB limit of PHP filesystem functions';
    41 				break;
    42 				break;
    42 			}
    43 			}
    43 			fseek($this->getid3->fp, $offset, SEEK_SET);
    44 			$this->fseek($offset);
    44 			$AtomHeader = fread($this->getid3->fp, 8);
    45 			$AtomHeader = $this->fread(8);
    45 
    46 
    46 			$atomsize = getid3_lib::BigEndian2Int(substr($AtomHeader, 0, 4));
    47 			$atomsize = getid3_lib::BigEndian2Int(substr($AtomHeader, 0, 4));
    47 			$atomname = substr($AtomHeader, 4, 4);
    48 			$atomname = substr($AtomHeader, 4, 4);
    48 
    49 
    49 			// 64-bit MOV patch by jlegateØktnc*com
    50 			// 64-bit MOV patch by jlegateØktnc*com
    50 			if ($atomsize == 1) {
    51 			if ($atomsize == 1) {
    51 				$atomsize = getid3_lib::BigEndian2Int(fread($this->getid3->fp, 8));
    52 				$atomsize = getid3_lib::BigEndian2Int($this->fread(8));
    52 			}
    53 			}
    53 
    54 
    54 			$info['quicktime'][$atomname]['name']   = $atomname;
    55 			$info['quicktime'][$atomname]['name']   = $atomname;
    55 			$info['quicktime'][$atomname]['size']   = $atomsize;
    56 			$info['quicktime'][$atomname]['size']   = $atomsize;
    56 			$info['quicktime'][$atomname]['offset'] = $offset;
    57 			$info['quicktime'][$atomname]['offset'] = $offset;
    64 				// Furthermore, for historical reasons the list of atoms is optionally
    65 				// Furthermore, for historical reasons the list of atoms is optionally
    65 				// terminated by a 32-bit integer set to 0. If you are writing a program
    66 				// terminated by a 32-bit integer set to 0. If you are writing a program
    66 				// to read user data atoms, you should allow for the terminating 0.
    67 				// to read user data atoms, you should allow for the terminating 0.
    67 				break;
    68 				break;
    68 			}
    69 			}
    69 			switch ($atomname) {
    70 			$atomHierarchy = array();
    70 				case 'mdat': // Media DATa atom
    71 			$info['quicktime'][$atomname] = $this->QuicktimeParseAtom($atomname, $atomsize, $this->fread(min($atomsize, round($this->getid3->memory_limit / 2))), $offset, $atomHierarchy, $this->ParseAllPossibleAtoms);
    71 					// 'mdat' contains the actual data for the audio/video
       
    72 					if (($atomsize > 8) && (!isset($info['avdataend_tmp']) || ($info['quicktime'][$atomname]['size'] > ($info['avdataend_tmp'] - $info['avdataoffset'])))) {
       
    73 
       
    74 						$info['avdataoffset'] = $info['quicktime'][$atomname]['offset'] + 8;
       
    75 						$OldAVDataEnd         = $info['avdataend'];
       
    76 						$info['avdataend']    = $info['quicktime'][$atomname]['offset'] + $info['quicktime'][$atomname]['size'];
       
    77 
       
    78 						$getid3_temp = new getID3();
       
    79 						$getid3_temp->openfile($this->getid3->filename);
       
    80 						$getid3_temp->info['avdataoffset'] = $info['avdataoffset'];
       
    81 						$getid3_temp->info['avdataend']    = $info['avdataend'];
       
    82 						$getid3_mp3 = new getid3_mp3($getid3_temp);
       
    83 						if ($getid3_mp3->MPEGaudioHeaderValid($getid3_mp3->MPEGaudioHeaderDecode(fread($this->getid3->fp, 4)))) {
       
    84 							$getid3_mp3->getOnlyMPEGaudioInfo($getid3_temp->info['avdataoffset'], false);
       
    85 							if (!empty($getid3_temp->info['warning'])) {
       
    86 								foreach ($getid3_temp->info['warning'] as $value) {
       
    87 									$info['warning'][] = $value;
       
    88 								}
       
    89 							}
       
    90 							if (!empty($getid3_temp->info['mpeg'])) {
       
    91 								$info['mpeg'] = $getid3_temp->info['mpeg'];
       
    92 								if (isset($info['mpeg']['audio'])) {
       
    93 									$info['audio']['dataformat']   = 'mp3';
       
    94 									$info['audio']['codec']        = (!empty($info['mpeg']['audio']['encoder']) ? $info['mpeg']['audio']['encoder'] : (!empty($info['mpeg']['audio']['codec']) ? $info['mpeg']['audio']['codec'] : (!empty($info['mpeg']['audio']['LAME']) ? 'LAME' :'mp3')));
       
    95 									$info['audio']['sample_rate']  = $info['mpeg']['audio']['sample_rate'];
       
    96 									$info['audio']['channels']     = $info['mpeg']['audio']['channels'];
       
    97 									$info['audio']['bitrate']      = $info['mpeg']['audio']['bitrate'];
       
    98 									$info['audio']['bitrate_mode'] = strtolower($info['mpeg']['audio']['bitrate_mode']);
       
    99 									$info['bitrate']               = $info['audio']['bitrate'];
       
   100 								}
       
   101 							}
       
   102 						}
       
   103 						unset($getid3_mp3, $getid3_temp);
       
   104 						$info['avdataend'] = $OldAVDataEnd;
       
   105 						unset($OldAVDataEnd);
       
   106 
       
   107 					}
       
   108 					break;
       
   109 
       
   110 				case 'free': // FREE space atom
       
   111 				case 'skip': // SKIP atom
       
   112 				case 'wide': // 64-bit expansion placeholder atom
       
   113 					// 'free', 'skip' and 'wide' are just padding, contains no useful data at all
       
   114 					break;
       
   115 
       
   116 				default:
       
   117 					$atomHierarchy = array();
       
   118 					$info['quicktime'][$atomname] = $this->QuicktimeParseAtom($atomname, $atomsize, fread($this->getid3->fp, $atomsize), $offset, $atomHierarchy, $this->ParseAllPossibleAtoms);
       
   119 					break;
       
   120 			}
       
   121 
    72 
   122 			$offset += $atomsize;
    73 			$offset += $atomsize;
   123 			$atomcounter++;
    74 			$atomcounter++;
   124 		}
    75 		}
   125 
    76 
   170 	public function QuicktimeParseAtom($atomname, $atomsize, $atom_data, $baseoffset, &$atomHierarchy, $ParseAllPossibleAtoms) {
   121 	public function QuicktimeParseAtom($atomname, $atomsize, $atom_data, $baseoffset, &$atomHierarchy, $ParseAllPossibleAtoms) {
   171 		// http://developer.apple.com/techpubs/quicktime/qtdevdocs/APIREF/INDEX/atomalphaindex.htm
   122 		// http://developer.apple.com/techpubs/quicktime/qtdevdocs/APIREF/INDEX/atomalphaindex.htm
   172 
   123 
   173 		$info = &$this->getid3->info;
   124 		$info = &$this->getid3->info;
   174 
   125 
   175 		//$atom_parent = array_pop($atomHierarchy);
   126 		$atom_parent = end($atomHierarchy); // not array_pop($atomHierarchy); see http://www.getid3.org/phpBB3/viewtopic.php?t=1717
   176 		$atom_parent = end($atomHierarchy); // http://www.getid3.org/phpBB3/viewtopic.php?t=1717
       
   177 		array_push($atomHierarchy, $atomname);
   127 		array_push($atomHierarchy, $atomname);
   178 		$atom_structure['hierarchy'] = implode(' ', $atomHierarchy);
   128 		$atom_structure['hierarchy'] = implode(' ', $atomHierarchy);
   179 		$atom_structure['name']      = $atomname;
   129 		$atom_structure['name']      = $atomname;
   180 		$atom_structure['size']      = $atomsize;
   130 		$atom_structure['size']      = $atomsize;
   181 		$atom_structure['offset']    = $baseoffset;
   131 		$atom_structure['offset']    = $baseoffset;
   182 //echo getid3_lib::PrintHexBytes(substr($atom_data, 0, 8)).'<br>';
       
   183 //echo getid3_lib::PrintHexBytes(substr($atom_data, 0, 8), false).'<br><br>';
       
   184 		switch ($atomname) {
   132 		switch ($atomname) {
   185 			case 'moov': // MOVie container atom
   133 			case 'moov': // MOVie container atom
   186 			case 'trak': // TRAcK container atom
   134 			case 'trak': // TRAcK container atom
   187 			case 'clip': // CLIPping container atom
   135 			case 'clip': // CLIPping container atom
   188 			case 'matt': // track MATTe container atom
   136 			case 'matt': // track MATTe container atom
   198 			case 'gmhd': // Generic Media info HeaDer atom (seen on QTVR)
   146 			case 'gmhd': // Generic Media info HeaDer atom (seen on QTVR)
   199 				$atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms);
   147 				$atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms);
   200 				break;
   148 				break;
   201 
   149 
   202 			case 'ilst': // Item LiST container atom
   150 			case 'ilst': // Item LiST container atom
   203 				$atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms);
   151 				if ($atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms)) {
   204 
   152 					// some "ilst" atoms contain data atoms that have a numeric name, and the data is far more accessible if the returned array is compacted
   205 				// some "ilst" atoms contain data atoms that have a numeric name, and the data is far more accessible if the returned array is compacted
   153 					$allnumericnames = true;
   206 				$allnumericnames = true;
       
   207 				foreach ($atom_structure['subatoms'] as $subatomarray) {
       
   208 					if (!is_integer($subatomarray['name']) || (count($subatomarray['subatoms']) != 1)) {
       
   209 						$allnumericnames = false;
       
   210 						break;
       
   211 					}
       
   212 				}
       
   213 				if ($allnumericnames) {
       
   214 					$newData = array();
       
   215 					foreach ($atom_structure['subatoms'] as $subatomarray) {
   154 					foreach ($atom_structure['subatoms'] as $subatomarray) {
   216 						foreach ($subatomarray['subatoms'] as $newData_subatomarray) {
   155 						if (!is_integer($subatomarray['name']) || (count($subatomarray['subatoms']) != 1)) {
   217 							unset($newData_subatomarray['hierarchy'], $newData_subatomarray['name']);
   156 							$allnumericnames = false;
   218 							$newData[$subatomarray['name']] = $newData_subatomarray;
       
   219 							break;
   157 							break;
   220 						}
   158 						}
   221 					}
   159 					}
   222 					$atom_structure['data'] = $newData;
   160 					if ($allnumericnames) {
   223 					unset($atom_structure['subatoms']);
   161 						$newData = array();
       
   162 						foreach ($atom_structure['subatoms'] as $subatomarray) {
       
   163 							foreach ($subatomarray['subatoms'] as $newData_subatomarray) {
       
   164 								unset($newData_subatomarray['hierarchy'], $newData_subatomarray['name']);
       
   165 								$newData[$subatomarray['name']] = $newData_subatomarray;
       
   166 								break;
       
   167 							}
       
   168 						}
       
   169 						$atom_structure['data'] = $newData;
       
   170 						unset($atom_structure['subatoms']);
       
   171 					}
   224 				}
   172 				}
   225 				break;
   173 				break;
   226 
   174 
   227 			case "\x00\x00\x00\x01":
   175 			case "\x00\x00\x00\x01":
   228 			case "\x00\x00\x00\x02":
   176 			case "\x00\x00\x00\x02":
   306 			case 'cmID':
   254 			case 'cmID':
   307 			case 'cnID':
   255 			case 'cnID':
   308 			case 'geID':
   256 			case 'geID':
   309 			case 'plID':
   257 			case 'plID':
   310 			case 'sfID': // iTunes store country
   258 			case 'sfID': // iTunes store country
   311 			case '©alb': // ALBum
   259 			case "\xA9".'alb': // ALBum
   312 			case '©art': // ARTist
   260 			case "\xA9".'art': // ARTist
   313 			case '©ART':
   261 			case "\xA9".'ART':
   314 			case '©aut':
   262 			case "\xA9".'aut':
   315 			case '©cmt': // CoMmenT
   263 			case "\xA9".'cmt': // CoMmenT
   316 			case '©com': // COMposer
   264 			case "\xA9".'com': // COMposer
   317 			case '©cpy':
   265 			case "\xA9".'cpy':
   318 			case '©day': // content created year
   266 			case "\xA9".'day': // content created year
   319 			case '©dir':
   267 			case "\xA9".'dir':
   320 			case '©ed1':
   268 			case "\xA9".'ed1':
   321 			case '©ed2':
   269 			case "\xA9".'ed2':
   322 			case '©ed3':
   270 			case "\xA9".'ed3':
   323 			case '©ed4':
   271 			case "\xA9".'ed4':
   324 			case '©ed5':
   272 			case "\xA9".'ed5':
   325 			case '©ed6':
   273 			case "\xA9".'ed6':
   326 			case '©ed7':
   274 			case "\xA9".'ed7':
   327 			case '©ed8':
   275 			case "\xA9".'ed8':
   328 			case '©ed9':
   276 			case "\xA9".'ed9':
   329 			case '©enc':
   277 			case "\xA9".'enc':
   330 			case '©fmt':
   278 			case "\xA9".'fmt':
   331 			case '©gen': // GENre
   279 			case "\xA9".'gen': // GENre
   332 			case '©grp': // GRouPing
   280 			case "\xA9".'grp': // GRouPing
   333 			case '©hst':
   281 			case "\xA9".'hst':
   334 			case '©inf':
   282 			case "\xA9".'inf':
   335 			case '©lyr': // LYRics
   283 			case "\xA9".'lyr': // LYRics
   336 			case '©mak':
   284 			case "\xA9".'mak':
   337 			case '©mod':
   285 			case "\xA9".'mod':
   338 			case '©nam': // full NAMe
   286 			case "\xA9".'nam': // full NAMe
   339 			case '©ope':
   287 			case "\xA9".'ope':
   340 			case '©PRD':
   288 			case "\xA9".'PRD':
   341 			case '©prd':
   289 			case "\xA9".'prd':
   342 			case '©prf':
   290 			case "\xA9".'prf':
   343 			case '©req':
   291 			case "\xA9".'req':
   344 			case '©src':
   292 			case "\xA9".'src':
   345 			case '©swr':
   293 			case "\xA9".'swr':
   346 			case '©too': // encoder
   294 			case "\xA9".'too': // encoder
   347 			case '©trk': // TRacK
   295 			case "\xA9".'trk': // TRacK
   348 			case '©url':
   296 			case "\xA9".'url':
   349 			case '©wrn':
   297 			case "\xA9".'wrn':
   350 			case '©wrt': // WRiTer
   298 			case "\xA9".'wrt': // WRiTer
   351 			case '----': // itunes specific
   299 			case '----': // itunes specific
   352 				if ($atom_parent == 'udta') {
   300 				if ($atom_parent == 'udta') {
   353 					// User data atom handler
   301 					// User data atom handler
   354 					$atom_structure['data_length'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 2));
   302 					$atom_structure['data_length'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 2));
   355 					$atom_structure['language_id'] = getid3_lib::BigEndian2Int(substr($atom_data, 2, 2));
   303 					$atom_structure['language_id'] = getid3_lib::BigEndian2Int(substr($atom_data, 2, 2));
   368 						while ($atomoffset < strlen($atom_data)) {
   316 						while ($atomoffset < strlen($atom_data)) {
   369 							$boxsmallsize = getid3_lib::BigEndian2Int(substr($atom_data, $atomoffset,     2));
   317 							$boxsmallsize = getid3_lib::BigEndian2Int(substr($atom_data, $atomoffset,     2));
   370 							$boxsmalltype =                           substr($atom_data, $atomoffset + 2, 2);
   318 							$boxsmalltype =                           substr($atom_data, $atomoffset + 2, 2);
   371 							$boxsmalldata =                           substr($atom_data, $atomoffset + 4, $boxsmallsize);
   319 							$boxsmalldata =                           substr($atom_data, $atomoffset + 4, $boxsmallsize);
   372 							if ($boxsmallsize <= 1) {
   320 							if ($boxsmallsize <= 1) {
   373 								$info['warning'][] = 'Invalid QuickTime atom smallbox size "'.$boxsmallsize.'" in atom "'.$atomname.'" at offset: '.($atom_structure['offset'] + $atomoffset);
   321 								$info['warning'][] = 'Invalid QuickTime atom smallbox size "'.$boxsmallsize.'" in atom "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $atomname).'" at offset: '.($atom_structure['offset'] + $atomoffset);
   374 								$atom_structure['data'] = null;
   322 								$atom_structure['data'] = null;
   375 								$atomoffset = strlen($atom_data);
   323 								$atomoffset = strlen($atom_data);
   376 								break;
   324 								break;
   377 							}
   325 							}
   378 							switch ($boxsmalltype) {
   326 							switch ($boxsmalltype) {
   379 								case "\x10\xB5":
   327 								case "\x10\xB5":
   380 									$atom_structure['data'] = $boxsmalldata;
   328 									$atom_structure['data'] = $boxsmalldata;
   381 									break;
   329 									break;
   382 								default:
   330 								default:
   383 									$info['warning'][] = 'Unknown QuickTime smallbox type: "'.getid3_lib::PrintHexBytes($boxsmalltype).'" at offset '.$baseoffset;
   331 									$info['warning'][] = 'Unknown QuickTime smallbox type: "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $boxsmalltype).'" ('.trim(getid3_lib::PrintHexBytes($boxsmalltype)).') at offset '.$baseoffset;
   384 									$atom_structure['data'] = $atom_data;
   332 									$atom_structure['data'] = $atom_data;
   385 									break;
   333 									break;
   386 							}
   334 							}
   387 							$atomoffset += (4 + $boxsmallsize);
   335 							$atomoffset += (4 + $boxsmallsize);
   388 						}
   336 						}
   390 						while ($atomoffset < strlen($atom_data)) {
   338 						while ($atomoffset < strlen($atom_data)) {
   391 							$boxsize = getid3_lib::BigEndian2Int(substr($atom_data, $atomoffset, 4));
   339 							$boxsize = getid3_lib::BigEndian2Int(substr($atom_data, $atomoffset, 4));
   392 							$boxtype =                           substr($atom_data, $atomoffset + 4, 4);
   340 							$boxtype =                           substr($atom_data, $atomoffset + 4, 4);
   393 							$boxdata =                           substr($atom_data, $atomoffset + 8, $boxsize - 8);
   341 							$boxdata =                           substr($atom_data, $atomoffset + 8, $boxsize - 8);
   394 							if ($boxsize <= 1) {
   342 							if ($boxsize <= 1) {
   395 								$info['warning'][] = 'Invalid QuickTime atom box size "'.$boxsize.'" in atom "'.$atomname.'" at offset: '.($atom_structure['offset'] + $atomoffset);
   343 								$info['warning'][] = 'Invalid QuickTime atom box size "'.$boxsize.'" in atom "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $atomname).'" at offset: '.($atom_structure['offset'] + $atomoffset);
   396 								$atom_structure['data'] = null;
   344 								$atom_structure['data'] = null;
   397 								$atomoffset = strlen($atom_data);
   345 								$atomoffset = strlen($atom_data);
   398 								break;
   346 								break;
   399 							}
   347 							}
   400 							$atomoffset += $boxsize;
   348 							$atomoffset += $boxsize;
   407 
   355 
   408 								case 'data':
   356 								case 'data':
   409 									$atom_structure['version']   = getid3_lib::BigEndian2Int(substr($boxdata,  0, 1));
   357 									$atom_structure['version']   = getid3_lib::BigEndian2Int(substr($boxdata,  0, 1));
   410 									$atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($boxdata,  1, 3));
   358 									$atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($boxdata,  1, 3));
   411 									switch ($atom_structure['flags_raw']) {
   359 									switch ($atom_structure['flags_raw']) {
   412 										case 0:  // data flag
   360 										case  0: // data flag
   413 										case 21: // tmpo/cpil flag
   361 										case 21: // tmpo/cpil flag
   414 											switch ($atomname) {
   362 											switch ($atomname) {
   415 												case 'cpil':
   363 												case 'cpil':
   416 												case 'pcst':
   364 												case 'pcst':
   417 												case 'pgap':
   365 												case 'pgap':
   458 												default:
   406 												default:
   459 													$atom_structure['data'] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 4));
   407 													$atom_structure['data'] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 4));
   460 											}
   408 											}
   461 											break;
   409 											break;
   462 
   410 
   463 										case 1:  // text flag
   411 										case  1: // text flag
   464 										case 13: // image flag
   412 										case 13: // image flag
   465 										default:
   413 										default:
   466 											$atom_structure['data'] = substr($boxdata, 8);
   414 											$atom_structure['data'] = substr($boxdata, 8);
       
   415 											if ($atomname == 'covr') {
       
   416 												// not a foolproof check, but better than nothing
       
   417 												if (preg_match('#^\xFF\xD8\xFF#', $atom_structure['data'])) {
       
   418 													$atom_structure['image_mime'] = 'image/jpeg';
       
   419 												} elseif (preg_match('#^\x89\x50\x4E\x47\x0D\x0A\x1A\x0A#', $atom_structure['data'])) {
       
   420 													$atom_structure['image_mime'] = 'image/png';
       
   421 												} elseif (preg_match('#^GIF#', $atom_structure['data'])) {
       
   422 													$atom_structure['image_mime'] = 'image/gif';
       
   423 												}
       
   424 											}
   467 											break;
   425 											break;
   468 
   426 
   469 									}
   427 									}
   470 									break;
   428 									break;
   471 
   429 
   472 								default:
   430 								default:
   473 									$info['warning'][] = 'Unknown QuickTime box type: "'.getid3_lib::PrintHexBytes($boxtype).'" at offset '.$baseoffset;
   431 									$info['warning'][] = 'Unknown QuickTime box type: "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $boxtype).'" ('.trim(getid3_lib::PrintHexBytes($boxtype)).') at offset '.$baseoffset;
   474 									$atom_structure['data'] = $atom_data;
   432 									$atom_structure['data'] = $atom_data;
   475 
   433 
   476 							}
   434 							}
   477 						}
   435 						}
   478 					}
   436 					}
   838 				$atom_structure['flags_raw']      = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
   796 				$atom_structure['flags_raw']      = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
   839 				$atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data,  4, 4));
   797 				$atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data,  4, 4));
   840 				$sttsEntriesDataOffset = 8;
   798 				$sttsEntriesDataOffset = 8;
   841 				//$FrameRateCalculatorArray = array();
   799 				//$FrameRateCalculatorArray = array();
   842 				$frames_count = 0;
   800 				$frames_count = 0;
   843 				for ($i = 0; $i < $atom_structure['number_entries']; $i++) {
   801 
       
   802 				$max_stts_entries_to_scan = min(floor($this->getid3->memory_limit / 10000), $atom_structure['number_entries']);
       
   803 				if ($max_stts_entries_to_scan < $atom_structure['number_entries']) {
       
   804 					$info['warning'][] = 'QuickTime atom "stts" has '.$atom_structure['number_entries'].' but only scanning the first '.$max_stts_entries_to_scan.' entries due to limited PHP memory available ('.floor($this->getid3->memory_limit / 1048576).'MB).';
       
   805 				}
       
   806 				for ($i = 0; $i < $max_stts_entries_to_scan; $i++) {
   844 					$atom_structure['time_to_sample_table'][$i]['sample_count']    = getid3_lib::BigEndian2Int(substr($atom_data, $sttsEntriesDataOffset, 4));
   807 					$atom_structure['time_to_sample_table'][$i]['sample_count']    = getid3_lib::BigEndian2Int(substr($atom_data, $sttsEntriesDataOffset, 4));
   845 					$sttsEntriesDataOffset += 4;
   808 					$sttsEntriesDataOffset += 4;
   846 					$atom_structure['time_to_sample_table'][$i]['sample_duration'] = getid3_lib::BigEndian2Int(substr($atom_data, $sttsEntriesDataOffset, 4));
   809 					$atom_structure['time_to_sample_table'][$i]['sample_duration'] = getid3_lib::BigEndian2Int(substr($atom_data, $sttsEntriesDataOffset, 4));
   847 					$sttsEntriesDataOffset += 4;
   810 					$sttsEntriesDataOffset += 4;
   848 
   811 
  1084 			case 'tmcd': // TiMe CoDe atom
  1047 			case 'tmcd': // TiMe CoDe atom
  1085 			case 'chap': // CHAPter list atom
  1048 			case 'chap': // CHAPter list atom
  1086 			case 'sync': // SYNChronization atom
  1049 			case 'sync': // SYNChronization atom
  1087 			case 'scpt': // tranSCriPT atom
  1050 			case 'scpt': // tranSCriPT atom
  1088 			case 'ssrc': // non-primary SouRCe atom
  1051 			case 'ssrc': // non-primary SouRCe atom
  1089 				for ($i = 0; $i < (strlen($atom_data) % 4); $i++) {
  1052 				for ($i = 0; $i < strlen($atom_data); $i += 4) {
  1090 					$atom_structure['track_id'][$i] = getid3_lib::BigEndian2Int(substr($atom_data, $i * 4, 4));
  1053 					@$atom_structure['track_id'][] = getid3_lib::BigEndian2Int(substr($atom_data, $i, 4));
  1091 				}
  1054 				}
  1092 				break;
  1055 				break;
  1093 
  1056 
  1094 
  1057 
  1095 			case 'elst': // Edit LiST atom
  1058 			case 'elst': // Edit LiST atom
  1258 				$atom_structure['unknown_1'] = getid3_lib::BigEndian2Int(substr($atom_data,  4, 4));
  1221 				$atom_structure['unknown_1'] = getid3_lib::BigEndian2Int(substr($atom_data,  4, 4));
  1259 				$atom_structure['fourcc']    =                           substr($atom_data,  8, 4);
  1222 				$atom_structure['fourcc']    =                           substr($atom_data,  8, 4);
  1260 				break;
  1223 				break;
  1261 
  1224 
  1262 			case 'mdat': // Media DATa atom
  1225 			case 'mdat': // Media DATa atom
       
  1226 				// 'mdat' contains the actual data for the audio/video, possibly also subtitles
       
  1227 
       
  1228 /* due to lack of known documentation, this is a kludge implementation. If you know of documentation on how mdat is properly structed, please send it to info@getid3.org */
       
  1229 
       
  1230 				// first, skip any 'wide' padding, and second 'mdat' header (with specified size of zero?)
       
  1231 				$mdat_offset = 0;
       
  1232 				while (true) {
       
  1233 					if (substr($atom_data, $mdat_offset, 8) == "\x00\x00\x00\x08".'wide') {
       
  1234 						$mdat_offset += 8;
       
  1235 					} elseif (substr($atom_data, $mdat_offset, 8) == "\x00\x00\x00\x00".'mdat') {
       
  1236 						$mdat_offset += 8;
       
  1237 					} else {
       
  1238 						break;
       
  1239 					}
       
  1240 				}
       
  1241 
       
  1242 				// check to see if it looks like chapter titles, in the form of unterminated strings with a leading 16-bit size field
       
  1243 				while  (($chapter_string_length = getid3_lib::BigEndian2Int(substr($atom_data, $mdat_offset, 2)))
       
  1244 					&& ($chapter_string_length < 1000)
       
  1245 					&& ($chapter_string_length <= (strlen($atom_data) - $mdat_offset - 2))
       
  1246 					&& preg_match('#^[\x20-\xFF]+$#', substr($atom_data, $mdat_offset + 2, $chapter_string_length), $chapter_matches)) {
       
  1247 						$mdat_offset += (2 + $chapter_string_length);
       
  1248 						@$info['quicktime']['comments']['chapters'][] = $chapter_matches[0];
       
  1249 				}
       
  1250 
       
  1251 
       
  1252 
       
  1253 				if (($atomsize > 8) && (!isset($info['avdataend_tmp']) || ($info['quicktime'][$atomname]['size'] > ($info['avdataend_tmp'] - $info['avdataoffset'])))) {
       
  1254 
       
  1255 					$info['avdataoffset'] = $atom_structure['offset'] + 8;                       // $info['quicktime'][$atomname]['offset'] + 8;
       
  1256 					$OldAVDataEnd         = $info['avdataend'];
       
  1257 					$info['avdataend']    = $atom_structure['offset'] + $atom_structure['size']; // $info['quicktime'][$atomname]['offset'] + $info['quicktime'][$atomname]['size'];
       
  1258 
       
  1259 					$getid3_temp = new getID3();
       
  1260 					$getid3_temp->openfile($this->getid3->filename);
       
  1261 					$getid3_temp->info['avdataoffset'] = $info['avdataoffset'];
       
  1262 					$getid3_temp->info['avdataend']    = $info['avdataend'];
       
  1263 					$getid3_mp3 = new getid3_mp3($getid3_temp);
       
  1264 					if ($getid3_mp3->MPEGaudioHeaderValid($getid3_mp3->MPEGaudioHeaderDecode($this->fread(4)))) {
       
  1265 						$getid3_mp3->getOnlyMPEGaudioInfo($getid3_temp->info['avdataoffset'], false);
       
  1266 						if (!empty($getid3_temp->info['warning'])) {
       
  1267 							foreach ($getid3_temp->info['warning'] as $value) {
       
  1268 								$info['warning'][] = $value;
       
  1269 							}
       
  1270 						}
       
  1271 						if (!empty($getid3_temp->info['mpeg'])) {
       
  1272 							$info['mpeg'] = $getid3_temp->info['mpeg'];
       
  1273 							if (isset($info['mpeg']['audio'])) {
       
  1274 								$info['audio']['dataformat']   = 'mp3';
       
  1275 								$info['audio']['codec']        = (!empty($info['mpeg']['audio']['encoder']) ? $info['mpeg']['audio']['encoder'] : (!empty($info['mpeg']['audio']['codec']) ? $info['mpeg']['audio']['codec'] : (!empty($info['mpeg']['audio']['LAME']) ? 'LAME' :'mp3')));
       
  1276 								$info['audio']['sample_rate']  = $info['mpeg']['audio']['sample_rate'];
       
  1277 								$info['audio']['channels']     = $info['mpeg']['audio']['channels'];
       
  1278 								$info['audio']['bitrate']      = $info['mpeg']['audio']['bitrate'];
       
  1279 								$info['audio']['bitrate_mode'] = strtolower($info['mpeg']['audio']['bitrate_mode']);
       
  1280 								$info['bitrate']               = $info['audio']['bitrate'];
       
  1281 							}
       
  1282 						}
       
  1283 					}
       
  1284 					unset($getid3_mp3, $getid3_temp);
       
  1285 					$info['avdataend'] = $OldAVDataEnd;
       
  1286 					unset($OldAVDataEnd);
       
  1287 
       
  1288 				}
       
  1289 
       
  1290 				unset($mdat_offset, $chapter_string_length, $chapter_matches);
       
  1291 				break;
       
  1292 
  1263 			case 'free': // FREE space atom
  1293 			case 'free': // FREE space atom
  1264 			case 'skip': // SKIP atom
  1294 			case 'skip': // SKIP atom
  1265 			case 'wide': // 64-bit expansion placeholder atom
  1295 			case 'wide': // 64-bit expansion placeholder atom
  1266 				// 'mdat' data is too big to deal with, contains no useful metadata
       
  1267 				// 'free', 'skip' and 'wide' are just padding, contains no useful data at all
  1296 				// 'free', 'skip' and 'wide' are just padding, contains no useful data at all
  1268 
  1297 
  1269 				// When writing QuickTime files, it is sometimes necessary to update an atom's size.
  1298 				// When writing QuickTime files, it is sometimes necessary to update an atom's size.
  1270 				// It is impossible to update a 32-bit atom to a 64-bit atom since the 32-bit atom
  1299 				// It is impossible to update a 32-bit atom to a 64-bit atom since the 32-bit atom
  1271 				// is only 8 bytes in size, and the 64-bit atom requires 16 bytes. Therefore, QuickTime
  1300 				// is only 8 bytes in size, and the 64-bit atom requires 16 bytes. Therefore, QuickTime
  1327 			case 'sdtp'://  STSampleDependencyAID              - http://developer.apple.com/documentation/QuickTime/Reference/QTRef_Constants/Reference/reference.html
  1356 			case 'sdtp'://  STSampleDependencyAID              - http://developer.apple.com/documentation/QuickTime/Reference/QTRef_Constants/Reference/reference.html
  1328 			case 'stps'://  STPartialSyncSampleAID             - http://developer.apple.com/documentation/QuickTime/Reference/QTRef_Constants/Reference/reference.html
  1357 			case 'stps'://  STPartialSyncSampleAID             - http://developer.apple.com/documentation/QuickTime/Reference/QTRef_Constants/Reference/reference.html
  1329 				//$atom_structure['data'] = $atom_data;
  1358 				//$atom_structure['data'] = $atom_data;
  1330 				break;
  1359 				break;
  1331 
  1360 
  1332 			case '©xyz':  // GPS latitude+longitude+altitude
  1361 			case "\xA9".'xyz':  // GPS latitude+longitude+altitude
  1333 				$atom_structure['data'] = $atom_data;
  1362 				$atom_structure['data'] = $atom_data;
  1334 				if (preg_match('#([\\+\\-][0-9\\.]+)([\\+\\-][0-9\\.]+)([\\+\\-][0-9\\.]+)?/$#i', $atom_data, $matches)) {
  1363 				if (preg_match('#([\\+\\-][0-9\\.]+)([\\+\\-][0-9\\.]+)([\\+\\-][0-9\\.]+)?/$#i', $atom_data, $matches)) {
  1335 					@list($all, $latitude, $longitude, $altitude) = $matches;
  1364 					@list($all, $latitude, $longitude, $altitude) = $matches;
  1336 					$info['quicktime']['comments']['gps_latitude'][]  = floatval($latitude);
  1365 					$info['quicktime']['comments']['gps_latitude'][]  = floatval($latitude);
  1337 					$info['quicktime']['comments']['gps_longitude'][] = floatval($longitude);
  1366 					$info['quicktime']['comments']['gps_longitude'][] = floatval($longitude);
  1356 					$atom_structure['image_mime'] = 'image/jpeg';
  1385 					$atom_structure['image_mime'] = 'image/jpeg';
  1357 					$atom_structure['description'] = (($atomname == 'NCTH') ? 'Nikon Camera Thumbnail Image' : (($atomname == 'NCVW') ? 'Nikon Camera Preview Image' : 'Nikon preview image'));
  1386 					$atom_structure['description'] = (($atomname == 'NCTH') ? 'Nikon Camera Thumbnail Image' : (($atomname == 'NCVW') ? 'Nikon Camera Preview Image' : 'Nikon preview image'));
  1358 					$info['quicktime']['comments']['picture'][] = array('image_mime'=>$atom_structure['image_mime'], 'data'=>$atom_data, 'description'=>$atom_structure['description']);
  1387 					$info['quicktime']['comments']['picture'][] = array('image_mime'=>$atom_structure['image_mime'], 'data'=>$atom_data, 'description'=>$atom_structure['description']);
  1359 				}
  1388 				}
  1360 				break;
  1389 				break;
  1361 			case 'NCHD': // MakerNoteVersion
  1390 			case 'NCTG': // Nikon - http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html#NCTG
  1362 				// http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html
       
  1363 				$atom_structure['data'] = $atom_data;
       
  1364 				break;
       
  1365 			case 'NCTG': // NikonTags
       
  1366 				// http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html#NCTG
       
  1367 				$atom_structure['data'] = $this->QuicktimeParseNikonNCTG($atom_data);
  1391 				$atom_structure['data'] = $this->QuicktimeParseNikonNCTG($atom_data);
  1368 				break;
  1392 				break;
  1369 			case 'NCDB': // NikonTags
  1393 			case 'NCHD': // Nikon:MakerNoteVersion  - http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html
  1370 				// http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html
  1394 			case 'NCDB': // Nikon                   - http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html
       
  1395 			case 'CNCV': // Canon:CompressorVersion - http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Canon.html
  1371 				$atom_structure['data'] = $atom_data;
  1396 				$atom_structure['data'] = $atom_data;
  1372 				break;
  1397 				break;
  1373 
  1398 
  1374 			case "\x00\x00\x00\x00":
  1399 			case "\x00\x00\x00\x00":
  1375 			case 'meta': // METAdata atom
  1400 			case 'meta': // METAdata atom
  1389 				$atom_structure['unknown']  = getid3_lib::BigEndian2Int(substr($atom_data, 4 + 2, 2));
  1414 				$atom_structure['unknown']  = getid3_lib::BigEndian2Int(substr($atom_data, 4 + 2, 2));
  1390 				$atom_structure['data']     =                           substr($atom_data, 4 + 4);
  1415 				$atom_structure['data']     =                           substr($atom_data, 4 + 4);
  1391 				break;
  1416 				break;
  1392 
  1417 
  1393 			default:
  1418 			default:
  1394 				$info['warning'][] = 'Unknown QuickTime atom type: "'.$atomname.'" ('.trim(getid3_lib::PrintHexBytes($atomname)).') at offset '.$baseoffset;
  1419 				$info['warning'][] = 'Unknown QuickTime atom type: "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $atomname).'" ('.trim(getid3_lib::PrintHexBytes($atomname)).') at offset '.$baseoffset;
  1395 				$atom_structure['data'] = $atom_data;
  1420 				$atom_structure['data'] = $atom_data;
  1396 				break;
  1421 				break;
  1397 		}
  1422 		}
  1398 		array_pop($atomHierarchy);
  1423 		array_pop($atomHierarchy);
  1399 		return $atom_structure;
  1424 		return $atom_structure;
  2084 
  2109 
  2085 
  2110 
  2086 	public function CopyToAppropriateCommentsSection($keyname, $data, $boxname='') {
  2111 	public function CopyToAppropriateCommentsSection($keyname, $data, $boxname='') {
  2087 		static $handyatomtranslatorarray = array();
  2112 		static $handyatomtranslatorarray = array();
  2088 		if (empty($handyatomtranslatorarray)) {
  2113 		if (empty($handyatomtranslatorarray)) {
  2089 			$handyatomtranslatorarray['©cpy'] = 'copyright';
  2114 			$handyatomtranslatorarray["\xA9".'cpy'] = 'copyright';
  2090 			$handyatomtranslatorarray['©day'] = 'creation_date';    // iTunes 4.0
  2115 			$handyatomtranslatorarray["\xA9".'day'] = 'creation_date';    // iTunes 4.0
  2091 			$handyatomtranslatorarray['©dir'] = 'director';
  2116 			$handyatomtranslatorarray["\xA9".'dir'] = 'director';
  2092 			$handyatomtranslatorarray['©ed1'] = 'edit1';
  2117 			$handyatomtranslatorarray["\xA9".'ed1'] = 'edit1';
  2093 			$handyatomtranslatorarray['©ed2'] = 'edit2';
  2118 			$handyatomtranslatorarray["\xA9".'ed2'] = 'edit2';
  2094 			$handyatomtranslatorarray['©ed3'] = 'edit3';
  2119 			$handyatomtranslatorarray["\xA9".'ed3'] = 'edit3';
  2095 			$handyatomtranslatorarray['©ed4'] = 'edit4';
  2120 			$handyatomtranslatorarray["\xA9".'ed4'] = 'edit4';
  2096 			$handyatomtranslatorarray['©ed5'] = 'edit5';
  2121 			$handyatomtranslatorarray["\xA9".'ed5'] = 'edit5';
  2097 			$handyatomtranslatorarray['©ed6'] = 'edit6';
  2122 			$handyatomtranslatorarray["\xA9".'ed6'] = 'edit6';
  2098 			$handyatomtranslatorarray['©ed7'] = 'edit7';
  2123 			$handyatomtranslatorarray["\xA9".'ed7'] = 'edit7';
  2099 			$handyatomtranslatorarray['©ed8'] = 'edit8';
  2124 			$handyatomtranslatorarray["\xA9".'ed8'] = 'edit8';
  2100 			$handyatomtranslatorarray['©ed9'] = 'edit9';
  2125 			$handyatomtranslatorarray["\xA9".'ed9'] = 'edit9';
  2101 			$handyatomtranslatorarray['©fmt'] = 'format';
  2126 			$handyatomtranslatorarray["\xA9".'fmt'] = 'format';
  2102 			$handyatomtranslatorarray['©inf'] = 'information';
  2127 			$handyatomtranslatorarray["\xA9".'inf'] = 'information';
  2103 			$handyatomtranslatorarray['©prd'] = 'producer';
  2128 			$handyatomtranslatorarray["\xA9".'prd'] = 'producer';
  2104 			$handyatomtranslatorarray['©prf'] = 'performers';
  2129 			$handyatomtranslatorarray["\xA9".'prf'] = 'performers';
  2105 			$handyatomtranslatorarray['©req'] = 'system_requirements';
  2130 			$handyatomtranslatorarray["\xA9".'req'] = 'system_requirements';
  2106 			$handyatomtranslatorarray['©src'] = 'source_credit';
  2131 			$handyatomtranslatorarray["\xA9".'src'] = 'source_credit';
  2107 			$handyatomtranslatorarray['©wrt'] = 'writer';
  2132 			$handyatomtranslatorarray["\xA9".'wrt'] = 'writer';
  2108 
  2133 
  2109 			// http://www.geocities.com/xhelmboyx/quicktime/formats/qtm-layout.txt
  2134 			// http://www.geocities.com/xhelmboyx/quicktime/formats/qtm-layout.txt
  2110 			$handyatomtranslatorarray['©nam'] = 'title';           // iTunes 4.0
  2135 			$handyatomtranslatorarray["\xA9".'nam'] = 'title';           // iTunes 4.0
  2111 			$handyatomtranslatorarray['©cmt'] = 'comment';         // iTunes 4.0
  2136 			$handyatomtranslatorarray["\xA9".'cmt'] = 'comment';         // iTunes 4.0
  2112 			$handyatomtranslatorarray['©wrn'] = 'warning';
  2137 			$handyatomtranslatorarray["\xA9".'wrn'] = 'warning';
  2113 			$handyatomtranslatorarray['©hst'] = 'host_computer';
  2138 			$handyatomtranslatorarray["\xA9".'hst'] = 'host_computer';
  2114 			$handyatomtranslatorarray['©mak'] = 'make';
  2139 			$handyatomtranslatorarray["\xA9".'mak'] = 'make';
  2115 			$handyatomtranslatorarray['©mod'] = 'model';
  2140 			$handyatomtranslatorarray["\xA9".'mod'] = 'model';
  2116 			$handyatomtranslatorarray['©PRD'] = 'product';
  2141 			$handyatomtranslatorarray["\xA9".'PRD'] = 'product';
  2117 			$handyatomtranslatorarray['©swr'] = 'software';
  2142 			$handyatomtranslatorarray["\xA9".'swr'] = 'software';
  2118 			$handyatomtranslatorarray['©aut'] = 'author';
  2143 			$handyatomtranslatorarray["\xA9".'aut'] = 'author';
  2119 			$handyatomtranslatorarray['©ART'] = 'artist';
  2144 			$handyatomtranslatorarray["\xA9".'ART'] = 'artist';
  2120 			$handyatomtranslatorarray['©trk'] = 'track';
  2145 			$handyatomtranslatorarray["\xA9".'trk'] = 'track';
  2121 			$handyatomtranslatorarray['©alb'] = 'album';           // iTunes 4.0
  2146 			$handyatomtranslatorarray["\xA9".'alb'] = 'album';           // iTunes 4.0
  2122 			$handyatomtranslatorarray['©com'] = 'comment';
  2147 			$handyatomtranslatorarray["\xA9".'com'] = 'comment';
  2123 			$handyatomtranslatorarray['©gen'] = 'genre';           // iTunes 4.0
  2148 			$handyatomtranslatorarray["\xA9".'gen'] = 'genre';           // iTunes 4.0
  2124 			$handyatomtranslatorarray['©ope'] = 'composer';
  2149 			$handyatomtranslatorarray["\xA9".'ope'] = 'composer';
  2125 			$handyatomtranslatorarray['©url'] = 'url';
  2150 			$handyatomtranslatorarray["\xA9".'url'] = 'url';
  2126 			$handyatomtranslatorarray['©enc'] = 'encoder';
  2151 			$handyatomtranslatorarray["\xA9".'enc'] = 'encoder';
  2127 
  2152 
  2128 			// http://atomicparsley.sourceforge.net/mpeg-4files.html
  2153 			// http://atomicparsley.sourceforge.net/mpeg-4files.html
  2129 			$handyatomtranslatorarray['©art'] = 'artist';           // iTunes 4.0
  2154 			$handyatomtranslatorarray["\xA9".'art'] = 'artist';           // iTunes 4.0
  2130 			$handyatomtranslatorarray['aART'] = 'album_artist';
  2155 			$handyatomtranslatorarray['aART'] = 'album_artist';
  2131 			$handyatomtranslatorarray['trkn'] = 'track_number';     // iTunes 4.0
  2156 			$handyatomtranslatorarray['trkn'] = 'track_number';     // iTunes 4.0
  2132 			$handyatomtranslatorarray['disk'] = 'disc_number';      // iTunes 4.0
  2157 			$handyatomtranslatorarray['disk'] = 'disc_number';      // iTunes 4.0
  2133 			$handyatomtranslatorarray['gnre'] = 'genre';            // iTunes 4.0
  2158 			$handyatomtranslatorarray['gnre'] = 'genre';            // iTunes 4.0
  2134 			$handyatomtranslatorarray['©too'] = 'encoder';          // iTunes 4.0
  2159 			$handyatomtranslatorarray["\xA9".'too'] = 'encoder';          // iTunes 4.0
  2135 			$handyatomtranslatorarray['tmpo'] = 'bpm';              // iTunes 4.0
  2160 			$handyatomtranslatorarray['tmpo'] = 'bpm';              // iTunes 4.0
  2136 			$handyatomtranslatorarray['cprt'] = 'copyright';        // iTunes 4.0?
  2161 			$handyatomtranslatorarray['cprt'] = 'copyright';        // iTunes 4.0?
  2137 			$handyatomtranslatorarray['cpil'] = 'compilation';      // iTunes 4.0
  2162 			$handyatomtranslatorarray['cpil'] = 'compilation';      // iTunes 4.0
  2138 			$handyatomtranslatorarray['covr'] = 'picture';          // iTunes 4.0
  2163 			$handyatomtranslatorarray['covr'] = 'picture';          // iTunes 4.0
  2139 			$handyatomtranslatorarray['rtng'] = 'rating';           // iTunes 4.0
  2164 			$handyatomtranslatorarray['rtng'] = 'rating';           // iTunes 4.0
  2140 			$handyatomtranslatorarray['©grp'] = 'grouping';         // iTunes 4.2
  2165 			$handyatomtranslatorarray["\xA9".'grp'] = 'grouping';         // iTunes 4.2
  2141 			$handyatomtranslatorarray['stik'] = 'stik';             // iTunes 4.9
  2166 			$handyatomtranslatorarray['stik'] = 'stik';             // iTunes 4.9
  2142 			$handyatomtranslatorarray['pcst'] = 'podcast';          // iTunes 4.9
  2167 			$handyatomtranslatorarray['pcst'] = 'podcast';          // iTunes 4.9
  2143 			$handyatomtranslatorarray['catg'] = 'category';         // iTunes 4.9
  2168 			$handyatomtranslatorarray['catg'] = 'category';         // iTunes 4.9
  2144 			$handyatomtranslatorarray['keyw'] = 'keyword';          // iTunes 4.9
  2169 			$handyatomtranslatorarray['keyw'] = 'keyword';          // iTunes 4.9
  2145 			$handyatomtranslatorarray['purl'] = 'podcast_url';      // iTunes 4.9
  2170 			$handyatomtranslatorarray['purl'] = 'podcast_url';      // iTunes 4.9
  2146 			$handyatomtranslatorarray['egid'] = 'episode_guid';     // iTunes 4.9
  2171 			$handyatomtranslatorarray['egid'] = 'episode_guid';     // iTunes 4.9
  2147 			$handyatomtranslatorarray['desc'] = 'description';      // iTunes 5.0
  2172 			$handyatomtranslatorarray['desc'] = 'description';      // iTunes 5.0
  2148 			$handyatomtranslatorarray['©lyr'] = 'lyrics';           // iTunes 5.0
  2173 			$handyatomtranslatorarray["\xA9".'lyr'] = 'lyrics';           // iTunes 5.0
  2149 			$handyatomtranslatorarray['tvnn'] = 'tv_network_name';  // iTunes 6.0
  2174 			$handyatomtranslatorarray['tvnn'] = 'tv_network_name';  // iTunes 6.0
  2150 			$handyatomtranslatorarray['tvsh'] = 'tv_show_name';     // iTunes 6.0
  2175 			$handyatomtranslatorarray['tvsh'] = 'tv_show_name';     // iTunes 6.0
  2151 			$handyatomtranslatorarray['tvsn'] = 'tv_season';        // iTunes 6.0
  2176 			$handyatomtranslatorarray['tvsn'] = 'tv_season';        // iTunes 6.0
  2152 			$handyatomtranslatorarray['tves'] = 'tv_episode';       // iTunes 6.0
  2177 			$handyatomtranslatorarray['tves'] = 'tv_episode';       // iTunes 6.0
  2153 			$handyatomtranslatorarray['purd'] = 'purchase_date';    // iTunes 6.0.2
  2178 			$handyatomtranslatorarray['purd'] = 'purchase_date';    // iTunes 6.0.2