Skip to content

Commit e1450a6

Browse files
authored
Merge pull request #427 from StudioMaX/2.0-with-1.9.23-202310190849
Sync 2.0 with 1.9.23-202310190849
2 parents 4e7aca9 + 5a3f29c commit e1450a6

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+718
-544
lines changed

.github/workflows/continuous-integration.yml

+4-3
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,9 @@ jobs:
2121
- "8.0"
2222
- "8.1"
2323
- "8.2"
24+
- "8.3"
2425
steps:
25-
- uses: "actions/checkout@v2"
26+
- uses: "actions/checkout@v3"
2627
- uses: "shivammathur/setup-php@v2"
2728
with:
2829
php-version: "${{ matrix.php-version }}"
@@ -36,11 +37,11 @@ jobs:
3637
name: "Static Analysis"
3738
runs-on: "ubuntu-latest"
3839
steps:
39-
- uses: "actions/checkout@v2"
40+
- uses: "actions/checkout@v3"
4041
- uses: "shivammathur/setup-php@v2"
4142
with:
4243
php-version: "7.4"
43-
tools: "phpstan:0.12.99"
44+
tools: "phpstan:1.8.11"
4445
coverage: "none"
4546
- uses: "ramsey/composer-install@v2"
4647
- name: "Run PHPStan"

LICENSE.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,4 @@ Mozilla MPL
2424

2525
getID3 Commercial License
2626
-------------------------
27-
* [gCL](http://getid3.org/#gCL) (payment required)
27+
* [gCL](http://getid3.org/#gCL) (no longer available, existing licenses remain valid)

changelog.txt

+13
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,19 @@
1818
Version History
1919
===============
2020

21+
1.9.23: [2023-10-19] James Heinrich :: 1.9.23-202310190849
22+
» add detection support for 7-zip archives
23+
* #424 RIFF Undefined index "data"
24+
* #421 tag.xmp remove GLOBALS
25+
* #419 Quicktime Undefined index "time_scale"
26+
* #418 tag.xmp zero-length fread
27+
* #414 Quicktime bitrate for mp4 audio
28+
* #413 Quicktime audio metadata
29+
* #410 MPEG-1 pixel aspect ratio
30+
* #407 PHP 8.1 compatibility
31+
* #404 guard against division by zero
32+
* #402 remove utf8_encode/utf8_decode
33+
2134
1.9.22: [2022-09-29] James Heinrich :: 1.9.22-202207161647
2235
* bugfix #387 fails to detect h265 video codec (QuickTime)
2336
* bugfix #385 Quicktime extended atom size

demos/demo.browse.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -460,7 +460,7 @@ function table_var_dump($variable, $wrap_in_td=false, $encoding='') {
460460
global $FileSystemEncoding;
461461
$encoding = ($encoding ? $encoding : $FileSystemEncoding);
462462
$returnstring = '';
463-
switch (gettype($variable)) {
463+
switch (strtolower(gettype($variable))) {
464464
case 'array':
465465
$returnstring .= ($wrap_in_td ? '<td>' : '');
466466
$returnstring .= '<table class="dump" cellspacing="0" cellpadding="2">';

demos/demo.mp3header.php

+29-32
Original file line numberDiff line numberDiff line change
@@ -705,7 +705,7 @@ function RoughTranslateUnicodeToASCII($rawdata, $frame_textencoding) {
705705
break;
706706

707707
case 3: // UTF-8 encoded Unicode. Terminated with $00.
708-
$asciidata = utf8_decode($rawdata);
708+
$asciidata = utf8_to_iso8859_1($rawdata);
709709
break;
710710

711711
case 255: // Unicode, Big-Endian. Terminated with $00 00.
@@ -929,43 +929,40 @@ function image_type_to_mime_type($imagetypeid) {
929929
}
930930
}
931931

932-
if (!function_exists('utf8_decode')) {
933-
// PHP has this function built-in if it's configured with the --with-xml option
934-
// This version of the function is only provided in case XML isn't installed
935-
function utf8_decode($utf8text) {
936-
// http://www.php.net/manual/en/function.utf8-encode.php
937-
// bytes bits representation
938-
// 1 7 0bbbbbbb
939-
// 2 11 110bbbbb 10bbbbbb
940-
// 3 16 1110bbbb 10bbbbbb 10bbbbbb
941-
// 4 21 11110bbb 10bbbbbb 10bbbbbb 10bbbbbb
942-
943-
$utf8length = strlen($utf8text);
944-
$decodedtext = '';
945-
for ($i = 0; $i < $utf8length; $i++) {
946-
if ((ord($utf8text[$i]) & 0x80) == 0) {
947-
$decodedtext .= $utf8text[$i];
948-
} elseif ((ord($utf8text[$i]) & 0xF0) == 0xF0) {
949-
$decodedtext .= '?';
950-
$i += 3;
951-
} elseif ((ord($utf8text[$i]) & 0xE0) == 0xE0) {
932+
function utf8_to_iso8859_1($utf8text) {
933+
// http://www.php.net/manual/en/function.utf8-encode.php
934+
// bytes bits representation
935+
// 1 7 0bbbbbbb
936+
// 2 11 110bbbbb 10bbbbbb
937+
// 3 16 1110bbbb 10bbbbbb 10bbbbbb
938+
// 4 21 11110bbb 10bbbbbb 10bbbbbb 10bbbbbb
939+
940+
$utf8length = strlen($utf8text);
941+
$decodedtext = '';
942+
for ($i = 0; $i < $utf8length; $i++) {
943+
if ((ord($utf8text[$i]) & 0x80) == 0) {
944+
$decodedtext .= $utf8text[$i];
945+
} elseif ((ord($utf8text[$i]) & 0xF0) == 0xF0) {
946+
$decodedtext .= '?';
947+
$i += 3;
948+
} elseif ((ord($utf8text[$i]) & 0xE0) == 0xE0) {
949+
$decodedtext .= '?';
950+
$i += 2;
951+
} elseif ((ord($utf8text[$i]) & 0xC0) == 0xC0) {
952+
// 2 11 110bbbbb 10bbbbbb
953+
$decodedchar = Bin2Dec(substr(Dec2Bin(ord($utf8text[$i])), 3, 5).substr(Dec2Bin(ord($utf8text[($i + 1)])), 2, 6));
954+
if ($decodedchar <= 255) {
955+
$decodedtext .= chr($decodedchar);
956+
} else {
952957
$decodedtext .= '?';
953-
$i += 2;
954-
} elseif ((ord($utf8text[$i]) & 0xC0) == 0xC0) {
955-
// 2 11 110bbbbb 10bbbbbb
956-
$decodedchar = Bin2Dec(substr(Dec2Bin(ord($utf8text[$i])), 3, 5).substr(Dec2Bin(ord($utf8text[($i + 1)])), 2, 6));
957-
if ($decodedchar <= 255) {
958-
$decodedtext .= chr($decodedchar);
959-
} else {
960-
$decodedtext .= '?';
961-
}
962-
$i += 1;
963958
}
959+
$i += 1;
964960
}
965-
return $decodedtext;
966961
}
962+
return $decodedtext;
967963
}
968964

965+
969966
if (!function_exists('DateMac2Unix')) {
970967
function DateMac2Unix($macdate) {
971968
// Macintosh timestamp: seconds since 00:00h January 1, 1904

readme.txt

+2-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ GNU LGPL: https://gnu.org/licenses/lgpl.html (v3)
2020

2121
Mozilla MPL: https://www.mozilla.org/MPL/2.0/ (v2)
2222

23-
getID3 Commercial License: https://www.getid3.org/#gCL (payment required)
23+
getID3 Commercial License: https://www.getid3.org/#gCL
24+
(no longer available, existing licenses remain valid)
2425

2526
*****************************************************************
2627
*****************************************************************

src/GetID3.php

+11-2
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,7 @@ class GetID3
319319
*/
320320
protected $startup_warning = '';
321321

322-
const VERSION = '2.0.x-202207161647';
322+
const VERSION = '2.0.x-202310190849';
323323
const FREAD_BUFFER_SIZE = 32768;
324324

325325
const ATTACHMENTS_NONE = false;
@@ -1253,6 +1253,15 @@ public function GetFileFormatArray() {
12531253
'fail_ape' => 'ERROR',
12541254
),
12551255

1256+
// XZ - data - XZ compressed data
1257+
'7zip' => array(
1258+
'pattern' => '^7z\\xBC\\xAF\\x27\\x1C',
1259+
'module' => 'Archive\\SevenZip',
1260+
'mime_type' => 'application/x-7z-compressed',
1261+
'fail_id3' => 'ERROR',
1262+
'fail_ape' => 'ERROR',
1263+
),
1264+
12561265

12571266
// Misc other formats
12581267

@@ -1750,7 +1759,7 @@ public function CalculateCompressionRatioVideo() {
17501759
}
17511760
$BitrateUncompressed = $this->info['video']['resolution_x'] * $this->info['video']['resolution_y'] * $this->info['video']['bits_per_sample'] * $FrameRate;
17521761

1753-
$this->info['video']['compression_ratio'] = $BitrateCompressed / $BitrateUncompressed;
1762+
$this->info['video']['compression_ratio'] = Utils::SafeDiv($BitrateCompressed, $BitrateUncompressed, 1);
17541763
return true;
17551764
}
17561765

src/Module/Archive/Hpk.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public function Analyze() {
4444
$info['hpk']['header']['fragmented_filesystem_offset'] = Utils::LittleEndian2Int(substr($HPKheader, 28, 4));
4545
$info['hpk']['header']['fragmented_filesystem_length'] = Utils::LittleEndian2Int(substr($HPKheader, 32, 4));
4646

47-
$info['hpk']['header']['filesystem_entries'] = $info['hpk']['header']['fragmented_filesystem_length'] / ($info['hpk']['header']['fragments_per_file'] * 8);
47+
$info['hpk']['header']['filesystem_entries'] = Utils::SafeDiv($info['hpk']['header']['fragmented_filesystem_length'], $info['hpk']['header']['fragments_per_file'] * 8);
4848
$this->fseek($info['hpk']['header']['fragmented_filesystem_offset']);
4949
for ($i = 0; $i < $info['hpk']['header']['filesystem_entries']; $i++) {
5050
$offset = Utils::LittleEndian2Int($this->fread(4));

src/Module/Archive/SevenZip.php

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<?php
2+
3+
namespace JamesHeinrich\GetID3\Module\Archive;
4+
5+
use JamesHeinrich\GetID3\Module\Handler;
6+
use JamesHeinrich\GetID3\Utils;
7+
8+
/////////////////////////////////////////////////////////////////
9+
/// getID3() by James Heinrich <[email protected]> //
10+
// available at https://github.com/JamesHeinrich/getID3 //
11+
// or https://www.getid3.org //
12+
// or http://getid3.sourceforge.net //
13+
// see readme.txt for more details //
14+
/////////////////////////////////////////////////////////////////
15+
// //
16+
// module.archive.7zip.php //
17+
// module for analyzing 7zip files //
18+
// ///
19+
/////////////////////////////////////////////////////////////////
20+
21+
class SevenZip extends Handler
22+
{
23+
/**
24+
* @return bool
25+
*/
26+
public function Analyze() {
27+
$info = &$this->getid3->info;
28+
29+
$this->fseek($info['avdataoffset']);
30+
$z7header = $this->fread(32);
31+
32+
// https://py7zr.readthedocs.io/en/latest/archive_format.html
33+
$info['7zip']['header']['magic'] = substr($z7header, 0, 6);
34+
if ($info['7zip']['header']['magic'] != '7z'."\xBC\xAF\x27\x1C") {
35+
$this->error('Invalid 7zip stream header magic (expecting 37 7A BC AF 27 1C, found '.Utils::PrintHexBytes($info['7zip']['header']['magic']).') at offset '.$info['avdataoffset']);
36+
return false;
37+
}
38+
$info['fileformat'] = '7zip';
39+
40+
$info['7zip']['header']['version_major'] = Utils::LittleEndian2Int(substr($z7header, 6, 1)); // always 0x00 (?)
41+
$info['7zip']['header']['version_minor'] = Utils::LittleEndian2Int(substr($z7header, 7, 1)); // always 0x04 (?)
42+
$info['7zip']['header']['start_header_crc'] = Utils::LittleEndian2Int(substr($z7header, 8, 4));
43+
$info['7zip']['header']['next_header_offset'] = Utils::LittleEndian2Int(substr($z7header, 12, 8));
44+
$info['7zip']['header']['next_header_size'] = Utils::LittleEndian2Int(substr($z7header, 20, 8));
45+
$info['7zip']['header']['next_header_crc'] = Utils::LittleEndian2Int(substr($z7header, 28, 4));
46+
47+
$this->error('7zip parsing not enabled in this version of getID3() ['.$this->getid3->version().']');
48+
return false;
49+
50+
}
51+
52+
}

src/Module/Audio/Amr.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ public function Analyze() {
6363
} while (strlen($buffer) > 0);
6464

6565
$info['playtime_seconds'] = array_sum($thisfile_amr['frame_mode_count']) * 0.020; // each frame contain 160 samples and is 20 milliseconds long
66-
$info['audio']['bitrate'] = (8 * ($info['avdataend'] - $info['avdataoffset'])) / $info['playtime_seconds']; // bitrate could be calculated from average bitrate by distributation of frame types. That would give effective audio bitrate, this gives overall file bitrate which will be a little bit higher since every frame will waste 8 bits for header, plus a few bits for octet padding
66+
$info['audio']['bitrate'] = Utils::SafeDiv(8 * ($info['avdataend'] - $info['avdataoffset']), $info['playtime_seconds']); // bitrate could be calculated from average bitrate by distributation of frame types. That would give effective audio bitrate, this gives overall file bitrate which will be a little bit higher since every frame will waste 8 bits for header, plus a few bits for octet padding
6767
$info['bitrate'] = $info['audio']['bitrate'];
6868

6969
return true;

src/Module/Audio/Au.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,8 @@ public function Analyze() {
6969
$this->warning('Possible truncated file - expecting "'.$thisfile_au['data_size'].'" bytes of audio data, only found '.($info['avdataend'] - $info['avdataoffset']).' bytes"');
7070
}
7171

72-
$info['playtime_seconds'] = $thisfile_au['data_size'] / ($thisfile_au['sample_rate'] * $thisfile_au['channels'] * ($thisfile_au['used_bits_per_sample'] / 8));
73-
$info['audio']['bitrate'] = ($thisfile_au['data_size'] * 8) / $info['playtime_seconds'];
72+
$info['audio']['bitrate'] = $thisfile_au['sample_rate'] * $thisfile_au['channels'] * $thisfile_au['used_bits_per_sample'];
73+
$info['playtime_seconds'] = Utils::SafeDiv($thisfile_au['data_size'], $info['audio']['bitrate'] / 8);
7474

7575
return true;
7676
}

src/Module/Audio/Avr.php

+3-3
Original file line numberDiff line numberDiff line change
@@ -120,9 +120,9 @@ public function Analyze() {
120120
$info['audio']['bits_per_sample'] = $info['avr']['bits_per_sample'];
121121
$info['audio']['sample_rate'] = $info['avr']['sample_rate'];
122122
$info['audio']['channels'] = ($info['avr']['flags']['stereo'] ? 2 : 1);
123-
$info['playtime_seconds'] = ($info['avr']['sample_length'] / $info['audio']['channels']) / $info['avr']['sample_rate'];
124-
$info['audio']['bitrate'] = ($info['avr']['sample_length'] * (($info['avr']['bits_per_sample'] == 8) ? 8 : 16)) / $info['playtime_seconds'];
125-
123+
$bits_per_sample = ($info['avr']['bits_per_sample'] == 8) ? 8 : 16;
124+
$info['audio']['bitrate'] = $bits_per_sample * $info['audio']['channels'] * $info['avr']['sample_rate'];
125+
$info['playtime_seconds'] = Utils::SafeDiv($info['avr']['sample_length'] * $bits_per_sample, $info['audio']['bitrate']);
126126

127127
return true;
128128
}

src/Module/Audio/Bonk.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ public function HandleBonkTags($BonkTagName) {
156156
$info['audio']['lossless'] = $thisfile_bonk_BONK['lossless'];
157157
$info['audio']['codec'] = 'bonk';
158158

159-
$info['playtime_seconds'] = $thisfile_bonk_BONK['number_samples'] / ($thisfile_bonk_BONK['sample_rate'] * $thisfile_bonk_BONK['channels']);
159+
$info['playtime_seconds'] = Utils::SafeDiv($thisfile_bonk_BONK['number_samples'], $thisfile_bonk_BONK['sample_rate'] * $thisfile_bonk_BONK['channels']);
160160
if ($info['playtime_seconds'] > 0) {
161161
$info['audio']['bitrate'] = (($info['bonk']['dataend'] - $info['bonk']['dataoffset']) * 8) / $info['playtime_seconds'];
162162
}

src/Module/Audio/Dsdiff.php

+7-3
Original file line numberDiff line numberDiff line change
@@ -198,9 +198,13 @@ public function Analyze() {
198198
$this->fseek(1, SEEK_CUR);
199199
}
200200

201-
if ($commentkey = (($thisChunk['name'] == 'DIAR') ? 'artist' : (($thisChunk['name'] == 'DITI') ? 'title' : ''))) {
202-
@$info['dsdiff']['comments'][$commentkey][] = $thisChunk['description'];
203-
}
201+
$commentKeys = array(
202+
'DIAR' => 'artist',
203+
'DITI' => 'title'
204+
);
205+
$commentkey = $commentKeys[$thisChunk['name']];
206+
207+
$info['dsdiff']['comments'][$commentkey][] = $thisChunk['description'];
204208
break;
205209
case 'EMID': // Edited Master ID chunk
206210
if ($thisChunk['size']) {

src/Module/Audio/Dsf.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ public function Analyze() {
118118
$info['audio']['sample_rate'] = $info['dsf']['fmt']['sample_rate'];
119119
$info['audio']['channels'] = $info['dsf']['fmt']['channels'];
120120
$info['audio']['bitrate'] = $info['audio']['bits_per_sample'] * $info['audio']['sample_rate'] * $info['audio']['channels'];
121-
$info['playtime_seconds'] = ($info['dsf']['data']['data_chunk_size'] * 8) / $info['audio']['bitrate'];
121+
$info['playtime_seconds'] = Utils::SafeDiv($info['dsf']['data']['data_chunk_size'] * 8, $info['audio']['bitrate']);
122122

123123
return true;
124124
}

src/Module/Audio/Lpac.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -127,8 +127,8 @@ public function Analyze() {
127127
}
128128
}
129129

130-
$info['playtime_seconds'] = $info['lpac']['total_samples'] / $info['audio']['sample_rate'];
131-
$info['audio']['bitrate'] = (($info['avdataend'] - $info['avdataoffset']) * 8) / $info['playtime_seconds'];
130+
$info['playtime_seconds'] = Utils::SafeDiv($info['lpac']['total_samples'], $info['audio']['sample_rate']);
131+
$info['audio']['bitrate'] = Utils::SafeDiv(($info['avdataend'] - $info['avdataoffset']) * 8, $info['playtime_seconds']);
132132

133133
return true;
134134
}

src/Module/Audio/Midi.php

-2
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,6 @@ public function Analyze() {
106106
$thisfile_midi['totalticks'] = 0;
107107
$info['playtime_seconds'] = 0;
108108
$CurrentMicroSecondsPerBeat = 500000; // 120 beats per minute; 60,000,000 microseconds per minute -> 500,000 microseconds per beat
109-
$CurrentBeatsPerMinute = 120; // 120 beats per minute; 60,000,000 microseconds per minute -> 500,000 microseconds per beat
110109
$MicroSecondsPerQuarterNoteAfter = array ();
111110
$MIDIevents = array();
112111

@@ -251,7 +250,6 @@ public function Analyze() {
251250
return false;
252251
}
253252
$thisfile_midi_raw['events'][$tracknumber][$CumulativeDeltaTime]['us_qnote'] = $CurrentMicroSecondsPerBeat;
254-
$CurrentBeatsPerMinute = (1000000 / $CurrentMicroSecondsPerBeat) * 60;
255253
$MicroSecondsPerQuarterNoteAfter[$CumulativeDeltaTime] = $CurrentMicroSecondsPerBeat;
256254
$TicksAtCurrentBPM = 0;
257255
break;

0 commit comments

Comments
 (0)