Completed
Push — vendor/getid3 ( f84e24...1ec141 )
by Pauli
03:18
created

getid3_quicktime::LociString()   D

Complexity

Conditions 10
Paths 6

Size

Total Lines 32
Code Lines 20

Duplication

Lines 16
Ratio 50 %

Importance

Changes 0
Metric Value
cc 10
eloc 20
nc 6
nop 2
dl 16
loc 32
rs 4.8196
c 0
b 0
f 0

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/////////////////////////////////////////////////////////////////
3
/// getID3() by James Heinrich <[email protected]>               //
4
//  available at http://getid3.sourceforge.net                 //
5
//            or http://www.getid3.org                         //
6
//          also https://github.com/JamesHeinrich/getID3       //
7
/////////////////////////////////////////////////////////////////
8
// See readme.txt for more details                             //
9
/////////////////////////////////////////////////////////////////
10
//                                                             //
11
// module.audio-video.quicktime.php                            //
12
// module for analyzing Quicktime and MP3-in-MP4 files         //
13
// dependencies: module.audio.mp3.php                          //
14
// dependencies: module.tag.id3v2.php                          //
15
//                                                            ///
16
/////////////////////////////////////////////////////////////////
17
18
getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.mp3.php', __FILE__, true);
19
getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.tag.id3v2.php', __FILE__, true); // needed for ISO 639-2 language code lookup
20
21
class getid3_quicktime extends getid3_handler
22
{
23
24
	public $ReturnAtomData        = true;
25
	public $ParseAllPossibleAtoms = false;
26
27
	public function Analyze() {
28
		$info = &$this->getid3->info;
29
30
		$info['fileformat'] = 'quicktime';
31
		$info['quicktime']['hinting']    = false;
32
		$info['quicktime']['controller'] = 'standard'; // may be overridden if 'ctyp' atom is present
33
34
		$this->fseek($info['avdataoffset']);
35
36
		$offset      = 0;
37
		$atomcounter = 0;
38
		$atom_data_read_buffer_size = max($this->getid3->option_fread_buffer_size * 1024, ($info['php_memory_limit'] ? round($info['php_memory_limit'] / 4) : 1024)); // set read buffer to 25% of PHP memory limit (if one is specified), otherwise use option_fread_buffer_size [default: 32MB]
39
		while ($offset < $info['avdataend']) {
40
			if (!getid3_lib::intValueSupported($offset)) {
41
				$this->error('Unable to parse atom at offset '.$offset.' because beyond '.round(PHP_INT_MAX / 1073741824).'GB limit of PHP filesystem functions');
42
				break;
43
			}
44
			$this->fseek($offset);
45
			$AtomHeader = $this->fread(8);
46
47
			$atomsize = getid3_lib::BigEndian2Int(substr($AtomHeader, 0, 4));
48
			$atomname = substr($AtomHeader, 4, 4);
49
50
			// 64-bit MOV patch by jlegateØktnc*com
51
			if ($atomsize == 1) {
52
				$atomsize = getid3_lib::BigEndian2Int($this->fread(8));
53
			}
54
55
			$info['quicktime'][$atomname]['name']   = $atomname;
56
			$info['quicktime'][$atomname]['size']   = $atomsize;
57
			$info['quicktime'][$atomname]['offset'] = $offset;
58
59
			if (($offset + $atomsize) > $info['avdataend']) {
60
				$this->error('Atom at offset '.$offset.' claims to go beyond end-of-file (length: '.$atomsize.' bytes)');
61
				return false;
62
			}
63
64
			if ($atomsize == 0) {
65
				// Furthermore, for historical reasons the list of atoms is optionally
66
				// terminated by a 32-bit integer set to 0. If you are writing a program
67
				// to read user data atoms, you should allow for the terminating 0.
68
				break;
69
			}
70
			$atomHierarchy = array();
71
			$info['quicktime'][$atomname] = $this->QuicktimeParseAtom($atomname, $atomsize, $this->fread(min($atomsize, $atom_data_read_buffer_size)), $offset, $atomHierarchy, $this->ParseAllPossibleAtoms);
72
73
			$offset += $atomsize;
74
			$atomcounter++;
75
		}
76
77
		if (!empty($info['avdataend_tmp'])) {
78
			// this value is assigned to a temp value and then erased because
79
			// otherwise any atoms beyond the 'mdat' atom would not get parsed
80
			$info['avdataend'] = $info['avdataend_tmp'];
81
			unset($info['avdataend_tmp']);
82
		}
83
84
		if (!empty($info['quicktime']['comments']['chapters']) && is_array($info['quicktime']['comments']['chapters']) && (count($info['quicktime']['comments']['chapters']) > 0)) {
85
			$durations = $this->quicktime_time_to_sample_table($info);
86
			for ($i = 0; $i < count($info['quicktime']['comments']['chapters']); $i++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
87
				$bookmark = array();
88
				$bookmark['title'] = $info['quicktime']['comments']['chapters'][$i];
89
				if (isset($durations[$i])) {
90
					$bookmark['duration_sample'] = $durations[$i]['sample_duration'];
91
					if ($i > 0) {
92
						$bookmark['start_sample'] = $info['quicktime']['bookmarks'][($i - 1)]['start_sample'] + $info['quicktime']['bookmarks'][($i - 1)]['duration_sample'];
93
					} else {
94
						$bookmark['start_sample'] = 0;
95
					}
96
					if ($time_scale = $this->quicktime_bookmark_time_scale($info)) {
97
						$bookmark['duration_seconds'] = $bookmark['duration_sample'] / $time_scale;
98
						$bookmark['start_seconds']    = $bookmark['start_sample']    / $time_scale;
99
					}
100
				}
101
				$info['quicktime']['bookmarks'][] = $bookmark;
102
			}
103
		}
104
105
		if (isset($info['quicktime']['temp_meta_key_names'])) {
106
			unset($info['quicktime']['temp_meta_key_names']);
107
		}
108
109
		if (!empty($info['quicktime']['comments']['location.ISO6709'])) {
110
			// https://en.wikipedia.org/wiki/ISO_6709
111
			foreach ($info['quicktime']['comments']['location.ISO6709'] as $ISO6709string) {
112
				$latitude  = false;
113
				$longitude = false;
114
				$altitude  = false;
115
				if (preg_match('#^([\\+\\-])([0-9]{2}|[0-9]{4}|[0-9]{6})(\\.[0-9]+)?([\\+\\-])([0-9]{3}|[0-9]{5}|[0-9]{7})(\\.[0-9]+)?(([\\+\\-])([0-9]{3}|[0-9]{5}|[0-9]{7})(\\.[0-9]+)?)?/$#', $ISO6709string, $matches)) {
116
					@list($dummy, $lat_sign, $lat_deg, $lat_deg_dec, $lon_sign, $lon_deg, $lon_deg_dec, $dummy, $alt_sign, $alt_deg, $alt_deg_dec) = $matches;
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
117
118 View Code Duplication
					if (strlen($lat_deg) == 2) {        // [+-]DD.D
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
119
						$latitude = floatval(ltrim($lat_deg, '0').$lat_deg_dec);
120
					} elseif (strlen($lat_deg) == 4) {  // [+-]DDMM.M
121
						$latitude = floatval(ltrim(substr($lat_deg, 0, 2), '0')) + floatval(ltrim(substr($lat_deg, 2, 2), '0').$lat_deg_dec / 60);
122
					} elseif (strlen($lat_deg) == 6) {  // [+-]DDMMSS.S
123
						$latitude = floatval(ltrim(substr($lat_deg, 0, 2), '0')) + floatval(ltrim(substr($lat_deg, 2, 2), '0') / 60) + floatval(ltrim(substr($lat_deg, 4, 2), '0').$lat_deg_dec / 3600);
124
					}
125
126 View Code Duplication
					if (strlen($lon_deg) == 3) {        // [+-]DDD.D
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
127
						$longitude = floatval(ltrim($lon_deg, '0').$lon_deg_dec);
128
					} elseif (strlen($lon_deg) == 5) {  // [+-]DDDMM.M
129
						$longitude = floatval(ltrim(substr($lon_deg, 0, 2), '0')) + floatval(ltrim(substr($lon_deg, 2, 2), '0').$lon_deg_dec / 60);
130
					} elseif (strlen($lon_deg) == 7) {  // [+-]DDDMMSS.S
131
						$longitude = floatval(ltrim(substr($lon_deg, 0, 2), '0')) + floatval(ltrim(substr($lon_deg, 2, 2), '0') / 60) + floatval(ltrim(substr($lon_deg, 4, 2), '0').$lon_deg_dec / 3600);
132
					}
133
134 View Code Duplication
					if (strlen($alt_deg) == 3) {        // [+-]DDD.D
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
135
						$altitude = floatval(ltrim($alt_deg, '0').$alt_deg_dec);
136
					} elseif (strlen($alt_deg) == 5) {  // [+-]DDDMM.M
137
						$altitude = floatval(ltrim(substr($alt_deg, 0, 2), '0')) + floatval(ltrim(substr($alt_deg, 2, 2), '0').$alt_deg_dec / 60);
138
					} elseif (strlen($alt_deg) == 7) {  // [+-]DDDMMSS.S
139
						$altitude = floatval(ltrim(substr($alt_deg, 0, 2), '0')) + floatval(ltrim(substr($alt_deg, 2, 2), '0') / 60) + floatval(ltrim(substr($alt_deg, 4, 2), '0').$alt_deg_dec / 3600);
140
					}
141
142 View Code Duplication
					if ($latitude !== false) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
143
						$info['quicktime']['comments']['gps_latitude'][]  = (($lat_sign == '-') ? -1 : 1) * floatval($latitude);
144
					}
145 View Code Duplication
					if ($longitude !== false) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
146
						$info['quicktime']['comments']['gps_longitude'][] = (($lon_sign == '-') ? -1 : 1) * floatval($longitude);
147
					}
148 View Code Duplication
					if ($altitude !== false) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
149
						$info['quicktime']['comments']['gps_altitude'][]  = (($alt_sign == '-') ? -1 : 1) * floatval($altitude);
150
					}
151
				}
152
				if ($latitude === false) {
153
					$this->warning('location.ISO6709 string not parsed correctly: "'.$ISO6709string.'", please submit as a bug');
154
				}
155
				break;
156
			}
157
		}
158
159 View Code Duplication
		if (!isset($info['bitrate']) && isset($info['playtime_seconds'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
160
			$info['bitrate'] = (($info['avdataend'] - $info['avdataoffset']) * 8) / $info['playtime_seconds'];
161
		}
162
		if (isset($info['bitrate']) && !isset($info['audio']['bitrate']) && !isset($info['quicktime']['video'])) {
163
			$info['audio']['bitrate'] = $info['bitrate'];
164
		}
165
		if (!empty($info['playtime_seconds']) && !isset($info['video']['frame_rate']) && !empty($info['quicktime']['stts_framecount'])) {
166
			foreach ($info['quicktime']['stts_framecount'] as $key => $samples_count) {
167
				$samples_per_second = $samples_count / $info['playtime_seconds'];
168
				if ($samples_per_second > 240) {
169
					// has to be audio samples
170
				} else {
171
					$info['video']['frame_rate'] = $samples_per_second;
172
					break;
173
				}
174
			}
175
		}
176
		if ($info['audio']['dataformat'] == 'mp4') {
177
			$info['fileformat'] = 'mp4';
178
			if (empty($info['video']['resolution_x'])) {
179
				$info['mime_type']  = 'audio/mp4';
180
				unset($info['video']['dataformat']);
181
			} else {
182
				$info['mime_type']  = 'video/mp4';
183
			}
184
		}
185
186
		if (!$this->ReturnAtomData) {
187
			unset($info['quicktime']['moov']);
188
		}
189
190 View Code Duplication
		if (empty($info['audio']['dataformat']) && !empty($info['quicktime']['audio'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
191
			$info['audio']['dataformat'] = 'quicktime';
192
		}
193 View Code Duplication
		if (empty($info['video']['dataformat']) && !empty($info['quicktime']['video'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
194
			$info['video']['dataformat'] = 'quicktime';
195
		}
196
		if (isset($info['video']) && ($info['mime_type'] == 'audio/mp4') && empty($info['video']['resolution_x']) && empty($info['video']['resolution_y']))  {
197
			unset($info['video']);
198
		}
199
200
		return true;
201
	}
202
203
	public function QuicktimeParseAtom($atomname, $atomsize, $atom_data, $baseoffset, &$atomHierarchy, $ParseAllPossibleAtoms) {
204
		// http://developer.apple.com/techpubs/quicktime/qtdevdocs/APIREF/INDEX/atomalphaindex.htm
205
		// https://code.google.com/p/mp4v2/wiki/iTunesMetadata
206
207
		$info = &$this->getid3->info;
208
209
		$atom_parent = end($atomHierarchy); // not array_pop($atomHierarchy); see http://www.getid3.org/phpBB3/viewtopic.php?t=1717
210
		array_push($atomHierarchy, $atomname);
211
		$atom_structure['hierarchy'] = implode(' ', $atomHierarchy);
0 ignored issues
show
Coding Style Comprehensibility introduced by
$atom_structure was never initialized. Although not strictly required by PHP, it is generally a good practice to add $atom_structure = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
212
		$atom_structure['name']      = $atomname;
213
		$atom_structure['size']      = $atomsize;
214
		$atom_structure['offset']    = $baseoffset;
215
		switch ($atomname) {
216
			case 'moov': // MOVie container atom
217
			case 'trak': // TRAcK container atom
218
			case 'clip': // CLIPping container atom
219
			case 'matt': // track MATTe container atom
220
			case 'edts': // EDiTS container atom
221
			case 'tref': // Track REFerence container atom
222
			case 'mdia': // MeDIA container atom
223
			case 'minf': // Media INFormation container atom
224
			case 'dinf': // Data INFormation container atom
225
			case 'udta': // User DaTA container atom
226
			case 'cmov': // Compressed MOVie container atom
227
			case 'rmra': // Reference Movie Record Atom
228
			case 'rmda': // Reference Movie Descriptor Atom
229
			case 'gmhd': // Generic Media info HeaDer atom (seen on QTVR)
230
				$atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms);
231
				break;
232
233
			case 'ilst': // Item LiST container atom
234
				if ($atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms)) {
235
					// some "ilst" atoms contain data atoms that have a numeric name, and the data is far more accessible if the returned array is compacted
236
					$allnumericnames = true;
237
					foreach ($atom_structure['subatoms'] as $subatomarray) {
0 ignored issues
show
Bug introduced by
The expression $atom_structure['subatoms'] of type boolean is not traversable.
Loading history...
238
						if (!is_integer($subatomarray['name']) || (count($subatomarray['subatoms']) != 1)) {
239
							$allnumericnames = false;
240
							break;
241
						}
242
					}
243
					if ($allnumericnames) {
244
						$newData = array();
245
						foreach ($atom_structure['subatoms'] as $subatomarray) {
0 ignored issues
show
Bug introduced by
The expression $atom_structure['subatoms'] of type boolean is not traversable.
Loading history...
246
							foreach ($subatomarray['subatoms'] as $newData_subatomarray) {
247
								unset($newData_subatomarray['hierarchy'], $newData_subatomarray['name']);
248
								$newData[$subatomarray['name']] = $newData_subatomarray;
249
								break;
250
							}
251
						}
252
						$atom_structure['data'] = $newData;
253
						unset($atom_structure['subatoms']);
254
					}
255
				}
256
				break;
257
258
			case "\x00\x00\x00\x01":
259
			case "\x00\x00\x00\x02":
260
			case "\x00\x00\x00\x03":
261
			case "\x00\x00\x00\x04":
262
			case "\x00\x00\x00\x05":
263
				$atomname = getid3_lib::BigEndian2Int($atomname);
264
				$atom_structure['name'] = $atomname;
265
				$atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms);
266
				break;
267
268
			case 'stbl': // Sample TaBLe container atom
269
				$atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms);
270
				$isVideo = false;
271
				$framerate  = 0;
272
				$framecount = 0;
273
				foreach ($atom_structure['subatoms'] as $key => $value_array) {
0 ignored issues
show
Bug introduced by
The expression $atom_structure['subatoms'] of type boolean is not traversable.
Loading history...
274
					if (isset($value_array['sample_description_table'])) {
275
						foreach ($value_array['sample_description_table'] as $key2 => $value_array2) {
276
							if (isset($value_array2['data_format'])) {
277
								switch ($value_array2['data_format']) {
278
									case 'avc1':
279
									case 'mp4v':
280
										// video data
281
										$isVideo = true;
282
										break;
283
									case 'mp4a':
284
										// audio data
285
										break;
286
								}
287
							}
288
						}
289
					} elseif (isset($value_array['time_to_sample_table'])) {
290
						foreach ($value_array['time_to_sample_table'] as $key2 => $value_array2) {
291
							if (isset($value_array2['sample_count']) && isset($value_array2['sample_duration']) && ($value_array2['sample_duration'] > 0)) {
292
								$framerate  = round($info['quicktime']['time_scale'] / $value_array2['sample_duration'], 3);
293
								$framecount = $value_array2['sample_count'];
294
							}
295
						}
296
					}
297
				}
298
				if ($isVideo && $framerate) {
299
					$info['quicktime']['video']['frame_rate'] = $framerate;
300
					$info['video']['frame_rate'] = $info['quicktime']['video']['frame_rate'];
301
				}
302
				if ($isVideo && $framecount) {
303
					$info['quicktime']['video']['frame_count'] = $framecount;
304
				}
305
				break;
306
307
308
			case "\xA9".'alb': // ALBum
309
			case "\xA9".'ART': //
310
			case "\xA9".'art': // ARTist
311
			case "\xA9".'aut': //
312
			case "\xA9".'cmt': // CoMmenT
313
			case "\xA9".'com': // COMposer
314
			case "\xA9".'cpy': //
315
			case "\xA9".'day': // content created year
316
			case "\xA9".'dir': //
317
			case "\xA9".'ed1': //
318
			case "\xA9".'ed2': //
319
			case "\xA9".'ed3': //
320
			case "\xA9".'ed4': //
321
			case "\xA9".'ed5': //
322
			case "\xA9".'ed6': //
323
			case "\xA9".'ed7': //
324
			case "\xA9".'ed8': //
325
			case "\xA9".'ed9': //
326
			case "\xA9".'enc': //
327
			case "\xA9".'fmt': //
328
			case "\xA9".'gen': // GENre
329
			case "\xA9".'grp': // GRouPing
330
			case "\xA9".'hst': //
331
			case "\xA9".'inf': //
332
			case "\xA9".'lyr': // LYRics
333
			case "\xA9".'mak': //
334
			case "\xA9".'mod': //
335
			case "\xA9".'nam': // full NAMe
336
			case "\xA9".'ope': //
337
			case "\xA9".'PRD': //
338
			case "\xA9".'prf': //
339
			case "\xA9".'req': //
340
			case "\xA9".'src': //
341
			case "\xA9".'swr': //
342
			case "\xA9".'too': // encoder
343
			case "\xA9".'trk': // TRacK
344
			case "\xA9".'url': //
345
			case "\xA9".'wrn': //
346
			case "\xA9".'wrt': // WRiTer
347
			case '----': // itunes specific
348
			case 'aART': // Album ARTist
349
			case 'akID': // iTunes store account type
350
			case 'apID': // Purchase Account
351
			case 'atID': //
352
			case 'catg': // CaTeGory
353
			case 'cmID': //
354
			case 'cnID': //
355
			case 'covr': // COVeR artwork
356
			case 'cpil': // ComPILation
357
			case 'cprt': // CoPyRighT
358
			case 'desc': // DESCription
359
			case 'disk': // DISK number
360
			case 'egid': // Episode Global ID
361
			case 'geID': //
362
			case 'gnre': // GeNRE
363
			case 'hdvd': // HD ViDeo
364
			case 'keyw': // KEYWord
365
			case 'ldes': // Long DEScription
366
			case 'pcst': // PodCaST
367
			case 'pgap': // GAPless Playback
368
			case 'plID': //
369
			case 'purd': // PURchase Date
370
			case 'purl': // Podcast URL
371
			case 'rati': //
372
			case 'rndu': //
373
			case 'rpdu': //
374
			case 'rtng': // RaTiNG
375
			case 'sfID': // iTunes store country
376
			case 'soaa': // SOrt Album Artist
377
			case 'soal': // SOrt ALbum
378
			case 'soar': // SOrt ARtist
379
			case 'soco': // SOrt COmposer
380
			case 'sonm': // SOrt NaMe
381
			case 'sosn': // SOrt Show Name
382
			case 'stik': //
383
			case 'tmpo': // TeMPO (BPM)
384
			case 'trkn': // TRacK Number
385
			case 'tven': // tvEpisodeID
386
			case 'tves': // TV EpiSode
387
			case 'tvnn': // TV Network Name
388
			case 'tvsh': // TV SHow Name
389
			case 'tvsn': // TV SeasoN
390
				if ($atom_parent == 'udta') {
391
					// User data atom handler
392
					$atom_structure['data_length'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 2));
393
					$atom_structure['language_id'] = getid3_lib::BigEndian2Int(substr($atom_data, 2, 2));
394
					$atom_structure['data']        =                           substr($atom_data, 4);
395
396
					$atom_structure['language']    = $this->QuicktimeLanguageLookup($atom_structure['language_id']);
397 View Code Duplication
					if (empty($info['comments']['language']) || (!in_array($atom_structure['language'], $info['comments']['language']))) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
398
						$info['comments']['language'][] = $atom_structure['language'];
399
					}
400
				} else {
401
					// Apple item list box atom handler
402
					$atomoffset = 0;
403
					if (substr($atom_data, 2, 2) == "\x10\xB5") {
404
						// not sure what it means, but observed on iPhone4 data.
405
						// Each $atom_data has 2 bytes of datasize, plus 0x10B5, then data
406
						while ($atomoffset < strlen($atom_data)) {
407
							$boxsmallsize = getid3_lib::BigEndian2Int(substr($atom_data, $atomoffset,     2));
408
							$boxsmalltype =                           substr($atom_data, $atomoffset + 2, 2);
409
							$boxsmalldata =                           substr($atom_data, $atomoffset + 4, $boxsmallsize);
410 View Code Duplication
							if ($boxsmallsize <= 1) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
411
								$this->warning('Invalid QuickTime atom smallbox size "'.$boxsmallsize.'" in atom "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $atomname).'" at offset: '.($atom_structure['offset'] + $atomoffset));
412
								$atom_structure['data'] = null;
413
								$atomoffset = strlen($atom_data);
0 ignored issues
show
Unused Code introduced by
$atomoffset is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
414
								break;
415
							}
416
							switch ($boxsmalltype) {
417
								case "\x10\xB5":
418
									$atom_structure['data'] = $boxsmalldata;
419
									break;
420 View Code Duplication
								default:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
421
									$this->warning('Unknown QuickTime smallbox type: "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $boxsmalltype).'" ('.trim(getid3_lib::PrintHexBytes($boxsmalltype)).') at offset '.$baseoffset);
422
									$atom_structure['data'] = $atom_data;
423
									break;
424
							}
425
							$atomoffset += (4 + $boxsmallsize);
426
						}
427
					} else {
428
						while ($atomoffset < strlen($atom_data)) {
429
							$boxsize = getid3_lib::BigEndian2Int(substr($atom_data, $atomoffset, 4));
430
							$boxtype =                           substr($atom_data, $atomoffset + 4, 4);
431
							$boxdata =                           substr($atom_data, $atomoffset + 8, $boxsize - 8);
432 View Code Duplication
							if ($boxsize <= 1) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
433
								$this->warning('Invalid QuickTime atom box size "'.$boxsize.'" in atom "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $atomname).'" at offset: '.($atom_structure['offset'] + $atomoffset));
434
								$atom_structure['data'] = null;
435
								$atomoffset = strlen($atom_data);
0 ignored issues
show
Unused Code introduced by
$atomoffset is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
436
								break;
437
							}
438
							$atomoffset += $boxsize;
439
440
							switch ($boxtype) {
441
								case 'mean':
442
								case 'name':
443
									$atom_structure[$boxtype] = substr($boxdata, 4);
444
									break;
445
446
								case 'data':
447
									$atom_structure['version']   = getid3_lib::BigEndian2Int(substr($boxdata,  0, 1));
448
									$atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($boxdata,  1, 3));
449
									switch ($atom_structure['flags_raw']) {
450
										case  0: // data flag
451
										case 21: // tmpo/cpil flag
452
											switch ($atomname) {
453
												case 'cpil':
454
												case 'hdvd':
455
												case 'pcst':
456
												case 'pgap':
457
													// 8-bit integer (boolean)
458
													$atom_structure['data'] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 1));
459
													break;
460
461
												case 'tmpo':
462
													// 16-bit integer
463
													$atom_structure['data'] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 2));
464
													break;
465
466
												case 'disk':
467
												case 'trkn':
468
													// binary
469
													$num       = getid3_lib::BigEndian2Int(substr($boxdata, 10, 2));
470
													$num_total = getid3_lib::BigEndian2Int(substr($boxdata, 12, 2));
471
													$atom_structure['data']  = empty($num) ? '' : $num;
472
													$atom_structure['data'] .= empty($num_total) ? '' : '/'.$num_total;
473
													break;
474
475
												case 'gnre':
476
													// enum
477
													$GenreID = getid3_lib::BigEndian2Int(substr($boxdata, 8, 4));
478
													$atom_structure['data']    = getid3_id3v1::LookupGenreName($GenreID - 1);
479
													break;
480
481 View Code Duplication
												case 'rtng':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
482
													// 8-bit integer
483
													$atom_structure[$atomname] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 1));
484
													$atom_structure['data']    = $this->QuicktimeContentRatingLookup($atom_structure[$atomname]);
485
													break;
486
487 View Code Duplication
												case 'stik':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
488
													// 8-bit integer (enum)
489
													$atom_structure[$atomname] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 1));
490
													$atom_structure['data']    = $this->QuicktimeSTIKLookup($atom_structure[$atomname]);
491
													break;
492
493 View Code Duplication
												case 'sfID':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
494
													// 32-bit integer
495
													$atom_structure[$atomname] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 4));
496
													$atom_structure['data']    = $this->QuicktimeStoreFrontCodeLookup($atom_structure[$atomname]);
497
													break;
498
499
												case 'egid':
500
												case 'purl':
501
													$atom_structure['data'] = substr($boxdata, 8);
502
													break;
503
504
												case 'plID':
505
													// 64-bit integer
506
													$atom_structure['data'] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 8));
507
													break;
508
509 View Code Duplication
												case 'covr':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
510
													$atom_structure['data'] = substr($boxdata, 8);
511
													// not a foolproof check, but better than nothing
512
													if (preg_match('#^\\xFF\\xD8\\xFF#', $atom_structure['data'])) {
513
														$atom_structure['image_mime'] = 'image/jpeg';
514
													} elseif (preg_match('#^\\x89\\x50\\x4E\\x47\\x0D\\x0A\\x1A\\x0A#', $atom_structure['data'])) {
515
														$atom_structure['image_mime'] = 'image/png';
516
													} elseif (preg_match('#^GIF#', $atom_structure['data'])) {
517
														$atom_structure['image_mime'] = 'image/gif';
518
													}
519
													break;
520
521
												case 'atID':
522
												case 'cnID':
523
												case 'geID':
524
												case 'tves':
525
												case 'tvsn':
526
												default:
527
													// 32-bit integer
528
													$atom_structure['data'] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 4));
529
											}
530
											break;
531
532
										case  1: // text flag
533
										case 13: // image flag
534 View Code Duplication
										default:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
535
											$atom_structure['data'] = substr($boxdata, 8);
536
											if ($atomname == 'covr') {
537
												// not a foolproof check, but better than nothing
538
												if (preg_match('#^\\xFF\\xD8\\xFF#', $atom_structure['data'])) {
539
													$atom_structure['image_mime'] = 'image/jpeg';
540
												} elseif (preg_match('#^\\x89\\x50\\x4E\\x47\\x0D\\x0A\\x1A\\x0A#', $atom_structure['data'])) {
541
													$atom_structure['image_mime'] = 'image/png';
542
												} elseif (preg_match('#^GIF#', $atom_structure['data'])) {
543
													$atom_structure['image_mime'] = 'image/gif';
544
												}
545
											}
546
											break;
547
548
									}
549
									break;
550
551 View Code Duplication
								default:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
552
									$this->warning('Unknown QuickTime box type: "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $boxtype).'" ('.trim(getid3_lib::PrintHexBytes($boxtype)).') at offset '.$baseoffset);
553
									$atom_structure['data'] = $atom_data;
554
555
							}
556
						}
557
					}
558
				}
559
				$this->CopyToAppropriateCommentsSection($atomname, $atom_structure['data'], $atom_structure['name']);
560
				break;
561
562
563
			case 'play': // auto-PLAY atom
564
				$atom_structure['autoplay'] = (bool) getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
565
566
				$info['quicktime']['autoplay'] = $atom_structure['autoplay'];
567
				break;
568
569
570 View Code Duplication
			case 'WLOC': // Window LOCation atom
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
571
				$atom_structure['location_x']  = getid3_lib::BigEndian2Int(substr($atom_data,  0, 2));
572
				$atom_structure['location_y']  = getid3_lib::BigEndian2Int(substr($atom_data,  2, 2));
573
				break;
574
575
576
			case 'LOOP': // LOOPing atom
577
			case 'SelO': // play SELection Only atom
578
			case 'AllF': // play ALL Frames atom
579
				$atom_structure['data'] = getid3_lib::BigEndian2Int($atom_data);
580
				break;
581
582
583
			case 'name': //
584
			case 'MCPS': // Media Cleaner PRo
585
			case '@PRM': // adobe PReMiere version
586
			case '@PRQ': // adobe PRemiere Quicktime version
587
				$atom_structure['data'] = $atom_data;
588
				break;
589
590
591
			case 'cmvd': // Compressed MooV Data atom
592
				// Code by ubergeekØubergeek*tv based on information from
593
				// http://developer.apple.com/quicktime/icefloe/dispatch012.html
594
				$atom_structure['unCompressedSize'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 4));
595
596
				$CompressedFileData = substr($atom_data, 4);
597
				if ($UncompressedHeader = @gzuncompress($CompressedFileData)) {
598
					$atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($UncompressedHeader, 0, $atomHierarchy, $ParseAllPossibleAtoms);
599
				} else {
600
					$this->warning('Error decompressing compressed MOV atom at offset '.$atom_structure['offset']);
601
				}
602
				break;
603
604
605
			case 'dcom': // Data COMpression atom
606
				$atom_structure['compression_id']   = $atom_data;
607
				$atom_structure['compression_text'] = $this->QuicktimeDCOMLookup($atom_data);
608
				break;
609
610
611
			case 'rdrf': // Reference movie Data ReFerence atom
612
				$atom_structure['version']                = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
613
				$atom_structure['flags_raw']              = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3));
614
				$atom_structure['flags']['internal_data'] = (bool) ($atom_structure['flags_raw'] & 0x000001);
615
616
				$atom_structure['reference_type_name']    =                           substr($atom_data,  4, 4);
617
				$atom_structure['reference_length']       = getid3_lib::BigEndian2Int(substr($atom_data,  8, 4));
618
				switch ($atom_structure['reference_type_name']) {
619
					case 'url ':
620
						$atom_structure['url']            =       $this->NoNullString(substr($atom_data, 12));
621
						break;
622
623
					case 'alis':
624
						$atom_structure['file_alias']     =                           substr($atom_data, 12);
625
						break;
626
627
					case 'rsrc':
628
						$atom_structure['resource_alias'] =                           substr($atom_data, 12);
629
						break;
630
631
					default:
632
						$atom_structure['data']           =                           substr($atom_data, 12);
633
						break;
634
				}
635
				break;
636
637
638
			case 'rmqu': // Reference Movie QUality atom
639
				$atom_structure['movie_quality'] = getid3_lib::BigEndian2Int($atom_data);
640
				break;
641
642
643 View Code Duplication
			case 'rmcs': // Reference Movie Cpu Speed atom
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
644
				$atom_structure['version']          = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
645
				$atom_structure['flags_raw']        = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
646
				$atom_structure['cpu_speed_rating'] = getid3_lib::BigEndian2Int(substr($atom_data,  4, 2));
647
				break;
648
649
650
			case 'rmvc': // Reference Movie Version Check atom
651
				$atom_structure['version']            = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
652
				$atom_structure['flags_raw']          = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
653
				$atom_structure['gestalt_selector']   =                           substr($atom_data,  4, 4);
654
				$atom_structure['gestalt_value_mask'] = getid3_lib::BigEndian2Int(substr($atom_data,  8, 4));
655
				$atom_structure['gestalt_value']      = getid3_lib::BigEndian2Int(substr($atom_data, 12, 4));
656
				$atom_structure['gestalt_check_type'] = getid3_lib::BigEndian2Int(substr($atom_data, 14, 2));
657
				break;
658
659
660
			case 'rmcd': // Reference Movie Component check atom
661
				$atom_structure['version']                = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
662
				$atom_structure['flags_raw']              = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
663
				$atom_structure['component_type']         =                           substr($atom_data,  4, 4);
664
				$atom_structure['component_subtype']      =                           substr($atom_data,  8, 4);
665
				$atom_structure['component_manufacturer'] =                           substr($atom_data, 12, 4);
666
				$atom_structure['component_flags_raw']    = getid3_lib::BigEndian2Int(substr($atom_data, 16, 4));
667
				$atom_structure['component_flags_mask']   = getid3_lib::BigEndian2Int(substr($atom_data, 20, 4));
668
				$atom_structure['component_min_version']  = getid3_lib::BigEndian2Int(substr($atom_data, 24, 4));
669
				break;
670
671
672 View Code Duplication
			case 'rmdr': // Reference Movie Data Rate atom
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
673
				$atom_structure['version']       = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
674
				$atom_structure['flags_raw']     = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
675
				$atom_structure['data_rate']     = getid3_lib::BigEndian2Int(substr($atom_data,  4, 4));
676
677
				$atom_structure['data_rate_bps'] = $atom_structure['data_rate'] * 10;
678
				break;
679
680
681
			case 'rmla': // Reference Movie Language Atom
682
				$atom_structure['version']     = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
683
				$atom_structure['flags_raw']   = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
684
				$atom_structure['language_id'] = getid3_lib::BigEndian2Int(substr($atom_data,  4, 2));
685
686
				$atom_structure['language']    = $this->QuicktimeLanguageLookup($atom_structure['language_id']);
687 View Code Duplication
				if (empty($info['comments']['language']) || (!in_array($atom_structure['language'], $info['comments']['language']))) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
688
					$info['comments']['language'][] = $atom_structure['language'];
689
				}
690
				break;
691
692
693 View Code Duplication
			case 'rmla': // Reference Movie Language Atom
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
694
				$atom_structure['version']   = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
695
				$atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
696
				$atom_structure['track_id']  = getid3_lib::BigEndian2Int(substr($atom_data,  4, 2));
697
				break;
698
699
700
			case 'ptv ': // Print To Video - defines a movie's full screen mode
701
				// http://developer.apple.com/documentation/QuickTime/APIREF/SOURCESIV/at_ptv-_pg.htm
702
				$atom_structure['display_size_raw']  = getid3_lib::BigEndian2Int(substr($atom_data, 0, 2));
703
				$atom_structure['reserved_1']        = getid3_lib::BigEndian2Int(substr($atom_data, 2, 2)); // hardcoded: 0x0000
704
				$atom_structure['reserved_2']        = getid3_lib::BigEndian2Int(substr($atom_data, 4, 2)); // hardcoded: 0x0000
705
				$atom_structure['slide_show_flag']   = getid3_lib::BigEndian2Int(substr($atom_data, 6, 1));
706
				$atom_structure['play_on_open_flag'] = getid3_lib::BigEndian2Int(substr($atom_data, 7, 1));
707
708
				$atom_structure['flags']['play_on_open'] = (bool) $atom_structure['play_on_open_flag'];
709
				$atom_structure['flags']['slide_show']   = (bool) $atom_structure['slide_show_flag'];
710
711
				$ptv_lookup[0] = 'normal';
0 ignored issues
show
Coding Style Comprehensibility introduced by
$ptv_lookup was never initialized. Although not strictly required by PHP, it is generally a good practice to add $ptv_lookup = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
712
				$ptv_lookup[1] = 'double';
713
				$ptv_lookup[2] = 'half';
714
				$ptv_lookup[3] = 'full';
715
				$ptv_lookup[4] = 'current';
716
				if (isset($ptv_lookup[$atom_structure['display_size_raw']])) {
717
					$atom_structure['display_size'] = $ptv_lookup[$atom_structure['display_size_raw']];
718
				} else {
719
					$this->warning('unknown "ptv " display constant ('.$atom_structure['display_size_raw'].')');
720
				}
721
				break;
722
723
724
			case 'stsd': // Sample Table Sample Description atom
725
				$atom_structure['version']        = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
726
				$atom_structure['flags_raw']      = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
727
				$atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data,  4, 4));
728
729
				// see: https://github.com/JamesHeinrich/getID3/issues/111
730
				// Some corrupt files have been known to have high bits set in the number_entries field
731
				// This field shouldn't really need to be 32-bits, values stores are likely in the range 1-100000
732
				// Workaround: mask off the upper byte and throw a warning if it's nonzero
733
				if ($atom_structure['number_entries'] > 0x000FFFFF) {
734
					if ($atom_structure['number_entries'] > 0x00FFFFFF) {
735
						$this->warning('"stsd" atom contains improbably large number_entries (0x'.getid3_lib::PrintHexBytes(substr($atom_data, 4, 4), true, false).' = '.$atom_structure['number_entries'].'), probably in error. Ignoring upper byte and interpreting this as 0x'.getid3_lib::PrintHexBytes(substr($atom_data, 5, 3), true, false).' = '.($atom_structure['number_entries'] & 0x00FFFFFF));
736
						$atom_structure['number_entries'] = ($atom_structure['number_entries'] & 0x00FFFFFF);
737 View Code Duplication
					} else {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
738
						$this->warning('"stsd" atom contains improbably large number_entries (0x'.getid3_lib::PrintHexBytes(substr($atom_data, 4, 4), true, false).' = '.$atom_structure['number_entries'].'), probably in error. Please report this to [email protected] referencing bug report #111');
739
					}
740
				}
741
742
				$stsdEntriesDataOffset = 8;
743
				for ($i = 0; $i < $atom_structure['number_entries']; $i++) {
744
					$atom_structure['sample_description_table'][$i]['size']             = getid3_lib::BigEndian2Int(substr($atom_data, $stsdEntriesDataOffset, 4));
745
					$stsdEntriesDataOffset += 4;
746
					$atom_structure['sample_description_table'][$i]['data_format']      =                           substr($atom_data, $stsdEntriesDataOffset, 4);
747
					$stsdEntriesDataOffset += 4;
748
					$atom_structure['sample_description_table'][$i]['reserved']         = getid3_lib::BigEndian2Int(substr($atom_data, $stsdEntriesDataOffset, 6));
749
					$stsdEntriesDataOffset += 6;
750
					$atom_structure['sample_description_table'][$i]['reference_index']  = getid3_lib::BigEndian2Int(substr($atom_data, $stsdEntriesDataOffset, 2));
751
					$stsdEntriesDataOffset += 2;
752
					$atom_structure['sample_description_table'][$i]['data']             =                           substr($atom_data, $stsdEntriesDataOffset, ($atom_structure['sample_description_table'][$i]['size'] - 4 - 4 - 6 - 2));
753
					$stsdEntriesDataOffset += ($atom_structure['sample_description_table'][$i]['size'] - 4 - 4 - 6 - 2);
754
755
					$atom_structure['sample_description_table'][$i]['encoder_version']  = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'],  0, 2));
756
					$atom_structure['sample_description_table'][$i]['encoder_revision'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'],  2, 2));
757
					$atom_structure['sample_description_table'][$i]['encoder_vendor']   =                           substr($atom_structure['sample_description_table'][$i]['data'],  4, 4);
758
759
					switch ($atom_structure['sample_description_table'][$i]['encoder_vendor']) {
760
761
						case "\x00\x00\x00\x00":
762
							// audio tracks
763
							$atom_structure['sample_description_table'][$i]['audio_channels']       =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'],  8,  2));
764
							$atom_structure['sample_description_table'][$i]['audio_bit_depth']      =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 10,  2));
765
							$atom_structure['sample_description_table'][$i]['audio_compression_id'] =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 12,  2));
766
							$atom_structure['sample_description_table'][$i]['audio_packet_size']    =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 14,  2));
767
							$atom_structure['sample_description_table'][$i]['audio_sample_rate']    = getid3_lib::FixedPoint16_16(substr($atom_structure['sample_description_table'][$i]['data'], 16,  4));
768
769
							// video tracks
770
							// http://developer.apple.com/library/mac/#documentation/QuickTime/QTFF/QTFFChap3/qtff3.html
771
							$atom_structure['sample_description_table'][$i]['temporal_quality'] =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'],  8,  4));
772
							$atom_structure['sample_description_table'][$i]['spatial_quality']  =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 12,  4));
773
							$atom_structure['sample_description_table'][$i]['width']            =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 16,  2));
774
							$atom_structure['sample_description_table'][$i]['height']           =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 18,  2));
775
							$atom_structure['sample_description_table'][$i]['resolution_x']     = getid3_lib::FixedPoint16_16(substr($atom_structure['sample_description_table'][$i]['data'], 24,  4));
776
							$atom_structure['sample_description_table'][$i]['resolution_y']     = getid3_lib::FixedPoint16_16(substr($atom_structure['sample_description_table'][$i]['data'], 28,  4));
777
							$atom_structure['sample_description_table'][$i]['data_size']        =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 32,  4));
778
							$atom_structure['sample_description_table'][$i]['frame_count']      =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 36,  2));
779
							$atom_structure['sample_description_table'][$i]['compressor_name']  =                             substr($atom_structure['sample_description_table'][$i]['data'], 38,  4);
780
							$atom_structure['sample_description_table'][$i]['pixel_depth']      =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 42,  2));
781
							$atom_structure['sample_description_table'][$i]['color_table_id']   =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 44,  2));
782
783
							switch ($atom_structure['sample_description_table'][$i]['data_format']) {
784
								case '2vuY':
785
								case 'avc1':
786
								case 'cvid':
787
								case 'dvc ':
788
								case 'dvcp':
789
								case 'gif ':
790
								case 'h263':
791
								case 'jpeg':
792
								case 'kpcd':
793
								case 'mjpa':
794
								case 'mjpb':
795
								case 'mp4v':
796
								case 'png ':
797
								case 'raw ':
798
								case 'rle ':
799
								case 'rpza':
800
								case 'smc ':
801
								case 'SVQ1':
802
								case 'SVQ3':
803
								case 'tiff':
804
								case 'v210':
805
								case 'v216':
806
								case 'v308':
807
								case 'v408':
808
								case 'v410':
809
								case 'yuv2':
810
									$info['fileformat'] = 'mp4';
811
									$info['video']['fourcc'] = $atom_structure['sample_description_table'][$i]['data_format'];
812
// http://www.getid3.org/phpBB3/viewtopic.php?t=1550
813
//if ((!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($atom_structure['sample_description_table'][$i]['width'])) && (empty($info['video']['resolution_x']) || empty($info['video']['resolution_y']) || (number_format($info['video']['resolution_x'], 6) != number_format(round($info['video']['resolution_x']), 6)) || (number_format($info['video']['resolution_y'], 6) != number_format(round($info['video']['resolution_y']), 6)))) { // ugly check for floating point numbers
814
if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($atom_structure['sample_description_table'][$i]['height'])) {
815
	// assume that values stored here are more important than values stored in [tkhd] atom
816
	$info['video']['resolution_x'] = $atom_structure['sample_description_table'][$i]['width'];
817
	$info['video']['resolution_y'] = $atom_structure['sample_description_table'][$i]['height'];
818
	$info['quicktime']['video']['resolution_x'] = $info['video']['resolution_x'];
819
	$info['quicktime']['video']['resolution_y'] = $info['video']['resolution_y'];
820
}
821
									break;
822
823
								case 'qtvr':
824
									$info['video']['dataformat'] = 'quicktimevr';
825
									break;
826
827
								case 'mp4a':
828
								default:
829
									$info['quicktime']['audio']['codec']       = $this->QuicktimeAudioCodecLookup($atom_structure['sample_description_table'][$i]['data_format']);
830
									$info['quicktime']['audio']['sample_rate'] = $atom_structure['sample_description_table'][$i]['audio_sample_rate'];
831
									$info['quicktime']['audio']['channels']    = $atom_structure['sample_description_table'][$i]['audio_channels'];
832
									$info['quicktime']['audio']['bit_depth']   = $atom_structure['sample_description_table'][$i]['audio_bit_depth'];
833
									$info['audio']['codec']                    = $info['quicktime']['audio']['codec'];
834
									$info['audio']['sample_rate']              = $info['quicktime']['audio']['sample_rate'];
835
									$info['audio']['channels']                 = $info['quicktime']['audio']['channels'];
836
									$info['audio']['bits_per_sample']          = $info['quicktime']['audio']['bit_depth'];
837
									switch ($atom_structure['sample_description_table'][$i]['data_format']) {
838
										case 'raw ': // PCM
839
										case 'alac': // Apple Lossless Audio Codec
840
											$info['audio']['lossless'] = true;
841
											break;
842
										default:
843
											$info['audio']['lossless'] = false;
844
											break;
845
									}
846
									break;
847
							}
848
							break;
849
850
						default:
851
							switch ($atom_structure['sample_description_table'][$i]['data_format']) {
852
								case 'mp4s':
853
									$info['fileformat'] = 'mp4';
854
									break;
855
856
								default:
857
									// video atom
858
									$atom_structure['sample_description_table'][$i]['video_temporal_quality']  =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'],  8,  4));
859
									$atom_structure['sample_description_table'][$i]['video_spatial_quality']   =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 12,  4));
860
									$atom_structure['sample_description_table'][$i]['video_frame_width']       =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 16,  2));
861
									$atom_structure['sample_description_table'][$i]['video_frame_height']      =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 18,  2));
862
									$atom_structure['sample_description_table'][$i]['video_resolution_x']      = getid3_lib::FixedPoint16_16(substr($atom_structure['sample_description_table'][$i]['data'], 20,  4));
863
									$atom_structure['sample_description_table'][$i]['video_resolution_y']      = getid3_lib::FixedPoint16_16(substr($atom_structure['sample_description_table'][$i]['data'], 24,  4));
864
									$atom_structure['sample_description_table'][$i]['video_data_size']         =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 28,  4));
865
									$atom_structure['sample_description_table'][$i]['video_frame_count']       =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 32,  2));
866
									$atom_structure['sample_description_table'][$i]['video_encoder_name_len']  =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 34,  1));
867
									$atom_structure['sample_description_table'][$i]['video_encoder_name']      =                             substr($atom_structure['sample_description_table'][$i]['data'], 35, $atom_structure['sample_description_table'][$i]['video_encoder_name_len']);
868
									$atom_structure['sample_description_table'][$i]['video_pixel_color_depth'] =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 66,  2));
869
									$atom_structure['sample_description_table'][$i]['video_color_table_id']    =   getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 68,  2));
870
871
									$atom_structure['sample_description_table'][$i]['video_pixel_color_type']  = (($atom_structure['sample_description_table'][$i]['video_pixel_color_depth'] > 32) ? 'grayscale' : 'color');
872
									$atom_structure['sample_description_table'][$i]['video_pixel_color_name']  = $this->QuicktimeColorNameLookup($atom_structure['sample_description_table'][$i]['video_pixel_color_depth']);
873
874
									if ($atom_structure['sample_description_table'][$i]['video_pixel_color_name'] != 'invalid') {
875
										$info['quicktime']['video']['codec_fourcc']        = $atom_structure['sample_description_table'][$i]['data_format'];
876
										$info['quicktime']['video']['codec_fourcc_lookup'] = $this->QuicktimeVideoCodecLookup($atom_structure['sample_description_table'][$i]['data_format']);
877
										$info['quicktime']['video']['codec']               = (($atom_structure['sample_description_table'][$i]['video_encoder_name_len'] > 0) ? $atom_structure['sample_description_table'][$i]['video_encoder_name'] : $atom_structure['sample_description_table'][$i]['data_format']);
878
										$info['quicktime']['video']['color_depth']         = $atom_structure['sample_description_table'][$i]['video_pixel_color_depth'];
879
										$info['quicktime']['video']['color_depth_name']    = $atom_structure['sample_description_table'][$i]['video_pixel_color_name'];
880
881
										$info['video']['codec']           = $info['quicktime']['video']['codec'];
882
										$info['video']['bits_per_sample'] = $info['quicktime']['video']['color_depth'];
883
									}
884
									$info['video']['lossless']           = false;
885
									$info['video']['pixel_aspect_ratio'] = (float) 1;
886
									break;
887
							}
888
							break;
889
					}
890
					switch (strtolower($atom_structure['sample_description_table'][$i]['data_format'])) {
891
						case 'mp4a':
892
							$info['audio']['dataformat']         = 'mp4';
893
							$info['quicktime']['audio']['codec'] = 'mp4';
894
							break;
895
896
						case '3ivx':
897
						case '3iv1':
898
						case '3iv2':
899
							$info['video']['dataformat'] = '3ivx';
900
							break;
901
902
						case 'xvid':
903
							$info['video']['dataformat'] = 'xvid';
904
							break;
905
906
						case 'mp4v':
907
							$info['video']['dataformat'] = 'mpeg4';
908
							break;
909
910
						case 'divx':
911
						case 'div1':
912
						case 'div2':
913
						case 'div3':
914
						case 'div4':
915
						case 'div5':
916
						case 'div6':
917
							$info['video']['dataformat'] = 'divx';
918
							break;
919
920
						default:
921
							// do nothing
922
							break;
923
					}
924
					unset($atom_structure['sample_description_table'][$i]['data']);
925
				}
926
				break;
927
928
929
			case 'stts': // Sample Table Time-to-Sample atom
930
				$atom_structure['version']        = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
931
				$atom_structure['flags_raw']      = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
932
				$atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data,  4, 4));
933
				$sttsEntriesDataOffset = 8;
934
				//$FrameRateCalculatorArray = array();
935
				$frames_count = 0;
936
937
				$max_stts_entries_to_scan = ($info['php_memory_limit'] ? min(floor($this->getid3->memory_limit / 10000), $atom_structure['number_entries']) : $atom_structure['number_entries']);
938
				if ($max_stts_entries_to_scan < $atom_structure['number_entries']) {
939
					$this->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($atom_structure['number_entries'] / 1048576).'MB).');
940
				}
941 View Code Duplication
				for ($i = 0; $i < $max_stts_entries_to_scan; $i++) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
942
					$atom_structure['time_to_sample_table'][$i]['sample_count']    = getid3_lib::BigEndian2Int(substr($atom_data, $sttsEntriesDataOffset, 4));
943
					$sttsEntriesDataOffset += 4;
944
					$atom_structure['time_to_sample_table'][$i]['sample_duration'] = getid3_lib::BigEndian2Int(substr($atom_data, $sttsEntriesDataOffset, 4));
945
					$sttsEntriesDataOffset += 4;
946
947
					$frames_count += $atom_structure['time_to_sample_table'][$i]['sample_count'];
948
949
					// THIS SECTION REPLACED WITH CODE IN "stbl" ATOM
950
					//if (!empty($info['quicktime']['time_scale']) && ($atom_structure['time_to_sample_table'][$i]['sample_duration'] > 0)) {
951
					//	$stts_new_framerate = $info['quicktime']['time_scale'] / $atom_structure['time_to_sample_table'][$i]['sample_duration'];
952
					//	if ($stts_new_framerate <= 60) {
953
					//		// some atoms have durations of "1" giving a very large framerate, which probably is not right
954
					//		$info['video']['frame_rate'] = max($info['video']['frame_rate'], $stts_new_framerate);
955
					//	}
956
					//}
957
					//
958
					//$FrameRateCalculatorArray[($info['quicktime']['time_scale'] / $atom_structure['time_to_sample_table'][$i]['sample_duration'])] += $atom_structure['time_to_sample_table'][$i]['sample_count'];
959
				}
960
				$info['quicktime']['stts_framecount'][] = $frames_count;
961
				//$sttsFramesTotal  = 0;
962
				//$sttsSecondsTotal = 0;
963
				//foreach ($FrameRateCalculatorArray as $frames_per_second => $frame_count) {
964
				//	if (($frames_per_second > 60) || ($frames_per_second < 1)) {
965
				//		// not video FPS information, probably audio information
966
				//		$sttsFramesTotal  = 0;
967
				//		$sttsSecondsTotal = 0;
968
				//		break;
969
				//	}
970
				//	$sttsFramesTotal  += $frame_count;
971
				//	$sttsSecondsTotal += $frame_count / $frames_per_second;
972
				//}
973
				//if (($sttsFramesTotal > 0) && ($sttsSecondsTotal > 0)) {
974
				//	if (($sttsFramesTotal / $sttsSecondsTotal) > $info['video']['frame_rate']) {
975
				//		$info['video']['frame_rate'] = $sttsFramesTotal / $sttsSecondsTotal;
976
				//	}
977
				//}
978
				break;
979
980
981 View Code Duplication
			case 'stss': // Sample Table Sync Sample (key frames) atom
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
982
				if ($ParseAllPossibleAtoms) {
983
					$atom_structure['version']        = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
984
					$atom_structure['flags_raw']      = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
985
					$atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data,  4, 4));
986
					$stssEntriesDataOffset = 8;
987
					for ($i = 0; $i < $atom_structure['number_entries']; $i++) {
988
						$atom_structure['time_to_sample_table'][$i] = getid3_lib::BigEndian2Int(substr($atom_data, $stssEntriesDataOffset, 4));
989
						$stssEntriesDataOffset += 4;
990
					}
991
				}
992
				break;
993
994
995
			case 'stsc': // Sample Table Sample-to-Chunk atom
996
				if ($ParseAllPossibleAtoms) {
997
					$atom_structure['version']        = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
998
					$atom_structure['flags_raw']      = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
999
					$atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data,  4, 4));
1000
					$stscEntriesDataOffset = 8;
1001 View Code Duplication
					for ($i = 0; $i < $atom_structure['number_entries']; $i++) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1002
						$atom_structure['sample_to_chunk_table'][$i]['first_chunk']        = getid3_lib::BigEndian2Int(substr($atom_data, $stscEntriesDataOffset, 4));
1003
						$stscEntriesDataOffset += 4;
1004
						$atom_structure['sample_to_chunk_table'][$i]['samples_per_chunk']  = getid3_lib::BigEndian2Int(substr($atom_data, $stscEntriesDataOffset, 4));
1005
						$stscEntriesDataOffset += 4;
1006
						$atom_structure['sample_to_chunk_table'][$i]['sample_description'] = getid3_lib::BigEndian2Int(substr($atom_data, $stscEntriesDataOffset, 4));
1007
						$stscEntriesDataOffset += 4;
1008
					}
1009
				}
1010
				break;
1011
1012
1013
			case 'stsz': // Sample Table SiZe atom
1014
				if ($ParseAllPossibleAtoms) {
1015
					$atom_structure['version']        = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
1016
					$atom_structure['flags_raw']      = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
1017
					$atom_structure['sample_size']    = getid3_lib::BigEndian2Int(substr($atom_data,  4, 4));
1018
					$atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data,  8, 4));
1019
					$stszEntriesDataOffset = 12;
1020
					if ($atom_structure['sample_size'] == 0) {
1021
						for ($i = 0; $i < $atom_structure['number_entries']; $i++) {
1022
							$atom_structure['sample_size_table'][$i] = getid3_lib::BigEndian2Int(substr($atom_data, $stszEntriesDataOffset, 4));
1023
							$stszEntriesDataOffset += 4;
1024
						}
1025
					}
1026
				}
1027
				break;
1028
1029
1030 View Code Duplication
			case 'stco': // Sample Table Chunk Offset atom
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1031
				if ($ParseAllPossibleAtoms) {
1032
					$atom_structure['version']        = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
1033
					$atom_structure['flags_raw']      = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
1034
					$atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data,  4, 4));
1035
					$stcoEntriesDataOffset = 8;
1036
					for ($i = 0; $i < $atom_structure['number_entries']; $i++) {
1037
						$atom_structure['chunk_offset_table'][$i] = getid3_lib::BigEndian2Int(substr($atom_data, $stcoEntriesDataOffset, 4));
1038
						$stcoEntriesDataOffset += 4;
1039
					}
1040
				}
1041
				break;
1042
1043
1044 View Code Duplication
			case 'co64': // Chunk Offset 64-bit (version of "stco" that supports > 2GB files)
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1045
				if ($ParseAllPossibleAtoms) {
1046
					$atom_structure['version']        = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
1047
					$atom_structure['flags_raw']      = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
1048
					$atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data,  4, 4));
1049
					$stcoEntriesDataOffset = 8;
1050
					for ($i = 0; $i < $atom_structure['number_entries']; $i++) {
1051
						$atom_structure['chunk_offset_table'][$i] = getid3_lib::BigEndian2Int(substr($atom_data, $stcoEntriesDataOffset, 8));
1052
						$stcoEntriesDataOffset += 8;
1053
					}
1054
				}
1055
				break;
1056
1057
1058
			case 'dref': // Data REFerence atom
1059
				$atom_structure['version']        = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
1060
				$atom_structure['flags_raw']      = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
1061
				$atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data,  4, 4));
1062
				$drefDataOffset = 8;
1063
				for ($i = 0; $i < $atom_structure['number_entries']; $i++) {
1064
					$atom_structure['data_references'][$i]['size']                    = getid3_lib::BigEndian2Int(substr($atom_data, $drefDataOffset, 4));
1065
					$drefDataOffset += 4;
1066
					$atom_structure['data_references'][$i]['type']                    =                           substr($atom_data, $drefDataOffset, 4);
1067
					$drefDataOffset += 4;
1068
					$atom_structure['data_references'][$i]['version']                 = getid3_lib::BigEndian2Int(substr($atom_data,  $drefDataOffset, 1));
1069
					$drefDataOffset += 1;
1070
					$atom_structure['data_references'][$i]['flags_raw']               = getid3_lib::BigEndian2Int(substr($atom_data,  $drefDataOffset, 3)); // hardcoded: 0x0000
1071
					$drefDataOffset += 3;
1072
					$atom_structure['data_references'][$i]['data']                    =                           substr($atom_data, $drefDataOffset, ($atom_structure['data_references'][$i]['size'] - 4 - 4 - 1 - 3));
1073
					$drefDataOffset += ($atom_structure['data_references'][$i]['size'] - 4 - 4 - 1 - 3);
1074
1075
					$atom_structure['data_references'][$i]['flags']['self_reference'] = (bool) ($atom_structure['data_references'][$i]['flags_raw'] & 0x001);
1076
				}
1077
				break;
1078
1079
1080
			case 'gmin': // base Media INformation atom
1081
				$atom_structure['version']                = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
1082
				$atom_structure['flags_raw']              = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
1083
				$atom_structure['graphics_mode']          = getid3_lib::BigEndian2Int(substr($atom_data,  4, 2));
1084
				$atom_structure['opcolor_red']            = getid3_lib::BigEndian2Int(substr($atom_data,  6, 2));
1085
				$atom_structure['opcolor_green']          = getid3_lib::BigEndian2Int(substr($atom_data,  8, 2));
1086
				$atom_structure['opcolor_blue']           = getid3_lib::BigEndian2Int(substr($atom_data, 10, 2));
1087
				$atom_structure['balance']                = getid3_lib::BigEndian2Int(substr($atom_data, 12, 2));
1088
				$atom_structure['reserved']               = getid3_lib::BigEndian2Int(substr($atom_data, 14, 2));
1089
				break;
1090
1091
1092 View Code Duplication
			case 'smhd': // Sound Media information HeaDer atom
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1093
				$atom_structure['version']                = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
1094
				$atom_structure['flags_raw']              = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
1095
				$atom_structure['balance']                = getid3_lib::BigEndian2Int(substr($atom_data,  4, 2));
1096
				$atom_structure['reserved']               = getid3_lib::BigEndian2Int(substr($atom_data,  6, 2));
1097
				break;
1098
1099
1100
			case 'vmhd': // Video Media information HeaDer atom
1101
				$atom_structure['version']                = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
1102
				$atom_structure['flags_raw']              = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3));
1103
				$atom_structure['graphics_mode']          = getid3_lib::BigEndian2Int(substr($atom_data,  4, 2));
1104
				$atom_structure['opcolor_red']            = getid3_lib::BigEndian2Int(substr($atom_data,  6, 2));
1105
				$atom_structure['opcolor_green']          = getid3_lib::BigEndian2Int(substr($atom_data,  8, 2));
1106
				$atom_structure['opcolor_blue']           = getid3_lib::BigEndian2Int(substr($atom_data, 10, 2));
1107
1108
				$atom_structure['flags']['no_lean_ahead'] = (bool) ($atom_structure['flags_raw'] & 0x001);
1109
				break;
1110
1111
1112
			case 'hdlr': // HanDLeR reference atom
1113
				$atom_structure['version']                = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
1114
				$atom_structure['flags_raw']              = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
1115
				$atom_structure['component_type']         =                           substr($atom_data,  4, 4);
1116
				$atom_structure['component_subtype']      =                           substr($atom_data,  8, 4);
1117
				$atom_structure['component_manufacturer'] =                           substr($atom_data, 12, 4);
1118
				$atom_structure['component_flags_raw']    = getid3_lib::BigEndian2Int(substr($atom_data, 16, 4));
1119
				$atom_structure['component_flags_mask']   = getid3_lib::BigEndian2Int(substr($atom_data, 20, 4));
1120
				$atom_structure['component_name']         =      $this->Pascal2String(substr($atom_data, 24));
1121
1122
				if (($atom_structure['component_subtype'] == 'STpn') && ($atom_structure['component_manufacturer'] == 'zzzz')) {
1123
					$info['video']['dataformat'] = 'quicktimevr';
1124
				}
1125
				break;
1126
1127
1128
			case 'mdhd': // MeDia HeaDer atom
1129
				$atom_structure['version']               = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
1130
				$atom_structure['flags_raw']             = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
1131
				$atom_structure['creation_time']         = getid3_lib::BigEndian2Int(substr($atom_data,  4, 4));
1132
				$atom_structure['modify_time']           = getid3_lib::BigEndian2Int(substr($atom_data,  8, 4));
1133
				$atom_structure['time_scale']            = getid3_lib::BigEndian2Int(substr($atom_data, 12, 4));
1134
				$atom_structure['duration']              = getid3_lib::BigEndian2Int(substr($atom_data, 16, 4));
1135
				$atom_structure['language_id']           = getid3_lib::BigEndian2Int(substr($atom_data, 20, 2));
1136
				$atom_structure['quality']               = getid3_lib::BigEndian2Int(substr($atom_data, 22, 2));
1137
1138
				if ($atom_structure['time_scale'] == 0) {
1139
					$this->error('Corrupt Quicktime file: mdhd.time_scale == zero');
1140
					return false;
1141
				}
1142
				$info['quicktime']['time_scale'] = ((isset($info['quicktime']['time_scale']) && ($info['quicktime']['time_scale'] < 1000)) ? max($info['quicktime']['time_scale'], $atom_structure['time_scale']) : $atom_structure['time_scale']);
1143
1144
				$atom_structure['creation_time_unix']    = getid3_lib::DateMac2Unix($atom_structure['creation_time']);
1145
				$atom_structure['modify_time_unix']      = getid3_lib::DateMac2Unix($atom_structure['modify_time']);
1146
				$atom_structure['playtime_seconds']      = $atom_structure['duration'] / $atom_structure['time_scale'];
1147
				$atom_structure['language']              = $this->QuicktimeLanguageLookup($atom_structure['language_id']);
1148 View Code Duplication
				if (empty($info['comments']['language']) || (!in_array($atom_structure['language'], $info['comments']['language']))) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1149
					$info['comments']['language'][] = $atom_structure['language'];
1150
				}
1151
				break;
1152
1153
1154
			case 'pnot': // Preview atom
1155
				$atom_structure['modification_date']      = getid3_lib::BigEndian2Int(substr($atom_data,  0, 4)); // "standard Macintosh format"
1156
				$atom_structure['version_number']         = getid3_lib::BigEndian2Int(substr($atom_data,  4, 2)); // hardcoded: 0x00
1157
				$atom_structure['atom_type']              =                           substr($atom_data,  6, 4);        // usually: 'PICT'
1158
				$atom_structure['atom_index']             = getid3_lib::BigEndian2Int(substr($atom_data, 10, 2)); // usually: 0x01
1159
1160
				$atom_structure['modification_date_unix'] = getid3_lib::DateMac2Unix($atom_structure['modification_date']);
1161
				break;
1162
1163
1164 View Code Duplication
			case 'crgn': // Clipping ReGioN atom
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1165
				$atom_structure['region_size']   = getid3_lib::BigEndian2Int(substr($atom_data,  0, 2)); // The Region size, Region boundary box,
1166
				$atom_structure['boundary_box']  = getid3_lib::BigEndian2Int(substr($atom_data,  2, 8)); // and Clipping region data fields
1167
				$atom_structure['clipping_data'] =                           substr($atom_data, 10);           // constitute a QuickDraw region.
1168
				break;
1169
1170
1171
			case 'load': // track LOAD settings atom
1172
				$atom_structure['preload_start_time'] = getid3_lib::BigEndian2Int(substr($atom_data,  0, 4));
1173
				$atom_structure['preload_duration']   = getid3_lib::BigEndian2Int(substr($atom_data,  4, 4));
1174
				$atom_structure['preload_flags_raw']  = getid3_lib::BigEndian2Int(substr($atom_data,  8, 4));
1175
				$atom_structure['default_hints_raw']  = getid3_lib::BigEndian2Int(substr($atom_data, 12, 4));
1176
1177
				$atom_structure['default_hints']['double_buffer'] = (bool) ($atom_structure['default_hints_raw'] & 0x0020);
1178
				$atom_structure['default_hints']['high_quality']  = (bool) ($atom_structure['default_hints_raw'] & 0x0100);
1179
				break;
1180
1181
1182
			case 'tmcd': // TiMe CoDe atom
1183
			case 'chap': // CHAPter list atom
1184
			case 'sync': // SYNChronization atom
1185
			case 'scpt': // tranSCriPT atom
1186 View Code Duplication
			case 'ssrc': // non-primary SouRCe atom
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1187
				for ($i = 0; $i < strlen($atom_data); $i += 4) {
1188
					@$atom_structure['track_id'][] = getid3_lib::BigEndian2Int(substr($atom_data, $i, 4));
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
1189
				}
1190
				break;
1191
1192
1193
			case 'elst': // Edit LiST atom
1194
				$atom_structure['version']        = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
1195
				$atom_structure['flags_raw']      = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
1196
				$atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data,  4, 4));
1197
				for ($i = 0; $i < $atom_structure['number_entries']; $i++ ) {
1198
					$atom_structure['edit_list'][$i]['track_duration'] =   getid3_lib::BigEndian2Int(substr($atom_data, 8 + ($i * 12) + 0, 4));
1199
					$atom_structure['edit_list'][$i]['media_time']     =   getid3_lib::BigEndian2Int(substr($atom_data, 8 + ($i * 12) + 4, 4));
1200
					$atom_structure['edit_list'][$i]['media_rate']     = getid3_lib::FixedPoint16_16(substr($atom_data, 8 + ($i * 12) + 8, 4));
1201
				}
1202
				break;
1203
1204
1205 View Code Duplication
			case 'kmat': // compressed MATte atom
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1206
				$atom_structure['version']        = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
1207
				$atom_structure['flags_raw']      = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3)); // hardcoded: 0x0000
1208
				$atom_structure['matte_data_raw'] =               substr($atom_data,  4);
1209
				break;
1210
1211
1212
			case 'ctab': // Color TABle atom
1213
				$atom_structure['color_table_seed']   = getid3_lib::BigEndian2Int(substr($atom_data,  0, 4)); // hardcoded: 0x00000000
1214
				$atom_structure['color_table_flags']  = getid3_lib::BigEndian2Int(substr($atom_data,  4, 2)); // hardcoded: 0x8000
1215
				$atom_structure['color_table_size']   = getid3_lib::BigEndian2Int(substr($atom_data,  6, 2)) + 1;
1216
				for ($colortableentry = 0; $colortableentry < $atom_structure['color_table_size']; $colortableentry++) {
1217
					$atom_structure['color_table'][$colortableentry]['alpha'] = getid3_lib::BigEndian2Int(substr($atom_data, 8 + ($colortableentry * 8) + 0, 2));
1218
					$atom_structure['color_table'][$colortableentry]['red']   = getid3_lib::BigEndian2Int(substr($atom_data, 8 + ($colortableentry * 8) + 2, 2));
1219
					$atom_structure['color_table'][$colortableentry]['green'] = getid3_lib::BigEndian2Int(substr($atom_data, 8 + ($colortableentry * 8) + 4, 2));
1220
					$atom_structure['color_table'][$colortableentry]['blue']  = getid3_lib::BigEndian2Int(substr($atom_data, 8 + ($colortableentry * 8) + 6, 2));
1221
				}
1222
				break;
1223
1224
1225
			case 'mvhd': // MoVie HeaDer atom
1226
				$atom_structure['version']            =   getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
1227
				$atom_structure['flags_raw']          =   getid3_lib::BigEndian2Int(substr($atom_data,  1, 3));
1228
				$atom_structure['creation_time']      =   getid3_lib::BigEndian2Int(substr($atom_data,  4, 4));
1229
				$atom_structure['modify_time']        =   getid3_lib::BigEndian2Int(substr($atom_data,  8, 4));
1230
				$atom_structure['time_scale']         =   getid3_lib::BigEndian2Int(substr($atom_data, 12, 4));
1231
				$atom_structure['duration']           =   getid3_lib::BigEndian2Int(substr($atom_data, 16, 4));
1232
				$atom_structure['preferred_rate']     = getid3_lib::FixedPoint16_16(substr($atom_data, 20, 4));
1233
				$atom_structure['preferred_volume']   =   getid3_lib::FixedPoint8_8(substr($atom_data, 24, 2));
1234
				$atom_structure['reserved']           =                             substr($atom_data, 26, 10);
1235
				$atom_structure['matrix_a']           = getid3_lib::FixedPoint16_16(substr($atom_data, 36, 4));
1236
				$atom_structure['matrix_b']           = getid3_lib::FixedPoint16_16(substr($atom_data, 40, 4));
1237
				$atom_structure['matrix_u']           =  getid3_lib::FixedPoint2_30(substr($atom_data, 44, 4));
1238
				$atom_structure['matrix_c']           = getid3_lib::FixedPoint16_16(substr($atom_data, 48, 4));
1239
				$atom_structure['matrix_d']           = getid3_lib::FixedPoint16_16(substr($atom_data, 52, 4));
1240
				$atom_structure['matrix_v']           =  getid3_lib::FixedPoint2_30(substr($atom_data, 56, 4));
1241
				$atom_structure['matrix_x']           = getid3_lib::FixedPoint16_16(substr($atom_data, 60, 4));
1242
				$atom_structure['matrix_y']           = getid3_lib::FixedPoint16_16(substr($atom_data, 64, 4));
1243
				$atom_structure['matrix_w']           =  getid3_lib::FixedPoint2_30(substr($atom_data, 68, 4));
1244
				$atom_structure['preview_time']       =   getid3_lib::BigEndian2Int(substr($atom_data, 72, 4));
1245
				$atom_structure['preview_duration']   =   getid3_lib::BigEndian2Int(substr($atom_data, 76, 4));
1246
				$atom_structure['poster_time']        =   getid3_lib::BigEndian2Int(substr($atom_data, 80, 4));
1247
				$atom_structure['selection_time']     =   getid3_lib::BigEndian2Int(substr($atom_data, 84, 4));
1248
				$atom_structure['selection_duration'] =   getid3_lib::BigEndian2Int(substr($atom_data, 88, 4));
1249
				$atom_structure['current_time']       =   getid3_lib::BigEndian2Int(substr($atom_data, 92, 4));
1250
				$atom_structure['next_track_id']      =   getid3_lib::BigEndian2Int(substr($atom_data, 96, 4));
1251
1252
				if ($atom_structure['time_scale'] == 0) {
1253
					$this->error('Corrupt Quicktime file: mvhd.time_scale == zero');
1254
					return false;
1255
				}
1256
				$atom_structure['creation_time_unix']        = getid3_lib::DateMac2Unix($atom_structure['creation_time']);
1257
				$atom_structure['modify_time_unix']          = getid3_lib::DateMac2Unix($atom_structure['modify_time']);
1258
				$info['quicktime']['time_scale']    = ((isset($info['quicktime']['time_scale']) && ($info['quicktime']['time_scale'] < 1000)) ? max($info['quicktime']['time_scale'], $atom_structure['time_scale']) : $atom_structure['time_scale']);
1259
				$info['quicktime']['display_scale'] = $atom_structure['matrix_a'];
1260
				$info['playtime_seconds']           = $atom_structure['duration'] / $atom_structure['time_scale'];
1261
				break;
1262
1263
1264
			case 'tkhd': // TracK HeaDer atom
1265
				$atom_structure['version']             =   getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
1266
				$atom_structure['flags_raw']           =   getid3_lib::BigEndian2Int(substr($atom_data,  1, 3));
1267
				$atom_structure['creation_time']       =   getid3_lib::BigEndian2Int(substr($atom_data,  4, 4));
1268
				$atom_structure['modify_time']         =   getid3_lib::BigEndian2Int(substr($atom_data,  8, 4));
1269
				$atom_structure['trackid']             =   getid3_lib::BigEndian2Int(substr($atom_data, 12, 4));
1270
				$atom_structure['reserved1']           =   getid3_lib::BigEndian2Int(substr($atom_data, 16, 4));
1271
				$atom_structure['duration']            =   getid3_lib::BigEndian2Int(substr($atom_data, 20, 4));
1272
				$atom_structure['reserved2']           =   getid3_lib::BigEndian2Int(substr($atom_data, 24, 8));
1273
				$atom_structure['layer']               =   getid3_lib::BigEndian2Int(substr($atom_data, 32, 2));
1274
				$atom_structure['alternate_group']     =   getid3_lib::BigEndian2Int(substr($atom_data, 34, 2));
1275
				$atom_structure['volume']              =   getid3_lib::FixedPoint8_8(substr($atom_data, 36, 2));
1276
				$atom_structure['reserved3']           =   getid3_lib::BigEndian2Int(substr($atom_data, 38, 2));
1277
// http://developer.apple.com/library/mac/#documentation/QuickTime/RM/MovieBasics/MTEditing/K-Chapter/11MatrixFunctions.html
1278
// http://developer.apple.com/library/mac/#documentation/QuickTime/qtff/QTFFChap4/qtff4.html#//apple_ref/doc/uid/TP40000939-CH206-18737
1279
				$atom_structure['matrix_a']            = getid3_lib::FixedPoint16_16(substr($atom_data, 40, 4));
1280
				$atom_structure['matrix_b']            = getid3_lib::FixedPoint16_16(substr($atom_data, 44, 4));
1281
				$atom_structure['matrix_u']            =  getid3_lib::FixedPoint2_30(substr($atom_data, 48, 4));
1282
				$atom_structure['matrix_c']            = getid3_lib::FixedPoint16_16(substr($atom_data, 52, 4));
1283
				$atom_structure['matrix_d']            = getid3_lib::FixedPoint16_16(substr($atom_data, 56, 4));
1284
				$atom_structure['matrix_v']            =  getid3_lib::FixedPoint2_30(substr($atom_data, 60, 4));
1285
				$atom_structure['matrix_x']            = getid3_lib::FixedPoint16_16(substr($atom_data, 64, 4));
1286
				$atom_structure['matrix_y']            = getid3_lib::FixedPoint16_16(substr($atom_data, 68, 4));
1287
				$atom_structure['matrix_w']            =  getid3_lib::FixedPoint2_30(substr($atom_data, 72, 4));
1288
				$atom_structure['width']               = getid3_lib::FixedPoint16_16(substr($atom_data, 76, 4));
1289
				$atom_structure['height']              = getid3_lib::FixedPoint16_16(substr($atom_data, 80, 4));
1290
				$atom_structure['flags']['enabled']    = (bool) ($atom_structure['flags_raw'] & 0x0001);
1291
				$atom_structure['flags']['in_movie']   = (bool) ($atom_structure['flags_raw'] & 0x0002);
1292
				$atom_structure['flags']['in_preview'] = (bool) ($atom_structure['flags_raw'] & 0x0004);
1293
				$atom_structure['flags']['in_poster']  = (bool) ($atom_structure['flags_raw'] & 0x0008);
1294
				$atom_structure['creation_time_unix']  = getid3_lib::DateMac2Unix($atom_structure['creation_time']);
1295
				$atom_structure['modify_time_unix']    = getid3_lib::DateMac2Unix($atom_structure['modify_time']);
1296
1297
				if ($atom_structure['flags']['enabled'] == 1) {
1298
					if (!isset($info['video']['resolution_x']) || !isset($info['video']['resolution_y'])) {
1299
						$info['video']['resolution_x'] = $atom_structure['width'];
1300
						$info['video']['resolution_y'] = $atom_structure['height'];
1301
					}
1302
					$info['video']['resolution_x'] = max($info['video']['resolution_x'], $atom_structure['width']);
1303
					$info['video']['resolution_y'] = max($info['video']['resolution_y'], $atom_structure['height']);
1304
					$info['quicktime']['video']['resolution_x'] = $info['video']['resolution_x'];
1305
					$info['quicktime']['video']['resolution_y'] = $info['video']['resolution_y'];
1306
				} else {
1307
					// see: http://www.getid3.org/phpBB3/viewtopic.php?t=1295
1308
					//if (isset($info['video']['resolution_x'])) { unset($info['video']['resolution_x']); }
1309
					//if (isset($info['video']['resolution_y'])) { unset($info['video']['resolution_y']); }
1310
					//if (isset($info['quicktime']['video']))    { unset($info['quicktime']['video']);    }
1311
				}
1312
				break;
1313
1314
1315
			case 'iods': // Initial Object DeScriptor atom
1316
				// http://www.koders.com/c/fid1FAB3E762903DC482D8A246D4A4BF9F28E049594.aspx?s=windows.h
1317
				// http://libquicktime.sourcearchive.com/documentation/1.0.2plus-pdebian/iods_8c-source.html
1318
				$offset = 0;
1319
				$atom_structure['version']                =       getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1));
1320
				$offset += 1;
1321
				$atom_structure['flags_raw']              =       getid3_lib::BigEndian2Int(substr($atom_data, $offset, 3));
1322
				$offset += 3;
1323
				$atom_structure['mp4_iod_tag']            =       getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1));
1324
				$offset += 1;
1325
				$atom_structure['length']                 = $this->quicktime_read_mp4_descr_length($atom_data, $offset);
1326
				//$offset already adjusted by quicktime_read_mp4_descr_length()
1327
				$atom_structure['object_descriptor_id']   =       getid3_lib::BigEndian2Int(substr($atom_data, $offset, 2));
1328
				$offset += 2;
1329
				$atom_structure['od_profile_level']       =       getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1));
1330
				$offset += 1;
1331
				$atom_structure['scene_profile_level']    =       getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1));
1332
				$offset += 1;
1333
				$atom_structure['audio_profile_id']       =       getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1));
1334
				$offset += 1;
1335
				$atom_structure['video_profile_id']       =       getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1));
1336
				$offset += 1;
1337
				$atom_structure['graphics_profile_level'] =       getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1));
1338
				$offset += 1;
1339
1340
				$atom_structure['num_iods_tracks'] = ($atom_structure['length'] - 7) / 6; // 6 bytes would only be right if all tracks use 1-byte length fields
1341 View Code Duplication
				for ($i = 0; $i < $atom_structure['num_iods_tracks']; $i++) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1342
					$atom_structure['track'][$i]['ES_ID_IncTag'] =       getid3_lib::BigEndian2Int(substr($atom_data, $offset, 1));
1343
					$offset += 1;
1344
					$atom_structure['track'][$i]['length']       = $this->quicktime_read_mp4_descr_length($atom_data, $offset);
1345
					//$offset already adjusted by quicktime_read_mp4_descr_length()
1346
					$atom_structure['track'][$i]['track_id']     =       getid3_lib::BigEndian2Int(substr($atom_data, $offset, 4));
1347
					$offset += 4;
1348
				}
1349
1350
				$atom_structure['audio_profile_name'] = $this->QuicktimeIODSaudioProfileName($atom_structure['audio_profile_id']);
1351
				$atom_structure['video_profile_name'] = $this->QuicktimeIODSvideoProfileName($atom_structure['video_profile_id']);
1352
				break;
1353
1354 View Code Duplication
			case 'ftyp': // FileTYPe (?) atom (for MP4 it seems)
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1355
				$atom_structure['signature'] =                           substr($atom_data,  0, 4);
1356
				$atom_structure['unknown_1'] = getid3_lib::BigEndian2Int(substr($atom_data,  4, 4));
1357
				$atom_structure['fourcc']    =                           substr($atom_data,  8, 4);
1358
				break;
1359
1360
			case 'mdat': // Media DATa atom
1361
				// 'mdat' contains the actual data for the audio/video, possibly also subtitles
1362
1363
/* 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 [email protected] */
1364
1365
				// first, skip any 'wide' padding, and second 'mdat' header (with specified size of zero?)
1366
				$mdat_offset = 0;
1367
				while (true) {
1368
					if (substr($atom_data, $mdat_offset, 8) == "\x00\x00\x00\x08".'wide') {
1369
						$mdat_offset += 8;
1370
					} elseif (substr($atom_data, $mdat_offset, 8) == "\x00\x00\x00\x00".'mdat') {
1371
						$mdat_offset += 8;
1372
					} else {
1373
						break;
1374
					}
1375
				}
1376
1377
				// check to see if it looks like chapter titles, in the form of unterminated strings with a leading 16-bit size field
1378
				while (($mdat_offset < (strlen($atom_data) - 8))
1379
					&& ($chapter_string_length = getid3_lib::BigEndian2Int(substr($atom_data, $mdat_offset, 2)))
1380
					&& ($chapter_string_length < 1000)
1381
					&& ($chapter_string_length <= (strlen($atom_data) - $mdat_offset - 2))
1382
					&& preg_match('#^([\x00-\xFF]{2})([\x20-\xFF]+)$#', substr($atom_data, $mdat_offset, $chapter_string_length + 2), $chapter_matches)) {
1383
						list($dummy, $chapter_string_length_hex, $chapter_string) = $chapter_matches;
0 ignored issues
show
Unused Code introduced by
The assignment to $dummy is unused. Consider omitting it like so list($first,,$third).

This checks looks for assignemnts to variables using the list(...) function, where not all assigned variables are subsequently used.

Consider the following code example.

<?php

function returnThreeValues() {
    return array('a', 'b', 'c');
}

list($a, $b, $c) = returnThreeValues();

print $a . " - " . $c;

Only the variables $a and $c are used. There was no need to assign $b.

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
Unused Code introduced by
The assignment to $chapter_string_length_hex is unused. Consider omitting it like so list($first,,$third).

This checks looks for assignemnts to variables using the list(...) function, where not all assigned variables are subsequently used.

Consider the following code example.

<?php

function returnThreeValues() {
    return array('a', 'b', 'c');
}

list($a, $b, $c) = returnThreeValues();

print $a . " - " . $c;

Only the variables $a and $c are used. There was no need to assign $b.

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
1384
						$mdat_offset += (2 + $chapter_string_length);
1385
						@$info['quicktime']['comments']['chapters'][] = $chapter_string;
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
1386
1387
						// "encd" atom specifies encoding. In theory could be anything, almost always UTF-8, but may be UTF-16 with BOM (not currently handled)
1388
						if (substr($atom_data, $mdat_offset, 12) == "\x00\x00\x00\x0C\x65\x6E\x63\x64\x00\x00\x01\x00") { // UTF-8
1389
							$mdat_offset += 12;
1390
						}
1391
				}
1392
1393
1394
				if (($atomsize > 8) && (!isset($info['avdataend_tmp']) || ($info['quicktime'][$atomname]['size'] > ($info['avdataend_tmp'] - $info['avdataoffset'])))) {
1395
1396
					$info['avdataoffset'] = $atom_structure['offset'] + 8;                       // $info['quicktime'][$atomname]['offset'] + 8;
1397
					$OldAVDataEnd         = $info['avdataend'];
1398
					$info['avdataend']    = $atom_structure['offset'] + $atom_structure['size']; // $info['quicktime'][$atomname]['offset'] + $info['quicktime'][$atomname]['size'];
1399
1400
					$getid3_temp = new getID3();
1401
					$getid3_temp->openfile($this->getid3->filename);
1402
					$getid3_temp->info['avdataoffset'] = $info['avdataoffset'];
1403
					$getid3_temp->info['avdataend']    = $info['avdataend'];
1404
					$getid3_mp3 = new getid3_mp3($getid3_temp);
1405
					if ($getid3_mp3->MPEGaudioHeaderValid($getid3_mp3->MPEGaudioHeaderDecode($this->fread(4)))) {
1406
						$getid3_mp3->getOnlyMPEGaudioInfo($getid3_temp->info['avdataoffset'], false);
1407
						if (!empty($getid3_temp->info['warning'])) {
1408
							foreach ($getid3_temp->info['warning'] as $value) {
1409
								$this->warning($value);
1410
							}
1411
						}
1412
						if (!empty($getid3_temp->info['mpeg'])) {
1413
							$info['mpeg'] = $getid3_temp->info['mpeg'];
1414
							if (isset($info['mpeg']['audio'])) {
1415
								$info['audio']['dataformat']   = 'mp3';
1416
								$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')));
1417
								$info['audio']['sample_rate']  = $info['mpeg']['audio']['sample_rate'];
1418
								$info['audio']['channels']     = $info['mpeg']['audio']['channels'];
1419
								$info['audio']['bitrate']      = $info['mpeg']['audio']['bitrate'];
1420
								$info['audio']['bitrate_mode'] = strtolower($info['mpeg']['audio']['bitrate_mode']);
1421
								$info['bitrate']               = $info['audio']['bitrate'];
1422
							}
1423
						}
1424
					}
1425
					unset($getid3_mp3, $getid3_temp);
1426
					$info['avdataend'] = $OldAVDataEnd;
1427
					unset($OldAVDataEnd);
1428
1429
				}
1430
1431
				unset($mdat_offset, $chapter_string_length, $chapter_matches);
1432
				break;
1433
1434
			case 'free': // FREE space atom
1435
			case 'skip': // SKIP atom
1436
			case 'wide': // 64-bit expansion placeholder atom
1437
				// 'free', 'skip' and 'wide' are just padding, contains no useful data at all
1438
1439
				// When writing QuickTime files, it is sometimes necessary to update an atom's size.
1440
				// It is impossible to update a 32-bit atom to a 64-bit atom since the 32-bit atom
1441
				// is only 8 bytes in size, and the 64-bit atom requires 16 bytes. Therefore, QuickTime
1442
				// puts an 8-byte placeholder atom before any atoms it may have to update the size of.
1443
				// In this way, if the atom needs to be converted from a 32-bit to a 64-bit atom, the
1444
				// placeholder atom can be overwritten to obtain the necessary 8 extra bytes.
1445
				// The placeholder atom has a type of kWideAtomPlaceholderType ( 'wide' ).
1446
				break;
1447
1448
1449
			case 'nsav': // NoSAVe atom
1450
				// http://developer.apple.com/technotes/tn/tn2038.html
1451
				$atom_structure['data'] = getid3_lib::BigEndian2Int(substr($atom_data,  0, 4));
1452
				break;
1453
1454
			case 'ctyp': // Controller TYPe atom (seen on QTVR)
1455
				// http://homepages.slingshot.co.nz/~helmboy/quicktime/formats/qtm-layout.txt
1456
				// some controller names are:
1457
				//   0x00 + 'std' for linear movie
1458
				//   'none' for no controls
1459
				$atom_structure['ctyp'] = substr($atom_data, 0, 4);
1460
				$info['quicktime']['controller'] = $atom_structure['ctyp'];
1461
				switch ($atom_structure['ctyp']) {
1462
					case 'qtvr':
1463
						$info['video']['dataformat'] = 'quicktimevr';
1464
						break;
1465
				}
1466
				break;
1467
1468
			case 'pano': // PANOrama track (seen on QTVR)
1469
				$atom_structure['pano'] = getid3_lib::BigEndian2Int(substr($atom_data,  0, 4));
1470
				break;
1471
1472
			case 'hint': // HINT track
1473
			case 'hinf': //
1474
			case 'hinv': //
1475
			case 'hnti': //
1476
				$info['quicktime']['hinting'] = true;
1477
				break;
1478
1479
			case 'imgt': // IMaGe Track reference (kQTVRImageTrackRefType) (seen on QTVR)
1480
				for ($i = 0; $i < ($atom_structure['size'] - 8); $i += 4) {
1481
					$atom_structure['imgt'][] = getid3_lib::BigEndian2Int(substr($atom_data, $i, 4));
1482
				}
1483
				break;
1484
1485
1486
			// Observed-but-not-handled atom types are just listed here to prevent warnings being generated
1487
			case 'FXTC': // Something to do with Adobe After Effects (?)
1488
			case 'PrmA':
1489
			case 'code':
1490
			case 'FIEL': // this is NOT "fiel" (Field Ordering) as describe here: http://developer.apple.com/documentation/QuickTime/QTFF/QTFFChap3/chapter_4_section_2.html
1491
			case 'tapt': // TrackApertureModeDimensionsAID - http://developer.apple.com/documentation/QuickTime/Reference/QT7-1_Update_Reference/Constants/Constants.html
1492
						// tapt seems to be used to compute the video size [http://www.getid3.org/phpBB3/viewtopic.php?t=838]
1493
						// * http://lists.apple.com/archives/quicktime-api/2006/Aug/msg00014.html
1494
						// * http://handbrake.fr/irclogs/handbrake-dev/handbrake-dev20080128_pg2.html
1495
			case 'ctts'://  STCompositionOffsetAID             - http://developer.apple.com/documentation/QuickTime/Reference/QTRef_Constants/Reference/reference.html
1496
			case 'cslg'://  STCompositionShiftLeastGreatestAID - http://developer.apple.com/documentation/QuickTime/Reference/QTRef_Constants/Reference/reference.html
1497
			case 'sdtp'://  STSampleDependencyAID              - http://developer.apple.com/documentation/QuickTime/Reference/QTRef_Constants/Reference/reference.html
1498
			case 'stps'://  STPartialSyncSampleAID             - http://developer.apple.com/documentation/QuickTime/Reference/QTRef_Constants/Reference/reference.html
1499
				//$atom_structure['data'] = $atom_data;
1500
				break;
1501
1502
			case "\xA9".'xyz':  // GPS latitude+longitude+altitude
1503
				$atom_structure['data'] = $atom_data;
1504
				if (preg_match('#([\\+\\-][0-9\\.]+)([\\+\\-][0-9\\.]+)([\\+\\-][0-9\\.]+)?/$#i', $atom_data, $matches)) {
1505
					@list($all, $latitude, $longitude, $altitude) = $matches;
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
1506
					$info['quicktime']['comments']['gps_latitude'][]  = floatval($latitude);
1507
					$info['quicktime']['comments']['gps_longitude'][] = floatval($longitude);
1508
					if (!empty($altitude)) {
1509
						$info['quicktime']['comments']['gps_altitude'][] = floatval($altitude);
1510
					}
1511
				} else {
1512
					$this->warning('QuickTime atom "©xyz" data does not match expected data pattern at offset '.$baseoffset.'. Please report as getID3() bug.');
1513
				}
1514
				break;
1515
1516
			case 'NCDT':
1517
				// http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html
1518
				// Nikon-specific QuickTime tags found in the NCDT atom of MOV videos from some Nikon cameras such as the Coolpix S8000 and D5100
1519
				$atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 4, $atomHierarchy, $ParseAllPossibleAtoms);
1520
				break;
1521
			case 'NCTH': // Nikon Camera THumbnail image
1522
			case 'NCVW': // Nikon Camera preVieW image
1523
				// http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html
1524
				if (preg_match('/^\xFF\xD8\xFF/', $atom_data)) {
1525
					$atom_structure['data'] = $atom_data;
1526
					$atom_structure['image_mime'] = 'image/jpeg';
1527
					$atom_structure['description'] = (($atomname == 'NCTH') ? 'Nikon Camera Thumbnail Image' : (($atomname == 'NCVW') ? 'Nikon Camera Preview Image' : 'Nikon preview image'));
1528
					$info['quicktime']['comments']['picture'][] = array('image_mime'=>$atom_structure['image_mime'], 'data'=>$atom_data, 'description'=>$atom_structure['description']);
1529
				}
1530
				break;
1531
			case 'NCTG': // Nikon - http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html#NCTG
1532
				$atom_structure['data'] = $this->QuicktimeParseNikonNCTG($atom_data);
1533
				break;
1534
			case 'NCHD': // Nikon:MakerNoteVersion  - http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html
1535
			case 'NCDB': // Nikon                   - http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html
1536
			case 'CNCV': // Canon:CompressorVersion - http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Canon.html
1537
				$atom_structure['data'] = $atom_data;
1538
				break;
1539
1540 View Code Duplication
			case "\x00\x00\x00\x00":
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1541
				// some kind of metacontainer, may contain a big data dump such as:
1542
				// mdta keys \005 mdtacom.apple.quicktime.make (mdtacom.apple.quicktime.creationdate ,mdtacom.apple.quicktime.location.ISO6709 $mdtacom.apple.quicktime.software !mdtacom.apple.quicktime.model ilst \01D \001 \015data \001DE\010Apple 0 \002 (data \001DE\0102011-05-11T17:54:04+0200 2 \003 *data \001DE\010+52.4936+013.3897+040.247/ \01D \004 \015data \001DE\0104.3.1 \005 \018data \001DE\010iPhone 4
1543
				// http://www.geocities.com/xhelmboyx/quicktime/formats/qti-layout.txt
1544
1545
				$atom_structure['version']   =          getid3_lib::BigEndian2Int(substr($atom_data, 0, 1));
1546
				$atom_structure['flags_raw'] =          getid3_lib::BigEndian2Int(substr($atom_data, 1, 3));
1547
				$atom_structure['subatoms']  = $this->QuicktimeParseContainerAtom(substr($atom_data, 4), $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms);
1548
				//$atom_structure['subatoms']  = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms);
1549
				break;
1550
1551 View Code Duplication
			case 'meta': // METAdata atom
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1552
				// https://developer.apple.com/library/mac/documentation/QuickTime/QTFF/Metadata/Metadata.html
1553
1554
				$atom_structure['version']   =          getid3_lib::BigEndian2Int(substr($atom_data, 0, 1));
1555
				$atom_structure['flags_raw'] =          getid3_lib::BigEndian2Int(substr($atom_data, 1, 3));
1556
				$atom_structure['subatoms']  = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms);
1557
				break;
1558
1559
			case 'data': // metaDATA atom
1560
				static $metaDATAkey = 1; // real ugly, but so is the QuickTime structure that stores keys and values in different multinested locations that are hard to relate to each other
1561
				// seems to be 2 bytes language code (ASCII), 2 bytes unknown (set to 0x10B5 in sample I have), remainder is useful data
1562
				$atom_structure['language'] =                           substr($atom_data, 4 + 0, 2);
1563
				$atom_structure['unknown']  = getid3_lib::BigEndian2Int(substr($atom_data, 4 + 2, 2));
1564
				$atom_structure['data']     =                           substr($atom_data, 4 + 4);
1565
				$atom_structure['key_name'] = @$info['quicktime']['temp_meta_key_names'][$metaDATAkey++];
1566
1567
				if ($atom_structure['key_name'] && $atom_structure['data']) {
1568
					@$info['quicktime']['comments'][str_replace('com.apple.quicktime.', '', $atom_structure['key_name'])][] = $atom_structure['data'];
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
1569
				}
1570
				break;
1571
1572
			case 'keys': // KEYS that may be present in the metadata atom.
1573
				// https://developer.apple.com/library/mac/documentation/QuickTime/QTFF/Metadata/Metadata.html#//apple_ref/doc/uid/TP40000939-CH1-SW21
1574
				// The metadata item keys atom holds a list of the metadata keys that may be present in the metadata atom.
1575
				// This list is indexed starting with 1; 0 is a reserved index value. The metadata item keys atom is a full atom with an atom type of "keys".
1576
				$atom_structure['version']       = getid3_lib::BigEndian2Int(substr($atom_data,  0, 1));
1577
				$atom_structure['flags_raw']     = getid3_lib::BigEndian2Int(substr($atom_data,  1, 3));
1578
				$atom_structure['entry_count']   = getid3_lib::BigEndian2Int(substr($atom_data,  4, 4));
1579
				$keys_atom_offset = 8;
1580
				for ($i = 1; $i <= $atom_structure['entry_count']; $i++) {
1581
					$atom_structure['keys'][$i]['key_size']      = getid3_lib::BigEndian2Int(substr($atom_data, $keys_atom_offset + 0, 4));
1582
					$atom_structure['keys'][$i]['key_namespace'] =                           substr($atom_data, $keys_atom_offset + 4, 4);
1583
					$atom_structure['keys'][$i]['key_value']     =                           substr($atom_data, $keys_atom_offset + 8, $atom_structure['keys'][$i]['key_size'] - 8);
1584
					$keys_atom_offset += $atom_structure['keys'][$i]['key_size']; // key_size includes the 4+4 bytes for key_size and key_namespace
1585
1586
					$info['quicktime']['temp_meta_key_names'][$i] = $atom_structure['keys'][$i]['key_value'];
1587
				}
1588
				break;
1589
1590
			case 'gps ':
1591
				// https://dashcamtalk.com/forum/threads/script-to-extract-gps-data-from-novatek-mp4.20808/page-2#post-291730
1592
				// The 'gps ' contains simple look up table made up of 8byte rows, that point to the 'free' atoms that contains the actual GPS data.
1593
				// The first row is version/metadata/notsure, I skip that.
1594
				// The following rows consist of 4byte address (absolute) and 4byte size (0x1000), these point to the GPS data in the file.
1595
1596
				$GPS_rowsize = 8; // 4 bytes for offset, 4 bytes for size
1597
				if (strlen($atom_data) > 0) {
1598
					if ((strlen($atom_data) % $GPS_rowsize) == 0) {
1599
						$atom_structure['gps_toc'] = array();
1600
						foreach (str_split($atom_data, $GPS_rowsize) as $counter => $datapair) {
1601
							$atom_structure['gps_toc'][] = unpack('Noffset/Nsize', substr($atom_data, $counter * $GPS_rowsize, $GPS_rowsize));
1602
						}
1603
1604
						$atom_structure['gps_entries'] = array();
1605
						$previous_offset = $this->ftell();
1606
						foreach ($atom_structure['gps_toc'] as $key => $gps_pointer) {
1607
							if ($key == 0) {
1608
								// "The first row is version/metadata/notsure, I skip that."
1609
								continue;
1610
							}
1611
							$this->fseek($gps_pointer['offset']);
1612
							$GPS_free_data = $this->fread($gps_pointer['size']);
1613
1614
							/*
1615
							// 2017-05-10: I see some of the data, notably the Hour-Minute-Second, but cannot reconcile the rest of the data. However, the NMEA "GPRMC" line is there and relatively easy to parse, so I'm using that instead
1616
1617
							// https://dashcamtalk.com/forum/threads/script-to-extract-gps-data-from-novatek-mp4.20808/page-2#post-291730
1618
							// The structure of the GPS data atom (the 'free' atoms mentioned above) is following:
1619
							// hour,minute,second,year,month,day,active,latitude_b,longitude_b,unknown2,latitude,longitude,speed = struct.unpack_from('<IIIIIIssssfff',data, 48)
1620
							// For those unfamiliar with python struct:
1621
							// I = int
1622
							// s = is string (size 1, in this case)
1623
							// f = float
1624
1625
							//$atom_structure['gps_entries'][$key] = unpack('Vhour/Vminute/Vsecond/Vyear/Vmonth/Vday/Vactive/Vlatitude_b/Vlongitude_b/Vunknown2/flatitude/flongitude/fspeed', substr($GPS_free_data, 48));
1626
							*/
1627
1628
							// $GPRMC,081836,A,3751.65,S,14507.36,E,000.0,360.0,130998,011.3,E*62
1629
							// $GPRMC,183731,A,3907.482,N,12102.436,W,000.0,360.0,080301,015.5,E*67
1630
							// $GPRMC,002454,A,3553.5295,N,13938.6570,E,0.0,43.1,180700,7.1,W,A*3F
1631
							// $GPRMC,094347.000,A,5342.0061,N,00737.9908,W,0.01,156.75,140217,,,A*7D
1632
							if (preg_match('#\\$GPRMC,([0-9\\.]*),([AV]),([0-9\\.]*),([NS]),([0-9\\.]*),([EW]),([0-9\\.]*),([0-9\\.]*),([0-9]*),([0-9\\.]*),([EW]?)(,[A])?(\\*[0-9A-F]{2})#', $GPS_free_data, $matches)) {
1633
								$GPS_this_GPRMC = array();
1634
								list(
1635
									$GPS_this_GPRMC['raw']['gprmc'],
1636
									$GPS_this_GPRMC['raw']['timestamp'],
1637
									$GPS_this_GPRMC['raw']['status'],
1638
									$GPS_this_GPRMC['raw']['latitude'],
1639
									$GPS_this_GPRMC['raw']['latitude_direction'],
1640
									$GPS_this_GPRMC['raw']['longitude'],
1641
									$GPS_this_GPRMC['raw']['longitude_direction'],
1642
									$GPS_this_GPRMC['raw']['knots'],
1643
									$GPS_this_GPRMC['raw']['angle'],
1644
									$GPS_this_GPRMC['raw']['datestamp'],
1645
									$GPS_this_GPRMC['raw']['variation'],
1646
									$GPS_this_GPRMC['raw']['variation_direction'],
1647
									$dummy,
0 ignored issues
show
Unused Code introduced by
The assignment to $dummy is unused. Consider omitting it like so list($first,,$third).

This checks looks for assignemnts to variables using the list(...) function, where not all assigned variables are subsequently used.

Consider the following code example.

<?php

function returnThreeValues() {
    return array('a', 'b', 'c');
}

list($a, $b, $c) = returnThreeValues();

print $a . " - " . $c;

Only the variables $a and $c are used. There was no need to assign $b.

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
1648
									$GPS_this_GPRMC['raw']['checksum'],
1649
								) = $matches;
1650
1651
								$hour   = substr($GPS_this_GPRMC['raw']['timestamp'], 0, 2);
1652
								$minute = substr($GPS_this_GPRMC['raw']['timestamp'], 2, 2);
1653
								$second = substr($GPS_this_GPRMC['raw']['timestamp'], 4, 2);
1654
								$ms     = substr($GPS_this_GPRMC['raw']['timestamp'], 6);    // may contain decimal seconds
1655
								$day   = substr($GPS_this_GPRMC['raw']['datestamp'], 0, 2);
1656
								$month = substr($GPS_this_GPRMC['raw']['datestamp'], 2, 2);
1657
								$year  = substr($GPS_this_GPRMC['raw']['datestamp'], 4, 2);
1658
								$year += (($year > 90) ? 1900 : 2000); // complete lack of foresight: datestamps are stored with 2-digit years, take best guess
1659
								$GPS_this_GPRMC['timestamp'] = $year.'-'.$month.'-'.$day.' '.$hour.':'.$minute.':'.$second.$ms;
1660
1661
								$GPS_this_GPRMC['active'] = ($GPS_this_GPRMC['raw']['status'] == 'A'); // A=Active,V=Void
1662
1663
								foreach (array('latitude','longitude') as $latlon) {
1664
									preg_match('#^([0-9]{1,3})([0-9]{2}\\.[0-9]+)$#', $GPS_this_GPRMC['raw'][$latlon], $matches);
1665
									list($dummy, $deg, $min) = $matches;
0 ignored issues
show
Unused Code introduced by
The assignment to $dummy is unused. Consider omitting it like so list($first,,$third).

This checks looks for assignemnts to variables using the list(...) function, where not all assigned variables are subsequently used.

Consider the following code example.

<?php

function returnThreeValues() {
    return array('a', 'b', 'c');
}

list($a, $b, $c) = returnThreeValues();

print $a . " - " . $c;

Only the variables $a and $c are used. There was no need to assign $b.

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
1666
									$GPS_this_GPRMC[$latlon] = $deg + ($min / 60);
1667
								}
1668
								$GPS_this_GPRMC['latitude']  *= (($GPS_this_GPRMC['raw']['latitude_direction']  == 'S') ? -1 : 1);
1669
								$GPS_this_GPRMC['longitude'] *= (($GPS_this_GPRMC['raw']['longitude_direction'] == 'W') ? -1 : 1);
1670
1671
								$GPS_this_GPRMC['heading']    = $GPS_this_GPRMC['raw']['angle'];
1672
								$GPS_this_GPRMC['speed_knot'] = $GPS_this_GPRMC['raw']['knots'];
1673
								$GPS_this_GPRMC['speed_kmh']  = $GPS_this_GPRMC['raw']['knots'] * 1.852;
1674
								if ($GPS_this_GPRMC['raw']['variation']) {
1675
									$GPS_this_GPRMC['variation']  = $GPS_this_GPRMC['raw']['variation'];
1676
									$GPS_this_GPRMC['variation'] *= (($GPS_this_GPRMC['raw']['variation_direction'] == 'W') ? -1 : 1);
1677
								}
1678
1679
								$atom_structure['gps_entries'][$key] = $GPS_this_GPRMC;
1680
1681
								@$info['quicktime']['gps_track'][$GPS_this_GPRMC['timestamp']] = array(
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
1682
									'latitude'  => $GPS_this_GPRMC['latitude'],
1683
									'longitude' => $GPS_this_GPRMC['longitude'],
1684
									'speed_kmh' => $GPS_this_GPRMC['speed_kmh'],
1685
									'heading'   => $GPS_this_GPRMC['heading'],
1686
								);
1687
1688
							} else {
1689
								$this->warning('Unhandled GPS format in "free" atom at offset '.$gps_pointer['offset']);
1690
							}
1691
						}
1692
						$this->fseek($previous_offset);
1693
1694
					} else {
1695
						$this->warning('QuickTime atom "'.$atomname.'" is not mod-8 bytes long ('.$atomsize.' bytes) at offset '.$baseoffset);
1696
					}
1697
				} else {
1698
					$this->warning('QuickTime atom "'.$atomname.'" is zero bytes long at offset '.$baseoffset);
1699
				}
1700
				break;
1701
1702
			case 'loci':// 3GP location (El Loco)
1703
				$loffset = 0;
1704
				$info['quicktime']['comments']['gps_flags']     =   getid3_lib::BigEndian2Int(substr($atom_data, 0, 4));
1705
				$info['quicktime']['comments']['gps_lang']      =   getid3_lib::BigEndian2Int(substr($atom_data, 4, 2));
1706
				$info['quicktime']['comments']['gps_location']  =           $this->LociString(substr($atom_data, 6), $loffset);
1707
				$loci_data = substr($atom_data, 6 + $loffset);
1708
				$info['quicktime']['comments']['gps_role']      =   getid3_lib::BigEndian2Int(substr($loci_data, 0, 1));
1709
				$info['quicktime']['comments']['gps_longitude'] = getid3_lib::FixedPoint16_16(substr($loci_data, 1, 4));
1710
				$info['quicktime']['comments']['gps_latitude']  = getid3_lib::FixedPoint16_16(substr($loci_data, 5, 4));
1711
				$info['quicktime']['comments']['gps_altitude']  = getid3_lib::FixedPoint16_16(substr($loci_data, 9, 4));
1712
				$info['quicktime']['comments']['gps_body']      =           $this->LociString(substr($loci_data, 13           ), $loffset);
1713
				$info['quicktime']['comments']['gps_notes']     =           $this->LociString(substr($loci_data, 13 + $loffset), $loffset);
1714
				break;
1715
1716
			case 'chpl': // CHaPter List
1717
				// https://www.adobe.com/content/dam/Adobe/en/devnet/flv/pdfs/video_file_format_spec_v10.pdf
1718
				$chpl_version = getid3_lib::BigEndian2Int(substr($atom_data, 4, 1)); // Expected to be 0
0 ignored issues
show
Unused Code introduced by
$chpl_version is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1719
				$chpl_flags   = getid3_lib::BigEndian2Int(substr($atom_data, 5, 3)); // Reserved, set to 0
0 ignored issues
show
Unused Code introduced by
$chpl_flags is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1720
				$chpl_count   = getid3_lib::BigEndian2Int(substr($atom_data, 8, 1));
1721
				$chpl_offset = 9;
1722
				for ($i = 0; $i < $chpl_count; $i++) {
1723
					if (($chpl_offset + 9) >= strlen($atom_data)) {
1724
						$this->warning('QuickTime chapter '.$i.' extends beyond end of "chpl" atom');
1725
						break;
1726
					}
1727
					$info['quicktime']['chapters'][$i]['timestamp'] = getid3_lib::BigEndian2Int(substr($atom_data, $chpl_offset, 8)) / 10000000; // timestamps are stored as 100-nanosecond units
1728
					$chpl_offset += 8;
1729
					$chpl_title_size = getid3_lib::BigEndian2Int(substr($atom_data, $chpl_offset, 1));
1730
					$chpl_offset += 1;
1731
					$info['quicktime']['chapters'][$i]['title']     =                           substr($atom_data, $chpl_offset, $chpl_title_size);
1732
					$chpl_offset += $chpl_title_size;
1733
				}
1734
				break;
1735
1736 View Code Duplication
			default:
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1737
				$this->warning('Unknown QuickTime atom type: "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $atomname).'" ('.trim(getid3_lib::PrintHexBytes($atomname)).') at offset '.$baseoffset);
1738
				$atom_structure['data'] = $atom_data;
1739
				break;
1740
		}
1741
		array_pop($atomHierarchy);
1742
		return $atom_structure;
1743
	}
1744
1745
	public function QuicktimeParseContainerAtom($atom_data, $baseoffset, &$atomHierarchy, $ParseAllPossibleAtoms) {
1746
//echo 'QuicktimeParseContainerAtom('.substr($atom_data, 4, 4).') @ '.$baseoffset.'<br><br>';
1747
		$atom_structure  = false;
1748
		$subatomoffset  = 0;
1749
		$subatomcounter = 0;
1750
		if ((strlen($atom_data) == 4) && (getid3_lib::BigEndian2Int($atom_data) == 0x00000000)) {
1751
			return false;
1752
		}
1753
		while ($subatomoffset < strlen($atom_data)) {
1754
			$subatomsize = getid3_lib::BigEndian2Int(substr($atom_data, $subatomoffset + 0, 4));
1755
			$subatomname =                           substr($atom_data, $subatomoffset + 4, 4);
1756
			$subatomdata =                           substr($atom_data, $subatomoffset + 8, $subatomsize - 8);
1757
			if ($subatomsize == 0) {
1758
				// Furthermore, for historical reasons the list of atoms is optionally
1759
				// terminated by a 32-bit integer set to 0. If you are writing a program
1760
				// to read user data atoms, you should allow for the terminating 0.
1761
				if (strlen($atom_data) > 12) {
1762
					$subatomoffset += 4;
1763
					continue;
1764
				}
1765
				return $atom_structure;
1766
			}
1767
1768
			$atom_structure[$subatomcounter] = $this->QuicktimeParseAtom($subatomname, $subatomsize, $subatomdata, $baseoffset + $subatomoffset, $atomHierarchy, $ParseAllPossibleAtoms);
1769
1770
			$subatomoffset += $subatomsize;
1771
			$subatomcounter++;
1772
		}
1773
		return $atom_structure;
1774
	}
1775
1776
1777
	public function quicktime_read_mp4_descr_length($data, &$offset) {
1778
		// http://libquicktime.sourcearchive.com/documentation/2:1.0.2plus-pdebian-2build1/esds_8c-source.html
1779
		$num_bytes = 0;
1780
		$length    = 0;
1781
		do {
1782
			$b = ord(substr($data, $offset++, 1));
1783
			$length = ($length << 7) | ($b & 0x7F);
1784
		} while (($b & 0x80) && ($num_bytes++ < 4));
1785
		return $length;
1786
	}
1787
1788
1789
	public function QuicktimeLanguageLookup($languageid) {
1790
		// http://developer.apple.com/library/mac/#documentation/QuickTime/QTFF/QTFFChap4/qtff4.html#//apple_ref/doc/uid/TP40000939-CH206-34353
1791
		static $QuicktimeLanguageLookup = array();
1792
		if (empty($QuicktimeLanguageLookup)) {
1793
			$QuicktimeLanguageLookup[0]     = 'English';
1794
			$QuicktimeLanguageLookup[1]     = 'French';
1795
			$QuicktimeLanguageLookup[2]     = 'German';
1796
			$QuicktimeLanguageLookup[3]     = 'Italian';
1797
			$QuicktimeLanguageLookup[4]     = 'Dutch';
1798
			$QuicktimeLanguageLookup[5]     = 'Swedish';
1799
			$QuicktimeLanguageLookup[6]     = 'Spanish';
1800
			$QuicktimeLanguageLookup[7]     = 'Danish';
1801
			$QuicktimeLanguageLookup[8]     = 'Portuguese';
1802
			$QuicktimeLanguageLookup[9]     = 'Norwegian';
1803
			$QuicktimeLanguageLookup[10]    = 'Hebrew';
1804
			$QuicktimeLanguageLookup[11]    = 'Japanese';
1805
			$QuicktimeLanguageLookup[12]    = 'Arabic';
1806
			$QuicktimeLanguageLookup[13]    = 'Finnish';
1807
			$QuicktimeLanguageLookup[14]    = 'Greek';
1808
			$QuicktimeLanguageLookup[15]    = 'Icelandic';
1809
			$QuicktimeLanguageLookup[16]    = 'Maltese';
1810
			$QuicktimeLanguageLookup[17]    = 'Turkish';
1811
			$QuicktimeLanguageLookup[18]    = 'Croatian';
1812
			$QuicktimeLanguageLookup[19]    = 'Chinese (Traditional)';
1813
			$QuicktimeLanguageLookup[20]    = 'Urdu';
1814
			$QuicktimeLanguageLookup[21]    = 'Hindi';
1815
			$QuicktimeLanguageLookup[22]    = 'Thai';
1816
			$QuicktimeLanguageLookup[23]    = 'Korean';
1817
			$QuicktimeLanguageLookup[24]    = 'Lithuanian';
1818
			$QuicktimeLanguageLookup[25]    = 'Polish';
1819
			$QuicktimeLanguageLookup[26]    = 'Hungarian';
1820
			$QuicktimeLanguageLookup[27]    = 'Estonian';
1821
			$QuicktimeLanguageLookup[28]    = 'Lettish';
1822
			$QuicktimeLanguageLookup[28]    = 'Latvian';
1823
			$QuicktimeLanguageLookup[29]    = 'Saamisk';
1824
			$QuicktimeLanguageLookup[29]    = 'Lappish';
1825
			$QuicktimeLanguageLookup[30]    = 'Faeroese';
1826
			$QuicktimeLanguageLookup[31]    = 'Farsi';
1827
			$QuicktimeLanguageLookup[31]    = 'Persian';
1828
			$QuicktimeLanguageLookup[32]    = 'Russian';
1829
			$QuicktimeLanguageLookup[33]    = 'Chinese (Simplified)';
1830
			$QuicktimeLanguageLookup[34]    = 'Flemish';
1831
			$QuicktimeLanguageLookup[35]    = 'Irish';
1832
			$QuicktimeLanguageLookup[36]    = 'Albanian';
1833
			$QuicktimeLanguageLookup[37]    = 'Romanian';
1834
			$QuicktimeLanguageLookup[38]    = 'Czech';
1835
			$QuicktimeLanguageLookup[39]    = 'Slovak';
1836
			$QuicktimeLanguageLookup[40]    = 'Slovenian';
1837
			$QuicktimeLanguageLookup[41]    = 'Yiddish';
1838
			$QuicktimeLanguageLookup[42]    = 'Serbian';
1839
			$QuicktimeLanguageLookup[43]    = 'Macedonian';
1840
			$QuicktimeLanguageLookup[44]    = 'Bulgarian';
1841
			$QuicktimeLanguageLookup[45]    = 'Ukrainian';
1842
			$QuicktimeLanguageLookup[46]    = 'Byelorussian';
1843
			$QuicktimeLanguageLookup[47]    = 'Uzbek';
1844
			$QuicktimeLanguageLookup[48]    = 'Kazakh';
1845
			$QuicktimeLanguageLookup[49]    = 'Azerbaijani';
1846
			$QuicktimeLanguageLookup[50]    = 'AzerbaijanAr';
1847
			$QuicktimeLanguageLookup[51]    = 'Armenian';
1848
			$QuicktimeLanguageLookup[52]    = 'Georgian';
1849
			$QuicktimeLanguageLookup[53]    = 'Moldavian';
1850
			$QuicktimeLanguageLookup[54]    = 'Kirghiz';
1851
			$QuicktimeLanguageLookup[55]    = 'Tajiki';
1852
			$QuicktimeLanguageLookup[56]    = 'Turkmen';
1853
			$QuicktimeLanguageLookup[57]    = 'Mongolian';
1854
			$QuicktimeLanguageLookup[58]    = 'MongolianCyr';
1855
			$QuicktimeLanguageLookup[59]    = 'Pashto';
1856
			$QuicktimeLanguageLookup[60]    = 'Kurdish';
1857
			$QuicktimeLanguageLookup[61]    = 'Kashmiri';
1858
			$QuicktimeLanguageLookup[62]    = 'Sindhi';
1859
			$QuicktimeLanguageLookup[63]    = 'Tibetan';
1860
			$QuicktimeLanguageLookup[64]    = 'Nepali';
1861
			$QuicktimeLanguageLookup[65]    = 'Sanskrit';
1862
			$QuicktimeLanguageLookup[66]    = 'Marathi';
1863
			$QuicktimeLanguageLookup[67]    = 'Bengali';
1864
			$QuicktimeLanguageLookup[68]    = 'Assamese';
1865
			$QuicktimeLanguageLookup[69]    = 'Gujarati';
1866
			$QuicktimeLanguageLookup[70]    = 'Punjabi';
1867
			$QuicktimeLanguageLookup[71]    = 'Oriya';
1868
			$QuicktimeLanguageLookup[72]    = 'Malayalam';
1869
			$QuicktimeLanguageLookup[73]    = 'Kannada';
1870
			$QuicktimeLanguageLookup[74]    = 'Tamil';
1871
			$QuicktimeLanguageLookup[75]    = 'Telugu';
1872
			$QuicktimeLanguageLookup[76]    = 'Sinhalese';
1873
			$QuicktimeLanguageLookup[77]    = 'Burmese';
1874
			$QuicktimeLanguageLookup[78]    = 'Khmer';
1875
			$QuicktimeLanguageLookup[79]    = 'Lao';
1876
			$QuicktimeLanguageLookup[80]    = 'Vietnamese';
1877
			$QuicktimeLanguageLookup[81]    = 'Indonesian';
1878
			$QuicktimeLanguageLookup[82]    = 'Tagalog';
1879
			$QuicktimeLanguageLookup[83]    = 'MalayRoman';
1880
			$QuicktimeLanguageLookup[84]    = 'MalayArabic';
1881
			$QuicktimeLanguageLookup[85]    = 'Amharic';
1882
			$QuicktimeLanguageLookup[86]    = 'Tigrinya';
1883
			$QuicktimeLanguageLookup[87]    = 'Galla';
1884
			$QuicktimeLanguageLookup[87]    = 'Oromo';
1885
			$QuicktimeLanguageLookup[88]    = 'Somali';
1886
			$QuicktimeLanguageLookup[89]    = 'Swahili';
1887
			$QuicktimeLanguageLookup[90]    = 'Ruanda';
1888
			$QuicktimeLanguageLookup[91]    = 'Rundi';
1889
			$QuicktimeLanguageLookup[92]    = 'Chewa';
1890
			$QuicktimeLanguageLookup[93]    = 'Malagasy';
1891
			$QuicktimeLanguageLookup[94]    = 'Esperanto';
1892
			$QuicktimeLanguageLookup[128]   = 'Welsh';
1893
			$QuicktimeLanguageLookup[129]   = 'Basque';
1894
			$QuicktimeLanguageLookup[130]   = 'Catalan';
1895
			$QuicktimeLanguageLookup[131]   = 'Latin';
1896
			$QuicktimeLanguageLookup[132]   = 'Quechua';
1897
			$QuicktimeLanguageLookup[133]   = 'Guarani';
1898
			$QuicktimeLanguageLookup[134]   = 'Aymara';
1899
			$QuicktimeLanguageLookup[135]   = 'Tatar';
1900
			$QuicktimeLanguageLookup[136]   = 'Uighur';
1901
			$QuicktimeLanguageLookup[137]   = 'Dzongkha';
1902
			$QuicktimeLanguageLookup[138]   = 'JavaneseRom';
1903
			$QuicktimeLanguageLookup[32767] = 'Unspecified';
1904
		}
1905
		if (($languageid > 138) && ($languageid < 32767)) {
1906
			/*
1907
			ISO Language Codes - http://www.loc.gov/standards/iso639-2/php/code_list.php
1908
			Because the language codes specified by ISO 639-2/T are three characters long, they must be packed to fit into a 16-bit field.
1909
			The packing algorithm must map each of the three characters, which are always lowercase, into a 5-bit integer and then concatenate
1910
			these integers into the least significant 15 bits of a 16-bit integer, leaving the 16-bit integer's most significant bit set to zero.
1911
1912
			One algorithm for performing this packing is to treat each ISO character as a 16-bit integer. Subtract 0x60 from the first character
1913
			and multiply by 2^10 (0x400), subtract 0x60 from the second character and multiply by 2^5 (0x20), subtract 0x60 from the third character,
1914
			and add the three 16-bit values. This will result in a single 16-bit value with the three codes correctly packed into the 15 least
1915
			significant bits and the most significant bit set to zero.
1916
			*/
1917
			$iso_language_id  = '';
1918
			$iso_language_id .= chr((($languageid & 0x7C00) >> 10) + 0x60);
1919
			$iso_language_id .= chr((($languageid & 0x03E0) >>  5) + 0x60);
1920
			$iso_language_id .= chr((($languageid & 0x001F) >>  0) + 0x60);
1921
			$QuicktimeLanguageLookup[$languageid] = getid3_id3v2::LanguageLookup($iso_language_id);
1922
		}
1923
		return (isset($QuicktimeLanguageLookup[$languageid]) ? $QuicktimeLanguageLookup[$languageid] : 'invalid');
1924
	}
1925
1926
	public function QuicktimeVideoCodecLookup($codecid) {
1927
		static $QuicktimeVideoCodecLookup = array();
1928
		if (empty($QuicktimeVideoCodecLookup)) {
1929
			$QuicktimeVideoCodecLookup['.SGI'] = 'SGI';
1930
			$QuicktimeVideoCodecLookup['3IV1'] = '3ivx MPEG-4 v1';
1931
			$QuicktimeVideoCodecLookup['3IV2'] = '3ivx MPEG-4 v2';
1932
			$QuicktimeVideoCodecLookup['3IVX'] = '3ivx MPEG-4';
1933
			$QuicktimeVideoCodecLookup['8BPS'] = 'Planar RGB';
1934
			$QuicktimeVideoCodecLookup['avc1'] = 'H.264/MPEG-4 AVC';
1935
			$QuicktimeVideoCodecLookup['avr '] = 'AVR-JPEG';
1936
			$QuicktimeVideoCodecLookup['b16g'] = '16Gray';
1937
			$QuicktimeVideoCodecLookup['b32a'] = '32AlphaGray';
1938
			$QuicktimeVideoCodecLookup['b48r'] = '48RGB';
1939
			$QuicktimeVideoCodecLookup['b64a'] = '64ARGB';
1940
			$QuicktimeVideoCodecLookup['base'] = 'Base';
1941
			$QuicktimeVideoCodecLookup['clou'] = 'Cloud';
1942
			$QuicktimeVideoCodecLookup['cmyk'] = 'CMYK';
1943
			$QuicktimeVideoCodecLookup['cvid'] = 'Cinepak';
1944
			$QuicktimeVideoCodecLookup['dmb1'] = 'OpenDML JPEG';
1945
			$QuicktimeVideoCodecLookup['dvc '] = 'DVC-NTSC';
1946
			$QuicktimeVideoCodecLookup['dvcp'] = 'DVC-PAL';
1947
			$QuicktimeVideoCodecLookup['dvpn'] = 'DVCPro-NTSC';
1948
			$QuicktimeVideoCodecLookup['dvpp'] = 'DVCPro-PAL';
1949
			$QuicktimeVideoCodecLookup['fire'] = 'Fire';
1950
			$QuicktimeVideoCodecLookup['flic'] = 'FLC';
1951
			$QuicktimeVideoCodecLookup['gif '] = 'GIF';
1952
			$QuicktimeVideoCodecLookup['h261'] = 'H261';
1953
			$QuicktimeVideoCodecLookup['h263'] = 'H263';
1954
			$QuicktimeVideoCodecLookup['IV41'] = 'Indeo4';
1955
			$QuicktimeVideoCodecLookup['jpeg'] = 'JPEG';
1956
			$QuicktimeVideoCodecLookup['kpcd'] = 'PhotoCD';
1957
			$QuicktimeVideoCodecLookup['mjpa'] = 'Motion JPEG-A';
1958
			$QuicktimeVideoCodecLookup['mjpb'] = 'Motion JPEG-B';
1959
			$QuicktimeVideoCodecLookup['msvc'] = 'Microsoft Video1';
1960
			$QuicktimeVideoCodecLookup['myuv'] = 'MPEG YUV420';
1961
			$QuicktimeVideoCodecLookup['path'] = 'Vector';
1962
			$QuicktimeVideoCodecLookup['png '] = 'PNG';
1963
			$QuicktimeVideoCodecLookup['PNTG'] = 'MacPaint';
1964
			$QuicktimeVideoCodecLookup['qdgx'] = 'QuickDrawGX';
1965
			$QuicktimeVideoCodecLookup['qdrw'] = 'QuickDraw';
1966
			$QuicktimeVideoCodecLookup['raw '] = 'RAW';
1967
			$QuicktimeVideoCodecLookup['ripl'] = 'WaterRipple';
1968
			$QuicktimeVideoCodecLookup['rpza'] = 'Video';
1969
			$QuicktimeVideoCodecLookup['smc '] = 'Graphics';
1970
			$QuicktimeVideoCodecLookup['SVQ1'] = 'Sorenson Video 1';
1971
			$QuicktimeVideoCodecLookup['SVQ1'] = 'Sorenson Video 3';
1972
			$QuicktimeVideoCodecLookup['syv9'] = 'Sorenson YUV9';
1973
			$QuicktimeVideoCodecLookup['tga '] = 'Targa';
1974
			$QuicktimeVideoCodecLookup['tiff'] = 'TIFF';
1975
			$QuicktimeVideoCodecLookup['WRAW'] = 'Windows RAW';
1976
			$QuicktimeVideoCodecLookup['WRLE'] = 'BMP';
1977
			$QuicktimeVideoCodecLookup['y420'] = 'YUV420';
1978
			$QuicktimeVideoCodecLookup['yuv2'] = 'ComponentVideo';
1979
			$QuicktimeVideoCodecLookup['yuvs'] = 'ComponentVideoUnsigned';
1980
			$QuicktimeVideoCodecLookup['yuvu'] = 'ComponentVideoSigned';
1981
		}
1982
		return (isset($QuicktimeVideoCodecLookup[$codecid]) ? $QuicktimeVideoCodecLookup[$codecid] : '');
1983
	}
1984
1985
	public function QuicktimeAudioCodecLookup($codecid) {
1986
		static $QuicktimeAudioCodecLookup = array();
1987
		if (empty($QuicktimeAudioCodecLookup)) {
1988
			$QuicktimeAudioCodecLookup['.mp3']          = 'Fraunhofer MPEG Layer-III alias';
1989
			$QuicktimeAudioCodecLookup['aac ']          = 'ISO/IEC 14496-3 AAC';
1990
			$QuicktimeAudioCodecLookup['agsm']          = 'Apple GSM 10:1';
1991
			$QuicktimeAudioCodecLookup['alac']          = 'Apple Lossless Audio Codec';
1992
			$QuicktimeAudioCodecLookup['alaw']          = 'A-law 2:1';
1993
			$QuicktimeAudioCodecLookup['conv']          = 'Sample Format';
1994
			$QuicktimeAudioCodecLookup['dvca']          = 'DV';
1995
			$QuicktimeAudioCodecLookup['dvi ']          = 'DV 4:1';
1996
			$QuicktimeAudioCodecLookup['eqal']          = 'Frequency Equalizer';
1997
			$QuicktimeAudioCodecLookup['fl32']          = '32-bit Floating Point';
1998
			$QuicktimeAudioCodecLookup['fl64']          = '64-bit Floating Point';
1999
			$QuicktimeAudioCodecLookup['ima4']          = 'Interactive Multimedia Association 4:1';
2000
			$QuicktimeAudioCodecLookup['in24']          = '24-bit Integer';
2001
			$QuicktimeAudioCodecLookup['in32']          = '32-bit Integer';
2002
			$QuicktimeAudioCodecLookup['lpc ']          = 'LPC 23:1';
2003
			$QuicktimeAudioCodecLookup['MAC3']          = 'Macintosh Audio Compression/Expansion (MACE) 3:1';
2004
			$QuicktimeAudioCodecLookup['MAC6']          = 'Macintosh Audio Compression/Expansion (MACE) 6:1';
2005
			$QuicktimeAudioCodecLookup['mixb']          = '8-bit Mixer';
2006
			$QuicktimeAudioCodecLookup['mixw']          = '16-bit Mixer';
2007
			$QuicktimeAudioCodecLookup['mp4a']          = 'ISO/IEC 14496-3 AAC';
2008
			$QuicktimeAudioCodecLookup['MS'."\x00\x02"] = 'Microsoft ADPCM';
2009
			$QuicktimeAudioCodecLookup['MS'."\x00\x11"] = 'DV IMA';
2010
			$QuicktimeAudioCodecLookup['MS'."\x00\x55"] = 'Fraunhofer MPEG Layer III';
2011
			$QuicktimeAudioCodecLookup['NONE']          = 'No Encoding';
2012
			$QuicktimeAudioCodecLookup['Qclp']          = 'Qualcomm PureVoice';
2013
			$QuicktimeAudioCodecLookup['QDM2']          = 'QDesign Music 2';
2014
			$QuicktimeAudioCodecLookup['QDMC']          = 'QDesign Music 1';
2015
			$QuicktimeAudioCodecLookup['ratb']          = '8-bit Rate';
2016
			$QuicktimeAudioCodecLookup['ratw']          = '16-bit Rate';
2017
			$QuicktimeAudioCodecLookup['raw ']          = 'raw PCM';
2018
			$QuicktimeAudioCodecLookup['sour']          = 'Sound Source';
2019
			$QuicktimeAudioCodecLookup['sowt']          = 'signed/two\'s complement (Little Endian)';
2020
			$QuicktimeAudioCodecLookup['str1']          = 'Iomega MPEG layer II';
2021
			$QuicktimeAudioCodecLookup['str2']          = 'Iomega MPEG *layer II';
2022
			$QuicktimeAudioCodecLookup['str3']          = 'Iomega MPEG **layer II';
2023
			$QuicktimeAudioCodecLookup['str4']          = 'Iomega MPEG ***layer II';
2024
			$QuicktimeAudioCodecLookup['twos']          = 'signed/two\'s complement (Big Endian)';
2025
			$QuicktimeAudioCodecLookup['ulaw']          = 'mu-law 2:1';
2026
		}
2027
		return (isset($QuicktimeAudioCodecLookup[$codecid]) ? $QuicktimeAudioCodecLookup[$codecid] : '');
2028
	}
2029
2030
	public function QuicktimeDCOMLookup($compressionid) {
2031
		static $QuicktimeDCOMLookup = array();
2032
		if (empty($QuicktimeDCOMLookup)) {
2033
			$QuicktimeDCOMLookup['zlib'] = 'ZLib Deflate';
2034
			$QuicktimeDCOMLookup['adec'] = 'Apple Compression';
2035
		}
2036
		return (isset($QuicktimeDCOMLookup[$compressionid]) ? $QuicktimeDCOMLookup[$compressionid] : '');
2037
	}
2038
2039
	public function QuicktimeColorNameLookup($colordepthid) {
2040
		static $QuicktimeColorNameLookup = array();
2041
		if (empty($QuicktimeColorNameLookup)) {
2042
			$QuicktimeColorNameLookup[1]  = '2-color (monochrome)';
2043
			$QuicktimeColorNameLookup[2]  = '4-color';
2044
			$QuicktimeColorNameLookup[4]  = '16-color';
2045
			$QuicktimeColorNameLookup[8]  = '256-color';
2046
			$QuicktimeColorNameLookup[16] = 'thousands (16-bit color)';
2047
			$QuicktimeColorNameLookup[24] = 'millions (24-bit color)';
2048
			$QuicktimeColorNameLookup[32] = 'millions+ (32-bit color)';
2049
			$QuicktimeColorNameLookup[33] = 'black & white';
2050
			$QuicktimeColorNameLookup[34] = '4-gray';
2051
			$QuicktimeColorNameLookup[36] = '16-gray';
2052
			$QuicktimeColorNameLookup[40] = '256-gray';
2053
		}
2054
		return (isset($QuicktimeColorNameLookup[$colordepthid]) ? $QuicktimeColorNameLookup[$colordepthid] : 'invalid');
2055
	}
2056
2057
	public function QuicktimeSTIKLookup($stik) {
2058
		static $QuicktimeSTIKLookup = array();
2059
		if (empty($QuicktimeSTIKLookup)) {
2060
			$QuicktimeSTIKLookup[0]  = 'Movie';
2061
			$QuicktimeSTIKLookup[1]  = 'Normal';
2062
			$QuicktimeSTIKLookup[2]  = 'Audiobook';
2063
			$QuicktimeSTIKLookup[5]  = 'Whacked Bookmark';
2064
			$QuicktimeSTIKLookup[6]  = 'Music Video';
2065
			$QuicktimeSTIKLookup[9]  = 'Short Film';
2066
			$QuicktimeSTIKLookup[10] = 'TV Show';
2067
			$QuicktimeSTIKLookup[11] = 'Booklet';
2068
			$QuicktimeSTIKLookup[14] = 'Ringtone';
2069
			$QuicktimeSTIKLookup[21] = 'Podcast';
2070
		}
2071
		return (isset($QuicktimeSTIKLookup[$stik]) ? $QuicktimeSTIKLookup[$stik] : 'invalid');
2072
	}
2073
2074
	public function QuicktimeIODSaudioProfileName($audio_profile_id) {
2075
		static $QuicktimeIODSaudioProfileNameLookup = array();
2076
		if (empty($QuicktimeIODSaudioProfileNameLookup)) {
2077
			$QuicktimeIODSaudioProfileNameLookup = array(
2078
				0x00 => 'ISO Reserved (0x00)',
2079
				0x01 => 'Main Audio Profile @ Level 1',
2080
				0x02 => 'Main Audio Profile @ Level 2',
2081
				0x03 => 'Main Audio Profile @ Level 3',
2082
				0x04 => 'Main Audio Profile @ Level 4',
2083
				0x05 => 'Scalable Audio Profile @ Level 1',
2084
				0x06 => 'Scalable Audio Profile @ Level 2',
2085
				0x07 => 'Scalable Audio Profile @ Level 3',
2086
				0x08 => 'Scalable Audio Profile @ Level 4',
2087
				0x09 => 'Speech Audio Profile @ Level 1',
2088
				0x0A => 'Speech Audio Profile @ Level 2',
2089
				0x0B => 'Synthetic Audio Profile @ Level 1',
2090
				0x0C => 'Synthetic Audio Profile @ Level 2',
2091
				0x0D => 'Synthetic Audio Profile @ Level 3',
2092
				0x0E => 'High Quality Audio Profile @ Level 1',
2093
				0x0F => 'High Quality Audio Profile @ Level 2',
2094
				0x10 => 'High Quality Audio Profile @ Level 3',
2095
				0x11 => 'High Quality Audio Profile @ Level 4',
2096
				0x12 => 'High Quality Audio Profile @ Level 5',
2097
				0x13 => 'High Quality Audio Profile @ Level 6',
2098
				0x14 => 'High Quality Audio Profile @ Level 7',
2099
				0x15 => 'High Quality Audio Profile @ Level 8',
2100
				0x16 => 'Low Delay Audio Profile @ Level 1',
2101
				0x17 => 'Low Delay Audio Profile @ Level 2',
2102
				0x18 => 'Low Delay Audio Profile @ Level 3',
2103
				0x19 => 'Low Delay Audio Profile @ Level 4',
2104
				0x1A => 'Low Delay Audio Profile @ Level 5',
2105
				0x1B => 'Low Delay Audio Profile @ Level 6',
2106
				0x1C => 'Low Delay Audio Profile @ Level 7',
2107
				0x1D => 'Low Delay Audio Profile @ Level 8',
2108
				0x1E => 'Natural Audio Profile @ Level 1',
2109
				0x1F => 'Natural Audio Profile @ Level 2',
2110
				0x20 => 'Natural Audio Profile @ Level 3',
2111
				0x21 => 'Natural Audio Profile @ Level 4',
2112
				0x22 => 'Mobile Audio Internetworking Profile @ Level 1',
2113
				0x23 => 'Mobile Audio Internetworking Profile @ Level 2',
2114
				0x24 => 'Mobile Audio Internetworking Profile @ Level 3',
2115
				0x25 => 'Mobile Audio Internetworking Profile @ Level 4',
2116
				0x26 => 'Mobile Audio Internetworking Profile @ Level 5',
2117
				0x27 => 'Mobile Audio Internetworking Profile @ Level 6',
2118
				0x28 => 'AAC Profile @ Level 1',
2119
				0x29 => 'AAC Profile @ Level 2',
2120
				0x2A => 'AAC Profile @ Level 4',
2121
				0x2B => 'AAC Profile @ Level 5',
2122
				0x2C => 'High Efficiency AAC Profile @ Level 2',
2123
				0x2D => 'High Efficiency AAC Profile @ Level 3',
2124
				0x2E => 'High Efficiency AAC Profile @ Level 4',
2125
				0x2F => 'High Efficiency AAC Profile @ Level 5',
2126
				0xFE => 'Not part of MPEG-4 audio profiles',
2127
				0xFF => 'No audio capability required',
2128
			);
2129
		}
2130
		return (isset($QuicktimeIODSaudioProfileNameLookup[$audio_profile_id]) ? $QuicktimeIODSaudioProfileNameLookup[$audio_profile_id] : 'ISO Reserved / User Private');
2131
	}
2132
2133
2134
	public function QuicktimeIODSvideoProfileName($video_profile_id) {
2135
		static $QuicktimeIODSvideoProfileNameLookup = array();
2136
		if (empty($QuicktimeIODSvideoProfileNameLookup)) {
2137
			$QuicktimeIODSvideoProfileNameLookup = array(
2138
				0x00 => 'Reserved (0x00) Profile',
2139
				0x01 => 'Simple Profile @ Level 1',
2140
				0x02 => 'Simple Profile @ Level 2',
2141
				0x03 => 'Simple Profile @ Level 3',
2142
				0x08 => 'Simple Profile @ Level 0',
2143
				0x10 => 'Simple Scalable Profile @ Level 0',
2144
				0x11 => 'Simple Scalable Profile @ Level 1',
2145
				0x12 => 'Simple Scalable Profile @ Level 2',
2146
				0x15 => 'AVC/H264 Profile',
2147
				0x21 => 'Core Profile @ Level 1',
2148
				0x22 => 'Core Profile @ Level 2',
2149
				0x32 => 'Main Profile @ Level 2',
2150
				0x33 => 'Main Profile @ Level 3',
2151
				0x34 => 'Main Profile @ Level 4',
2152
				0x42 => 'N-bit Profile @ Level 2',
2153
				0x51 => 'Scalable Texture Profile @ Level 1',
2154
				0x61 => 'Simple Face Animation Profile @ Level 1',
2155
				0x62 => 'Simple Face Animation Profile @ Level 2',
2156
				0x63 => 'Simple FBA Profile @ Level 1',
2157
				0x64 => 'Simple FBA Profile @ Level 2',
2158
				0x71 => 'Basic Animated Texture Profile @ Level 1',
2159
				0x72 => 'Basic Animated Texture Profile @ Level 2',
2160
				0x81 => 'Hybrid Profile @ Level 1',
2161
				0x82 => 'Hybrid Profile @ Level 2',
2162
				0x91 => 'Advanced Real Time Simple Profile @ Level 1',
2163
				0x92 => 'Advanced Real Time Simple Profile @ Level 2',
2164
				0x93 => 'Advanced Real Time Simple Profile @ Level 3',
2165
				0x94 => 'Advanced Real Time Simple Profile @ Level 4',
2166
				0xA1 => 'Core Scalable Profile @ Level1',
2167
				0xA2 => 'Core Scalable Profile @ Level2',
2168
				0xA3 => 'Core Scalable Profile @ Level3',
2169
				0xB1 => 'Advanced Coding Efficiency Profile @ Level 1',
2170
				0xB2 => 'Advanced Coding Efficiency Profile @ Level 2',
2171
				0xB3 => 'Advanced Coding Efficiency Profile @ Level 3',
2172
				0xB4 => 'Advanced Coding Efficiency Profile @ Level 4',
2173
				0xC1 => 'Advanced Core Profile @ Level 1',
2174
				0xC2 => 'Advanced Core Profile @ Level 2',
2175
				0xD1 => 'Advanced Scalable Texture @ Level1',
2176
				0xD2 => 'Advanced Scalable Texture @ Level2',
2177
				0xE1 => 'Simple Studio Profile @ Level 1',
2178
				0xE2 => 'Simple Studio Profile @ Level 2',
2179
				0xE3 => 'Simple Studio Profile @ Level 3',
2180
				0xE4 => 'Simple Studio Profile @ Level 4',
2181
				0xE5 => 'Core Studio Profile @ Level 1',
2182
				0xE6 => 'Core Studio Profile @ Level 2',
2183
				0xE7 => 'Core Studio Profile @ Level 3',
2184
				0xE8 => 'Core Studio Profile @ Level 4',
2185
				0xF0 => 'Advanced Simple Profile @ Level 0',
2186
				0xF1 => 'Advanced Simple Profile @ Level 1',
2187
				0xF2 => 'Advanced Simple Profile @ Level 2',
2188
				0xF3 => 'Advanced Simple Profile @ Level 3',
2189
				0xF4 => 'Advanced Simple Profile @ Level 4',
2190
				0xF5 => 'Advanced Simple Profile @ Level 5',
2191
				0xF7 => 'Advanced Simple Profile @ Level 3b',
2192
				0xF8 => 'Fine Granularity Scalable Profile @ Level 0',
2193
				0xF9 => 'Fine Granularity Scalable Profile @ Level 1',
2194
				0xFA => 'Fine Granularity Scalable Profile @ Level 2',
2195
				0xFB => 'Fine Granularity Scalable Profile @ Level 3',
2196
				0xFC => 'Fine Granularity Scalable Profile @ Level 4',
2197
				0xFD => 'Fine Granularity Scalable Profile @ Level 5',
2198
				0xFE => 'Not part of MPEG-4 Visual profiles',
2199
				0xFF => 'No visual capability required',
2200
			);
2201
		}
2202
		return (isset($QuicktimeIODSvideoProfileNameLookup[$video_profile_id]) ? $QuicktimeIODSvideoProfileNameLookup[$video_profile_id] : 'ISO Reserved Profile');
2203
	}
2204
2205
2206 View Code Duplication
	public function QuicktimeContentRatingLookup($rtng) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2207
		static $QuicktimeContentRatingLookup = array();
2208
		if (empty($QuicktimeContentRatingLookup)) {
2209
			$QuicktimeContentRatingLookup[0]  = 'None';
2210
			$QuicktimeContentRatingLookup[2]  = 'Clean';
2211
			$QuicktimeContentRatingLookup[4]  = 'Explicit';
2212
		}
2213
		return (isset($QuicktimeContentRatingLookup[$rtng]) ? $QuicktimeContentRatingLookup[$rtng] : 'invalid');
2214
	}
2215
2216
	public function QuicktimeStoreAccountTypeLookup($akid) {
2217
		static $QuicktimeStoreAccountTypeLookup = array();
2218
		if (empty($QuicktimeStoreAccountTypeLookup)) {
2219
			$QuicktimeStoreAccountTypeLookup[0] = 'iTunes';
2220
			$QuicktimeStoreAccountTypeLookup[1] = 'AOL';
2221
		}
2222
		return (isset($QuicktimeStoreAccountTypeLookup[$akid]) ? $QuicktimeStoreAccountTypeLookup[$akid] : 'invalid');
2223
	}
2224
2225
	public function QuicktimeStoreFrontCodeLookup($sfid) {
2226
		static $QuicktimeStoreFrontCodeLookup = array();
2227
		if (empty($QuicktimeStoreFrontCodeLookup)) {
2228
			$QuicktimeStoreFrontCodeLookup[143460] = 'Australia';
2229
			$QuicktimeStoreFrontCodeLookup[143445] = 'Austria';
2230
			$QuicktimeStoreFrontCodeLookup[143446] = 'Belgium';
2231
			$QuicktimeStoreFrontCodeLookup[143455] = 'Canada';
2232
			$QuicktimeStoreFrontCodeLookup[143458] = 'Denmark';
2233
			$QuicktimeStoreFrontCodeLookup[143447] = 'Finland';
2234
			$QuicktimeStoreFrontCodeLookup[143442] = 'France';
2235
			$QuicktimeStoreFrontCodeLookup[143443] = 'Germany';
2236
			$QuicktimeStoreFrontCodeLookup[143448] = 'Greece';
2237
			$QuicktimeStoreFrontCodeLookup[143449] = 'Ireland';
2238
			$QuicktimeStoreFrontCodeLookup[143450] = 'Italy';
2239
			$QuicktimeStoreFrontCodeLookup[143462] = 'Japan';
2240
			$QuicktimeStoreFrontCodeLookup[143451] = 'Luxembourg';
2241
			$QuicktimeStoreFrontCodeLookup[143452] = 'Netherlands';
2242
			$QuicktimeStoreFrontCodeLookup[143461] = 'New Zealand';
2243
			$QuicktimeStoreFrontCodeLookup[143457] = 'Norway';
2244
			$QuicktimeStoreFrontCodeLookup[143453] = 'Portugal';
2245
			$QuicktimeStoreFrontCodeLookup[143454] = 'Spain';
2246
			$QuicktimeStoreFrontCodeLookup[143456] = 'Sweden';
2247
			$QuicktimeStoreFrontCodeLookup[143459] = 'Switzerland';
2248
			$QuicktimeStoreFrontCodeLookup[143444] = 'United Kingdom';
2249
			$QuicktimeStoreFrontCodeLookup[143441] = 'United States';
2250
		}
2251
		return (isset($QuicktimeStoreFrontCodeLookup[$sfid]) ? $QuicktimeStoreFrontCodeLookup[$sfid] : 'invalid');
2252
	}
2253
2254
	public function QuicktimeParseNikonNCTG($atom_data) {
2255
		// http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html#NCTG
2256
		// Nikon-specific QuickTime tags found in the NCDT atom of MOV videos from some Nikon cameras such as the Coolpix S8000 and D5100
2257
		// Data is stored as records of:
2258
		// * 4 bytes record type
2259
		// * 2 bytes size of data field type:
2260
		//     0x0001 = flag   (size field *= 1-byte)
2261
		//     0x0002 = char   (size field *= 1-byte)
2262
		//     0x0003 = DWORD+ (size field *= 2-byte), values are stored CDAB
2263
		//     0x0004 = QWORD+ (size field *= 4-byte), values are stored EFGHABCD
2264
		//     0x0005 = float  (size field *= 8-byte), values are stored aaaabbbb where value is aaaa/bbbb; possibly multiple sets of values appended together
2265
		//     0x0007 = bytes  (size field *= 1-byte), values are stored as ??????
2266
		//     0x0008 = ?????  (size field *= 2-byte), values are stored as ??????
2267
		// * 2 bytes data size field
2268
		// * ? bytes data (string data may be null-padded; datestamp fields are in the format "2011:05:25 20:24:15")
2269
		// all integers are stored BigEndian
2270
2271
		$NCTGtagName = array(
2272
			0x00000001 => 'Make',
2273
			0x00000002 => 'Model',
2274
			0x00000003 => 'Software',
2275
			0x00000011 => 'CreateDate',
2276
			0x00000012 => 'DateTimeOriginal',
2277
			0x00000013 => 'FrameCount',
2278
			0x00000016 => 'FrameRate',
2279
			0x00000022 => 'FrameWidth',
2280
			0x00000023 => 'FrameHeight',
2281
			0x00000032 => 'AudioChannels',
2282
			0x00000033 => 'AudioBitsPerSample',
2283
			0x00000034 => 'AudioSampleRate',
2284
			0x02000001 => 'MakerNoteVersion',
2285
			0x02000005 => 'WhiteBalance',
2286
			0x0200000b => 'WhiteBalanceFineTune',
2287
			0x0200001e => 'ColorSpace',
2288
			0x02000023 => 'PictureControlData',
2289
			0x02000024 => 'WorldTime',
2290
			0x02000032 => 'UnknownInfo',
2291
			0x02000083 => 'LensType',
2292
			0x02000084 => 'Lens',
2293
		);
2294
2295
		$offset = 0;
2296
		$datalength = strlen($atom_data);
2297
		$parsed = array();
2298
		while ($offset < $datalength) {
2299
//echo getid3_lib::PrintHexBytes(substr($atom_data, $offset, 4)).'<br>';
2300
			$record_type       = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 4));  $offset += 4;
2301
			$data_size_type    = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 2));  $offset += 2;
2302
			$data_size         = getid3_lib::BigEndian2Int(substr($atom_data, $offset, 2));  $offset += 2;
2303
			switch ($data_size_type) {
2304
				case 0x0001: // 0x0001 = flag   (size field *= 1-byte)
2305
					$data = getid3_lib::BigEndian2Int(substr($atom_data, $offset, $data_size * 1));
2306
					$offset += ($data_size * 1);
2307
					break;
2308 View Code Duplication
				case 0x0002: // 0x0002 = char   (size field *= 1-byte)
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2309
					$data = substr($atom_data, $offset, $data_size * 1);
2310
					$offset += ($data_size * 1);
2311
					$data = rtrim($data, "\x00");
2312
					break;
2313 View Code Duplication
				case 0x0003: // 0x0003 = DWORD+ (size field *= 2-byte), values are stored CDAB
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2314
					$data = '';
2315
					for ($i = $data_size - 1; $i >= 0; $i--) {
2316
						$data .= substr($atom_data, $offset + ($i * 2), 2);
2317
					}
2318
					$data = getid3_lib::BigEndian2Int($data);
2319
					$offset += ($data_size * 2);
2320
					break;
2321 View Code Duplication
				case 0x0004: // 0x0004 = QWORD+ (size field *= 4-byte), values are stored EFGHABCD
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2322
					$data = '';
2323
					for ($i = $data_size - 1; $i >= 0; $i--) {
2324
						$data .= substr($atom_data, $offset + ($i * 4), 4);
2325
					}
2326
					$data = getid3_lib::BigEndian2Int($data);
2327
					$offset += ($data_size * 4);
2328
					break;
2329
				case 0x0005: // 0x0005 = float  (size field *= 8-byte), values are stored aaaabbbb where value is aaaa/bbbb; possibly multiple sets of values appended together
2330
					$data = array();
2331
					for ($i = 0; $i < $data_size; $i++) {
2332
						$numerator    = getid3_lib::BigEndian2Int(substr($atom_data, $offset + ($i * 8) + 0, 4));
2333
						$denomninator = getid3_lib::BigEndian2Int(substr($atom_data, $offset + ($i * 8) + 4, 4));
2334
						if ($denomninator == 0) {
2335
							$data[$i] = false;
2336
						} else {
2337
							$data[$i] = (double) $numerator / $denomninator;
2338
						}
2339
					}
2340
					$offset += (8 * $data_size);
2341
					if (count($data) == 1) {
2342
						$data = $data[0];
2343
					}
2344
					break;
2345 View Code Duplication
				case 0x0007: // 0x0007 = bytes  (size field *= 1-byte), values are stored as ??????
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2346
					$data = substr($atom_data, $offset, $data_size * 1);
2347
					$offset += ($data_size * 1);
2348
					break;
2349 View Code Duplication
				case 0x0008: // 0x0008 = ?????  (size field *= 2-byte), values are stored as ??????
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2350
					$data = substr($atom_data, $offset, $data_size * 2);
2351
					$offset += ($data_size * 2);
2352
					break;
2353
				default:
2354
echo 'QuicktimeParseNikonNCTG()::unknown $data_size_type: '.$data_size_type.'<br>';
2355
					break 2;
2356
			}
2357
2358
			switch ($record_type) {
2359
				case 0x00000011: // CreateDate
2360
				case 0x00000012: // DateTimeOriginal
2361
					$data = strtotime($data);
2362
					break;
2363
				case 0x0200001e: // ColorSpace
2364
					switch ($data) {
2365
						case 1:
2366
							$data = 'sRGB';
2367
							break;
2368
						case 2:
2369
							$data = 'Adobe RGB';
2370
							break;
2371
					}
2372
					break;
2373
				case 0x02000023: // PictureControlData
2374
					$PictureControlAdjust = array(0=>'default', 1=>'quick', 2=>'full');
2375
					$FilterEffect = array(0x80=>'off', 0x81=>'yellow', 0x82=>'orange',    0x83=>'red', 0x84=>'green',  0xff=>'n/a');
2376
					$ToningEffect = array(0x80=>'b&w', 0x81=>'sepia',  0x82=>'cyanotype', 0x83=>'red', 0x84=>'yellow', 0x85=>'green', 0x86=>'blue-green', 0x87=>'blue', 0x88=>'purple-blue', 0x89=>'red-purple', 0xff=>'n/a');
2377
					$data = array(
2378
						'PictureControlVersion'     =>                           substr($data,  0,  4),
2379
						'PictureControlName'        =>                     rtrim(substr($data,  4, 20), "\x00"),
2380
						'PictureControlBase'        =>                     rtrim(substr($data, 24, 20), "\x00"),
2381
						//'?'                       =>                           substr($data, 44,  4),
2382
						'PictureControlAdjust'      => $PictureControlAdjust[ord(substr($data, 48,  1))],
2383
						'PictureControlQuickAdjust' =>                       ord(substr($data, 49,  1)),
2384
						'Sharpness'                 =>                       ord(substr($data, 50,  1)),
2385
						'Contrast'                  =>                       ord(substr($data, 51,  1)),
2386
						'Brightness'                =>                       ord(substr($data, 52,  1)),
2387
						'Saturation'                =>                       ord(substr($data, 53,  1)),
2388
						'HueAdjustment'             =>                       ord(substr($data, 54,  1)),
2389
						'FilterEffect'              =>         $FilterEffect[ord(substr($data, 55,  1))],
2390
						'ToningEffect'              =>         $ToningEffect[ord(substr($data, 56,  1))],
2391
						'ToningSaturation'          =>                       ord(substr($data, 57,  1)),
2392
					);
2393
					break;
2394
				case 0x02000024: // WorldTime
2395
					// http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html#WorldTime
2396
					// timezone is stored as offset from GMT in minutes
2397
					$timezone = getid3_lib::BigEndian2Int(substr($data, 0, 2));
2398
					if ($timezone & 0x8000) {
2399
						$timezone = 0 - (0x10000 - $timezone);
2400
					}
2401
					$timezone /= 60;
2402
2403
					$dst = (bool) getid3_lib::BigEndian2Int(substr($data, 2, 1));
2404
					switch (getid3_lib::BigEndian2Int(substr($data, 3, 1))) {
2405
						case 2:
2406
							$datedisplayformat = 'D/M/Y'; break;
2407
						case 1:
2408
							$datedisplayformat = 'M/D/Y'; break;
2409
						case 0:
2410
						default:
2411
							$datedisplayformat = 'Y/M/D'; break;
2412
					}
2413
2414
					$data = array('timezone'=>floatval($timezone), 'dst'=>$dst, 'display'=>$datedisplayformat);
2415
					break;
2416
				case 0x02000083: // LensType
2417
					$data = array(
2418
						//'_'  => $data,
2419
						'mf' => (bool) ($data & 0x01),
2420
						'd'  => (bool) ($data & 0x02),
2421
						'g'  => (bool) ($data & 0x04),
2422
						'vr' => (bool) ($data & 0x08),
2423
					);
2424
					break;
2425
			}
2426
			$tag_name = (isset($NCTGtagName[$record_type]) ? $NCTGtagName[$record_type] : '0x'.str_pad(dechex($record_type), 8, '0', STR_PAD_LEFT));
2427
			$parsed[$tag_name] = $data;
2428
		}
2429
		return $parsed;
2430
	}
2431
2432
2433
	public function CopyToAppropriateCommentsSection($keyname, $data, $boxname='') {
2434
		static $handyatomtranslatorarray = array();
2435
		if (empty($handyatomtranslatorarray)) {
2436
			// http://www.geocities.com/xhelmboyx/quicktime/formats/qtm-layout.txt
2437
			// http://www.geocities.com/xhelmboyx/quicktime/formats/mp4-layout.txt
2438
			// http://atomicparsley.sourceforge.net/mpeg-4files.html
2439
			// https://code.google.com/p/mp4v2/wiki/iTunesMetadata
2440
			$handyatomtranslatorarray["\xA9".'alb'] = 'album';               // iTunes 4.0
2441
			$handyatomtranslatorarray["\xA9".'ART'] = 'artist';
2442
			$handyatomtranslatorarray["\xA9".'art'] = 'artist';              // iTunes 4.0
2443
			$handyatomtranslatorarray["\xA9".'aut'] = 'author';
2444
			$handyatomtranslatorarray["\xA9".'cmt'] = 'comment';             // iTunes 4.0
2445
			$handyatomtranslatorarray["\xA9".'com'] = 'comment';
2446
			$handyatomtranslatorarray["\xA9".'cpy'] = 'copyright';
2447
			$handyatomtranslatorarray["\xA9".'day'] = 'creation_date';       // iTunes 4.0
2448
			$handyatomtranslatorarray["\xA9".'dir'] = 'director';
2449
			$handyatomtranslatorarray["\xA9".'ed1'] = 'edit1';
2450
			$handyatomtranslatorarray["\xA9".'ed2'] = 'edit2';
2451
			$handyatomtranslatorarray["\xA9".'ed3'] = 'edit3';
2452
			$handyatomtranslatorarray["\xA9".'ed4'] = 'edit4';
2453
			$handyatomtranslatorarray["\xA9".'ed5'] = 'edit5';
2454
			$handyatomtranslatorarray["\xA9".'ed6'] = 'edit6';
2455
			$handyatomtranslatorarray["\xA9".'ed7'] = 'edit7';
2456
			$handyatomtranslatorarray["\xA9".'ed8'] = 'edit8';
2457
			$handyatomtranslatorarray["\xA9".'ed9'] = 'edit9';
2458
			$handyatomtranslatorarray["\xA9".'enc'] = 'encoded_by';
2459
			$handyatomtranslatorarray["\xA9".'fmt'] = 'format';
2460
			$handyatomtranslatorarray["\xA9".'gen'] = 'genre';               // iTunes 4.0
2461
			$handyatomtranslatorarray["\xA9".'grp'] = 'grouping';            // iTunes 4.2
2462
			$handyatomtranslatorarray["\xA9".'hst'] = 'host_computer';
2463
			$handyatomtranslatorarray["\xA9".'inf'] = 'information';
2464
			$handyatomtranslatorarray["\xA9".'lyr'] = 'lyrics';              // iTunes 5.0
2465
			$handyatomtranslatorarray["\xA9".'mak'] = 'make';
2466
			$handyatomtranslatorarray["\xA9".'mod'] = 'model';
2467
			$handyatomtranslatorarray["\xA9".'nam'] = 'title';               // iTunes 4.0
2468
			$handyatomtranslatorarray["\xA9".'ope'] = 'composer';
2469
			$handyatomtranslatorarray["\xA9".'prd'] = 'producer';
2470
			$handyatomtranslatorarray["\xA9".'PRD'] = 'product';
2471
			$handyatomtranslatorarray["\xA9".'prf'] = 'performers';
2472
			$handyatomtranslatorarray["\xA9".'req'] = 'system_requirements';
2473
			$handyatomtranslatorarray["\xA9".'src'] = 'source_credit';
2474
			$handyatomtranslatorarray["\xA9".'swr'] = 'software';
2475
			$handyatomtranslatorarray["\xA9".'too'] = 'encoding_tool';       // iTunes 4.0
2476
			$handyatomtranslatorarray["\xA9".'trk'] = 'track';
2477
			$handyatomtranslatorarray["\xA9".'url'] = 'url';
2478
			$handyatomtranslatorarray["\xA9".'wrn'] = 'warning';
2479
			$handyatomtranslatorarray["\xA9".'wrt'] = 'composer';
2480
			$handyatomtranslatorarray['aART'] = 'album_artist';
2481
			$handyatomtranslatorarray['apID'] = 'purchase_account';
2482
			$handyatomtranslatorarray['catg'] = 'category';            // iTunes 4.9
2483
			$handyatomtranslatorarray['covr'] = 'picture';             // iTunes 4.0
2484
			$handyatomtranslatorarray['cpil'] = 'compilation';         // iTunes 4.0
2485
			$handyatomtranslatorarray['cprt'] = 'copyright';           // iTunes 4.0?
2486
			$handyatomtranslatorarray['desc'] = 'description';         // iTunes 5.0
2487
			$handyatomtranslatorarray['disk'] = 'disc_number';         // iTunes 4.0
2488
			$handyatomtranslatorarray['egid'] = 'episode_guid';        // iTunes 4.9
2489
			$handyatomtranslatorarray['gnre'] = 'genre';               // iTunes 4.0
2490
			$handyatomtranslatorarray['hdvd'] = 'hd_video';            // iTunes 4.0
2491
			$handyatomtranslatorarray['ldes'] = 'description_long';    //
2492
			$handyatomtranslatorarray['keyw'] = 'keyword';             // iTunes 4.9
2493
			$handyatomtranslatorarray['pcst'] = 'podcast';             // iTunes 4.9
2494
			$handyatomtranslatorarray['pgap'] = 'gapless_playback';    // iTunes 7.0
2495
			$handyatomtranslatorarray['purd'] = 'purchase_date';       // iTunes 6.0.2
2496
			$handyatomtranslatorarray['purl'] = 'podcast_url';         // iTunes 4.9
2497
			$handyatomtranslatorarray['rtng'] = 'rating';              // iTunes 4.0
2498
			$handyatomtranslatorarray['soaa'] = 'sort_album_artist';   //
2499
			$handyatomtranslatorarray['soal'] = 'sort_album';          //
2500
			$handyatomtranslatorarray['soar'] = 'sort_artist';         //
2501
			$handyatomtranslatorarray['soco'] = 'sort_composer';       //
2502
			$handyatomtranslatorarray['sonm'] = 'sort_title';          //
2503
			$handyatomtranslatorarray['sosn'] = 'sort_show';           //
2504
			$handyatomtranslatorarray['stik'] = 'stik';                // iTunes 4.9
2505
			$handyatomtranslatorarray['tmpo'] = 'bpm';                 // iTunes 4.0
2506
			$handyatomtranslatorarray['trkn'] = 'track_number';        // iTunes 4.0
2507
			$handyatomtranslatorarray['tven'] = 'tv_episode_id';       //
2508
			$handyatomtranslatorarray['tves'] = 'tv_episode';          // iTunes 6.0
2509
			$handyatomtranslatorarray['tvnn'] = 'tv_network_name';     // iTunes 6.0
2510
			$handyatomtranslatorarray['tvsh'] = 'tv_show_name';        // iTunes 6.0
2511
			$handyatomtranslatorarray['tvsn'] = 'tv_season';           // iTunes 6.0
2512
2513
			// boxnames:
2514
			/*
2515
			$handyatomtranslatorarray['iTunSMPB']                    = 'iTunSMPB';
2516
			$handyatomtranslatorarray['iTunNORM']                    = 'iTunNORM';
2517
			$handyatomtranslatorarray['Encoding Params']             = 'Encoding Params';
2518
			$handyatomtranslatorarray['replaygain_track_gain']       = 'replaygain_track_gain';
2519
			$handyatomtranslatorarray['replaygain_track_peak']       = 'replaygain_track_peak';
2520
			$handyatomtranslatorarray['replaygain_track_minmax']     = 'replaygain_track_minmax';
2521
			$handyatomtranslatorarray['MusicIP PUID']                = 'MusicIP PUID';
2522
			$handyatomtranslatorarray['MusicBrainz Artist Id']       = 'MusicBrainz Artist Id';
2523
			$handyatomtranslatorarray['MusicBrainz Album Id']        = 'MusicBrainz Album Id';
2524
			$handyatomtranslatorarray['MusicBrainz Album Artist Id'] = 'MusicBrainz Album Artist Id';
2525
			$handyatomtranslatorarray['MusicBrainz Track Id']        = 'MusicBrainz Track Id';
2526
			$handyatomtranslatorarray['MusicBrainz Disc Id']         = 'MusicBrainz Disc Id';
2527
2528
			// http://age.hobba.nl/audio/tag_frame_reference.html
2529
			$handyatomtranslatorarray['PLAY_COUNTER']                = 'play_counter'; // Foobar2000 - http://www.getid3.org/phpBB3/viewtopic.php?t=1355
2530
			$handyatomtranslatorarray['MEDIATYPE']                   = 'mediatype';    // Foobar2000 - http://www.getid3.org/phpBB3/viewtopic.php?t=1355
2531
			*/
2532
		}
2533
		$info = &$this->getid3->info;
2534
		$comment_key = '';
2535
		if ($boxname && ($boxname != $keyname)) {
2536
			$comment_key = (isset($handyatomtranslatorarray[$boxname]) ? $handyatomtranslatorarray[$boxname] : $boxname);
2537
		} elseif (isset($handyatomtranslatorarray[$keyname])) {
2538
			$comment_key = $handyatomtranslatorarray[$keyname];
2539
		}
2540
		if ($comment_key) {
2541
			if ($comment_key == 'picture') {
2542
				if (!is_array($data)) {
2543
					$image_mime = '';
2544
					if (preg_match('#^\x89\x50\x4E\x47\x0D\x0A\x1A\x0A#', $data)) {
2545
						$image_mime = 'image/png';
2546
					} elseif (preg_match('#^\xFF\xD8\xFF#', $data)) {
2547
						$image_mime = 'image/jpeg';
2548
					} elseif (preg_match('#^GIF#', $data)) {
2549
						$image_mime = 'image/gif';
2550
					} elseif (preg_match('#^BM#', $data)) {
2551
						$image_mime = 'image/bmp';
2552
					}
2553
					$data = array('data'=>$data, 'image_mime'=>$image_mime);
2554
				}
2555
			}
2556
			$gooddata = array($data);
2557
			if ($comment_key == 'genre') {
2558
				// some other taggers separate multiple genres with semicolon, e.g. "Heavy Metal;Thrash Metal;Metal"
2559
				$gooddata = explode(';', $data);
2560
			}
2561
			foreach ($gooddata as $data) {
2562
				$info['quicktime']['comments'][$comment_key][] = $data;
2563
			}
2564
		}
2565
		return true;
2566
	}
2567
2568
    public function LociString($lstring, &$count) {
2569
            // Loci strings are UTF-8 or UTF-16 and null (x00/x0000) terminated. UTF-16 has a BOM
2570
            // Also need to return the number of bytes the string occupied so additional fields can be extracted
2571
            $len = strlen($lstring);
2572
            if ($len == 0) {
2573
                $count = 0;
2574
                return '';
2575
            }
2576
            if ($lstring[0] == "\x00") {
2577
                $count = 1;
2578
                return '';
2579
            }
2580
            //check for BOM
2581
            if ($len > 2 && (($lstring[0] == "\xFE" && $lstring[1] == "\xFF") || ($lstring[0] == "\xFF" && $lstring[1] == "\xFE"))) {
2582
                //UTF-16
2583 View Code Duplication
                if (preg_match('/(.*)\x00/', $lstring, $lmatches)){
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2584
                     $count = strlen($lmatches[1]) * 2 + 2; //account for 2 byte characters and trailing \x0000
2585
                    return getid3_lib::iconv_fallback_utf16_utf8($lmatches[1]);
2586
                } else {
2587
                    return '';
2588
                }
2589 View Code Duplication
            } else {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2590
                //UTF-8
2591
                if (preg_match('/(.*)\x00/', $lstring, $lmatches)){
2592
                    $count = strlen($lmatches[1]) + 1; //account for trailing \x00
2593
                    return $lmatches[1];
2594
                }else {
2595
                    return '';
2596
                }
2597
2598
            }
2599
        }
2600
2601 View Code Duplication
	public function NoNullString($nullterminatedstring) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
2602
		// remove the single null terminator on null terminated strings
2603
		if (substr($nullterminatedstring, strlen($nullterminatedstring) - 1, 1) === "\x00") {
2604
			return substr($nullterminatedstring, 0, strlen($nullterminatedstring) - 1);
2605
		}
2606
		return $nullterminatedstring;
2607
	}
2608
2609
	public function Pascal2String($pascalstring) {
2610
		// Pascal strings have 1 unsigned byte at the beginning saying how many chars (1-255) are in the string
2611
		return substr($pascalstring, 1);
2612
	}
2613
2614
2615
	/*
2616
	// helper functions for m4b audiobook chapters
2617
	// code by Steffen Hartmann 2015-Nov-08
2618
	*/
2619
	public function search_tag_by_key($info, $tag, $history, &$result) {
2620
		foreach ($info as $key => $value) {
2621
			$key_history = $history.'/'.$key;
2622
			if ($key === $tag) {
2623
				$result[] = array($key_history, $info);
2624
			} else {
2625
				if (is_array($value)) {
2626
					$this->search_tag_by_key($value, $tag, $key_history, $result);
2627
				}
2628
			}
2629
		}
2630
	}
2631
2632
	public function search_tag_by_pair($info, $k, $v, $history, &$result) {
2633
		foreach ($info as $key => $value) {
2634
			$key_history = $history.'/'.$key;
2635
			if (($key === $k) && ($value === $v)) {
2636
				$result[] = array($key_history, $info);
2637
			} else {
2638
				if (is_array($value)) {
2639
					$this->search_tag_by_pair($value, $k, $v, $key_history, $result);
2640
				}
2641
			}
2642
		}
2643
	}
2644
2645
	public function quicktime_time_to_sample_table($info) {
2646
		$res = array();
2647
		$this->search_tag_by_pair($info['quicktime']['moov'], 'name', 'stbl', 'quicktime/moov', $res);
2648
		foreach ($res as $value) {
2649
			$stbl_res = array();
2650
			$this->search_tag_by_pair($value[1], 'data_format', 'text', $value[0], $stbl_res);
2651
			if (count($stbl_res) > 0) {
2652
				$stts_res = array();
2653
				$this->search_tag_by_key($value[1], 'time_to_sample_table', $value[0], $stts_res);
2654
				if (count($stts_res) > 0) {
2655
					return $stts_res[0][1]['time_to_sample_table'];
2656
				}
2657
			}
2658
		}
2659
		return array();
2660
	}
2661
2662
	function quicktime_bookmark_time_scale($info) {
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
2663
		$time_scale = '';
2664
		$ts_prefix_len = 0;
2665
		$res = array();
2666
		$this->search_tag_by_pair($info['quicktime']['moov'], 'name', 'stbl', 'quicktime/moov', $res);
2667
		foreach ($res as $value) {
2668
			$stbl_res = array();
2669
			$this->search_tag_by_pair($value[1], 'data_format', 'text', $value[0], $stbl_res);
2670
			if (count($stbl_res) > 0) {
2671
				$ts_res = array();
2672
				$this->search_tag_by_key($info['quicktime']['moov'], 'time_scale', 'quicktime/moov', $ts_res);
2673
				foreach ($ts_res as $value) {
2674
					$prefix = substr($value[0], 0, -12);
2675
					if ((substr($stbl_res[0][0], 0, strlen($prefix)) === $prefix) && ($ts_prefix_len < strlen($prefix))) {
2676
						$time_scale = $value[1]['time_scale'];
2677
						$ts_prefix_len = strlen($prefix);
2678
					}
2679
				}
2680
			}
2681
		}
2682
		return $time_scale;
2683
	}
2684
	/*
2685
	// END helper functions for m4b audiobook chapters
2686
	*/
2687
2688
2689
}
2690