Completed
Push — vendor/getid3 ( 49c253...dfd0b4 )
by Pauli
02:49
created

getid3_tak   A

Complexity

Total Complexity 25

Size/Duplication

Total Lines 194
Duplicated Lines 9.79 %

Coupling/Cohesion

Components 1
Dependencies 3

Importance

Changes 0
Metric Value
dl 19
loc 194
rs 10
c 0
b 0
f 0
wmc 25
lcom 1
cbo 3

4 Methods

Rating   Name   Duplication   Size   Complexity  
F Analyze() 19 152 19
A TAKFramesizeLookup() 0 15 2
A TAKCodecTypeLookup() 0 10 2
A TAKProfileLookup() 0 11 2

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
/////////////////////////////////////////////////////////////////
3
/// getID3() by James Heinrich <[email protected]>               //
4
//  available at http://getid3.sourceforge.net                 //
5
//            or https://www.getid3.org                         //
6
//          also https://github.com/JamesHeinrich/getID3       //
7
/////////////////////////////////////////////////////////////////
8
// See readme.txt for more details                             //
9
/////////////////////////////////////////////////////////////////
10
//                                                             //
11
// module.audio.tak.php                                        //
12
// module for analyzing Tom's lossless Audio Kompressor        //
13
// dependencies: NONE                                          //
14
//                                                            ///
15
/////////////////////////////////////////////////////////////////
16
17
if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
18
	exit;
19
}
20
21
class getid3_tak extends getid3_handler
22
{
23
24
	public function Analyze() {
25
		$info = &$this->getid3->info;
26
27
		$info['fileformat']            = 'tak';
28
		$info['audio']['dataformat']   = 'tak';
29
		$info['audio']['bitrate_mode'] = 'vbr';
30
		$info['audio']['lossless']     = true;
31
32
		$info['tak_audio']['raw'] = array();
33
		$thisfile_takaudio                = &$info['tak_audio'];
34
		$thisfile_takaudio_raw            = &$thisfile_takaudio['raw'];
35
36
		$this->fseek($info['avdataoffset']);
37
		$TAKMetaData = $this->fread(4);
38
39
		$thisfile_takaudio_raw['magic'] = $TAKMetaData;
40
		$magic = 'tBaK';
41 View Code Duplication
		if ($thisfile_takaudio_raw['magic'] != $magic) {
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...
42
			$this->error('Expecting "'.getid3_lib::PrintHexBytes($magic).'" at offset '.$info['avdataoffset'].', found "'.getid3_lib::PrintHexBytes($thisfile_takaudio_raw['magic']).'"');
0 ignored issues
show
Security Bug introduced by
It seems like $thisfile_takaudio_raw['magic'] can also be of type false; however, getid3_lib::PrintHexBytes() does only seem to accept string, did you maybe forget to handle an error condition?
Loading history...
43
			unset($info['fileformat']);
44
			return false;
45
		}
46
		$offset = 4; //skip magic
47
		$this->fseek($offset);
48
		$TAKMetaData = $this->fread(4); //read Metadata Block Header
49
		$objtype = getid3_lib::BigEndian2Int(substr($TAKMetaData, 0, 1)); //Metadata Block Object Type
50
		$objlength = getid3_lib::LittleEndian2Int(substr($TAKMetaData, 1, 3)); //Metadata Block Object Lenght excluding header
51
		if ($objtype == 1) { //The First Metadata Block Object must be of Type 1 (STREAMINFO)
52
			$offset += 4; //skip to Metadata Block contents
53
			$this->fseek($offset);
54
		        $TAKMetaData = $this->fread($objlength); // Get the raw Metadata Block Data
0 ignored issues
show
Bug introduced by
It seems like $objlength defined by \getid3_lib::LittleEndia...tr($TAKMetaData, 1, 3)) on line 50 can also be of type double or false; however, getid3_handler::fread() does only seem to accept integer, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
55
			$thisfile_takaudio_raw['STREAMINFO'] = getid3_lib::LittleEndian2Bin(substr($TAKMetaData, 0, $objlength - 3));
56
			$offset += $objlength; // Move to the next Metadata Block Object
57
			$thisfile_takaudio['channels'] = getid3_lib::Bin2Dec(substr($thisfile_takaudio_raw['STREAMINFO'], 1, 4)) + 1;
58
			$thisfile_takaudio['bits_per_sample'] = getid3_lib::Bin2Dec(substr($thisfile_takaudio_raw['STREAMINFO'], 5, 5)) + 8;
59
			$thisfile_takaudio['sample_rate'] = getid3_lib::Bin2Dec(substr($thisfile_takaudio_raw['STREAMINFO'], 10, 18)) + 6000;
60
			$thisfile_takaudio['samples'] = getid3_lib::Bin2Dec(substr($thisfile_takaudio_raw['STREAMINFO'], 31, 35));
61
			$thisfile_takaudio['framesize'] = self::TAKFramesizeLookup(getid3_lib::Bin2Dec(substr($thisfile_takaudio_raw['STREAMINFO'], 66, 4)));
62
			$thisfile_takaudio['codectype'] = self::TAKCodecTypeLookup(getid3_lib::Bin2Dec(substr($thisfile_takaudio_raw['STREAMINFO'], 74, 6)));
63
		} else {
64
			$this->error('Expecting Type 1 (STREAMINFO) Metadata Object header, but found Type "'.$objtype.'" Object instead');
65
			unset($info['fileformat']);
66
			return false;
67
		}
68
		$this->fseek($offset);
69
		$TAKMetaData = $this->fread(4);
70
		$objtype = getid3_lib::BigEndian2Int(substr($TAKMetaData, 0, 1));
71
		$objlength = getid3_lib::LittleEndian2Int(substr($TAKMetaData, 1, 3));
72
		while ($objtype != 0) {
73
			switch ($objtype) {
74
			case 4 :
75
				// ENCODERINFO Metadata Block
76
				$offset += 4;
77
				$this->fseek($offset);
78
		                $TAKMetaData = $this->fread($objlength);
0 ignored issues
show
Bug introduced by
It seems like $objlength can also be of type double or false; however, getid3_handler::fread() does only seem to accept integer, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
79
				$ver = getid3_lib::LittleEndian2Int(substr($TAKMetaData, 0, 3));
80
				$major = ($ver & 0xff0000) >> 16;
81
				$minor = ($ver & 0x00ff00) >> 8;
82
				$revision= $ver & 0x0000ff;
83
				$thisfile_takaudio['version'] = 'TAK V '.$major.'.'.$minor.'.'.$revision;
84
				$thisfile_takaudio['profile'] = self::TAKProfileLookup(getid3_lib::BigEndian2Int(substr($TAKMetaData, 3, 1)));
85
				$offset += $objlength;
86
				break;
87
			case 6 :
88
				// MD5 Checksum Metadata Block
89
				$offset += 4;
90
				$this->fseek($offset);
91
		                $TAKMetaData = $this->fread($objlength);
0 ignored issues
show
Bug introduced by
It seems like $objlength can also be of type double or false; however, getid3_handler::fread() does only seem to accept integer, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
92
				$thisfile_takaudio_raw['MD5Data'] = substr($TAKMetaData, 0, 16);
93
				$offset += $objlength;
94
				break;
95
			case 7 :
96
				// LASTFRAME Metadata Block
97
				$offset += 4;
98
				$this->fseek($offset);
99
		                $TAKMetaData = $this->fread($objlength);
0 ignored issues
show
Bug introduced by
It seems like $objlength can also be of type double or false; however, getid3_handler::fread() does only seem to accept integer, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
100
				$thisfile_takaudio['lastframe_pos'] = getid3_lib::LittleEndian2Int(substr($TAKMetaData, 0, 5));
101
				$thisfile_takaudio['last_frame_size'] = getid3_lib::LittleEndian2Int(substr($TAKMetaData, 5, 3));
102
				$offset += $objlength;
103
				break;
104
			case 3 :
105
				// ORIGINALFILEDATA Metadata Block
106
				$offset += 4;
107
				$this->fseek($offset);
108
		                $TAKMetaData = $this->fread($objlength);
0 ignored issues
show
Bug introduced by
It seems like $objlength can also be of type double or false; however, getid3_handler::fread() does only seem to accept integer, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
109
				$headersize = getid3_lib::LittleEndian2Int(substr($TAKMetaData, 0, 3));
110
				$footersize = getid3_lib::LittleEndian2Int(substr($TAKMetaData, 3, 3));
111
				if ($headersize) $thisfile_takaudio_raw['header_data'] = substr($TAKMetaData, 6, $headersize);
112
				if ($footersize) $thisfile_takaudio_raw['footer_data'] = substr($TAKMetaData, $headersize, $footersize);
113
				$offset += $objlength;
114
				break;
115
			default :
116
				// PADDING or SEEKTABLE Metadata Block. Just skip it
117
				$offset += 4;
118
				$this->fseek($offset);
119
		                $TAKMetaData = $this->fread($objlength);
0 ignored issues
show
Bug introduced by
It seems like $objlength can also be of type double or false; however, getid3_handler::fread() does only seem to accept integer, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
Unused Code introduced by
$TAKMetaData 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...
120
				$offset += $objlength;
121
				break;
122
			}
123
			$this->fseek($offset);
124
			$TAKMetaData = $this->fread(4);
125
			$objtype = getid3_lib::BigEndian2Int(substr($TAKMetaData, 0, 1));
126
			$objlength = getid3_lib::LittleEndian2Int(substr($TAKMetaData, 1, 3));
127
		}
128
		// Finished all Metadata Blocks. So update $info['avdataoffset'] because next block is the first Audio data block
129
		$info['avdataoffset'] = $offset;
130
131
		$info['audio']['channels'] = $thisfile_takaudio['channels'];
132
		if ($thisfile_takaudio['sample_rate'] == 0) {
133
			$this->error('Corrupt TAK file: samplerate == zero');
134
			return false;
135
		}
136
		$info['audio']['sample_rate'] = $thisfile_takaudio['sample_rate'];
137
		$thisfile_takaudio['playtime'] = $thisfile_takaudio['samples'] / $thisfile_takaudio['sample_rate'];
138
		if ($thisfile_takaudio['playtime'] == 0) {
139
			$this->error('Corrupt TAK file: playtime == zero');
140
			return false;
141
		}
142
		$info['playtime_seconds'] = $thisfile_takaudio['playtime'];
143
		$thisfile_takaudio['compressed_size'] = $info['avdataend'] - $info['avdataoffset'];
144
		$thisfile_takaudio['uncompressed_size'] = $thisfile_takaudio['samples'] * $thisfile_takaudio['channels'] * ($thisfile_takaudio['bits_per_sample'] / 8);
145
		if ($thisfile_takaudio['uncompressed_size'] == 0) {
146
			$this->error('Corrupt TAK file: uncompressed_size == zero');
147
			return false;
148
		}
149
		$thisfile_takaudio['compression_ratio'] = $thisfile_takaudio['compressed_size'] / ($thisfile_takaudio['uncompressed_size'] + $offset);
150
		$thisfile_takaudio['bitrate'] = (($thisfile_takaudio['samples'] * $thisfile_takaudio['channels'] * $thisfile_takaudio['bits_per_sample']) / $thisfile_takaudio['playtime']) * $thisfile_takaudio['compression_ratio'];
151
		$info['audio']['bitrate'] = $thisfile_takaudio['bitrate'];
152
153 View Code Duplication
		if (empty($thisfile_takaudio_raw['MD5Data'])) {
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...
154
			//$this->warning('MD5Data is not set');
155
		} elseif ($thisfile_takaudio_raw['MD5Data'] === str_repeat("\x00", 16)) {
156
			//$this->warning('MD5Data is null');
157
		} else {
158
			$info['md5_data_source'] = '';
159
			$md5 = $thisfile_takaudio_raw['MD5Data'];
160
			for ($i = 0; $i < strlen($md5); $i++) {
161
				$info['md5_data_source'] .= str_pad(dechex(ord($md5[$i])), 2, '00', STR_PAD_LEFT);
162
			}
163
			if (!preg_match('/^[0-9a-f]{32}$/', $info['md5_data_source'])) {
164
				unset($info['md5_data_source']);
165
			}
166
		}
167
168
		foreach (array('bits_per_sample', 'version', 'profile') as $key) {
169
			if (!empty($thisfile_takaudio[$key])) {
170
				$info['audio'][$key] = $thisfile_takaudio[$key];
171
			}
172
		}
173
174
		return true;
175
	}
176
177
	public function TAKFramesizeLookup($framesize) {
178
		static $TAKFramesizeLookup = array(
179
			0     => '94 ms',
180
			1     => '125 ms',
181
			2     => '188 ms',
182
			3     => '250 ms',
183
			4     => '4096 samples',
184
			5     => '8192 samples',
185
			6     => '16384 samples',
186
			7     => '512 samples',
187
			8     => '1024 samples',
188
			9     => '2048 samples'
189
		);
190
		return (isset($TAKFramesizeLookup[$framesize]) ? $TAKFramesizeLookup[$framesize] : 'invalid');
191
	}
192
	public function TAKCodecTypeLookup($code) {
193
		static $TAKCodecTypeLookup = array(
194
			0     => 'Integer 24 bit (TAK 1.0)',
195
			1     => 'Experimental!',
196
			2     => 'Integer 24 bit (TAK 2.0)',
197
			3     => 'LossyWav (TAK 2.1)',
198
			4     => 'Integer 24 bit MC (TAK 2.2)'
199
		);
200
		return (isset($TAKCodecTypeLookup[$code]) ? $TAKCodecTypeLookup[$code] : 'invalid');
201
	}
202
	public function TAKProfileLookup($code) {
203
		$out ='-p';
204
		$evaluation = ($code & 0xf0) >> 4;
205
		$compresion = $code & 0x0f;
206
		static $TAKEvaluationLookup = array(
207
			0     => '',
208
			1     => 'e',
209
			2     => 'm'
210
		);
211
		return (isset($TAKEvaluationLookup[$evaluation]) ? $out .= $compresion . $TAKEvaluationLookup[$evaluation] : 'invalid');
212
	}
213
214
}
215