--- a/wp/wp-includes/ID3/module.audio-video.riff.php Wed Sep 21 18:19:35 2022 +0200
+++ b/wp/wp-includes/ID3/module.audio-video.riff.php Tue Sep 27 16:37:53 2022 +0200
@@ -56,6 +56,7 @@
$thisfile_riff_video = &$thisfile_riff['video'];
$thisfile_riff_WAVE = array();
+ $Original = array();
$Original['avdataoffset'] = $info['avdataoffset'];
$Original['avdataend'] = $info['avdataend'];
@@ -296,9 +297,18 @@
// shortcut
$thisfile_riff_WAVE_bext_0 = &$thisfile_riff_WAVE['bext'][0];
- $thisfile_riff_WAVE_bext_0['title'] = trim(substr($thisfile_riff_WAVE_bext_0['data'], 0, 256));
- $thisfile_riff_WAVE_bext_0['author'] = trim(substr($thisfile_riff_WAVE_bext_0['data'], 256, 32));
- $thisfile_riff_WAVE_bext_0['reference'] = trim(substr($thisfile_riff_WAVE_bext_0['data'], 288, 32));
+ $thisfile_riff_WAVE_bext_0['title'] = substr($thisfile_riff_WAVE_bext_0['data'], 0, 256);
+ $thisfile_riff_WAVE_bext_0['author'] = substr($thisfile_riff_WAVE_bext_0['data'], 256, 32);
+ $thisfile_riff_WAVE_bext_0['reference'] = substr($thisfile_riff_WAVE_bext_0['data'], 288, 32);
+ foreach (array('title','author','reference') as $bext_key) {
+ // Some software (notably Logic Pro) may not blank existing data before writing a null-terminated string to the offsets
+ // assigned for text fields, resulting in a null-terminated string (or possibly just a single null) followed by garbage
+ // Keep only string as far as first null byte, discard rest of fixed-width data
+ // https://github.com/JamesHeinrich/getID3/issues/263
+ $null_terminator_offset = strpos($thisfile_riff_WAVE_bext_0[$bext_key], "\x00");
+ $thisfile_riff_WAVE_bext_0[$bext_key] = substr($thisfile_riff_WAVE_bext_0[$bext_key], 0, $null_terminator_offset);
+ }
+
$thisfile_riff_WAVE_bext_0['origin_date'] = substr($thisfile_riff_WAVE_bext_0['data'], 320, 10);
$thisfile_riff_WAVE_bext_0['origin_time'] = substr($thisfile_riff_WAVE_bext_0['data'], 330, 8);
$thisfile_riff_WAVE_bext_0['time_reference'] = getid3_lib::LittleEndian2Int(substr($thisfile_riff_WAVE_bext_0['data'], 338, 8));
@@ -307,6 +317,7 @@
$thisfile_riff_WAVE_bext_0['coding_history'] = explode("\r\n", trim(substr($thisfile_riff_WAVE_bext_0['data'], 601)));
if (preg_match('#^([0-9]{4}).([0-9]{2}).([0-9]{2})$#', $thisfile_riff_WAVE_bext_0['origin_date'], $matches_bext_date)) {
if (preg_match('#^([0-9]{2}).([0-9]{2}).([0-9]{2})$#', $thisfile_riff_WAVE_bext_0['origin_time'], $matches_bext_time)) {
+ $bext_timestamp = array();
list($dummy, $bext_timestamp['year'], $bext_timestamp['month'], $bext_timestamp['day']) = $matches_bext_date;
list($dummy, $bext_timestamp['hour'], $bext_timestamp['minute'], $bext_timestamp['second']) = $matches_bext_time;
$thisfile_riff_WAVE_bext_0['origin_date_unix'] = gmmktime($bext_timestamp['hour'], $bext_timestamp['minute'], $bext_timestamp['second'], $bext_timestamp['month'], $bext_timestamp['day'], $bext_timestamp['year']);
@@ -451,7 +462,62 @@
}
}
+ if (isset($thisfile_riff_WAVE['guan'][0]['data'])) {
+ // shortcut
+ $thisfile_riff_WAVE_guan_0 = &$thisfile_riff_WAVE['guan'][0];
+ if (!empty($thisfile_riff_WAVE_guan_0['data']) && (substr($thisfile_riff_WAVE_guan_0['data'], 0, 14) == 'GUANO|Version:')) {
+ $thisfile_riff['guano'] = array();
+ foreach (explode("\n", $thisfile_riff_WAVE_guan_0['data']) as $line) {
+ if ($line) {
+ @list($key, $value) = explode(':', $line, 2);
+ if (substr($value, 0, 3) == '[{"') {
+ if ($decoded = @json_decode($value, true)) {
+ if (!empty($decoded) && (count($decoded) == 1)) {
+ $value = $decoded[0];
+ } else {
+ $value = $decoded;
+ }
+ }
+ }
+ $thisfile_riff['guano'] = array_merge_recursive($thisfile_riff['guano'], getid3_lib::CreateDeepArray($key, '|', $value));
+ }
+ }
+ // https://www.wildlifeacoustics.com/SCHEMA/GUANO.html
+ foreach ($thisfile_riff['guano'] as $key => $value) {
+ switch ($key) {
+ case 'Loc Position':
+ if (preg_match('#^([\\+\\-]?[0-9]+\\.[0-9]+) ([\\+\\-]?[0-9]+\\.[0-9]+)$#', $value, $matches)) {
+ list($dummy, $latitude, $longitude) = $matches;
+ $thisfile_riff['comments']['gps_latitude'][0] = floatval($latitude);
+ $thisfile_riff['comments']['gps_longitude'][0] = floatval($longitude);
+ $thisfile_riff['guano'][$key] = floatval($latitude).' '.floatval($longitude);
+ }
+ break;
+ case 'Loc Elevation': // Elevation/altitude above mean sea level in meters
+ $thisfile_riff['comments']['gps_altitude'][0] = floatval($value);
+ $thisfile_riff['guano'][$key] = (float) $value;
+ break;
+ case 'Filter HP': // High-pass filter frequency in kHz
+ case 'Filter LP': // Low-pass filter frequency in kHz
+ case 'Humidity': // Relative humidity as a percentage
+ case 'Length': // Recording length in seconds
+ case 'Loc Accuracy': // Estimated Position Error in meters
+ case 'Temperature Ext': // External temperature in degrees Celsius outside the recorder's housing
+ case 'Temperature Int': // Internal temperature in degrees Celsius inside the recorder's housing
+ $thisfile_riff['guano'][$key] = (float) $value;
+ break;
+ case 'Samplerate': // Recording sample rate, Hz
+ case 'TE': // Time-expansion factor. If not specified, then 1 (no time-expansion a.k.a. direct-recording) is assumed.
+ $thisfile_riff['guano'][$key] = (int) $value;
+ break;
+ }
+ }
+
+ } else {
+ $this->warning('RIFF.guan data not in expected format');
+ }
+ }
if (!isset($thisfile_audio['bitrate']) && isset($thisfile_riff_audio[$streamindex]['bitrate'])) {
$thisfile_audio['bitrate'] = $thisfile_riff_audio[$streamindex]['bitrate'];
@@ -733,6 +799,7 @@
}
if (isset($thisfile_riff['AVI ']['hdrl']['strl']['strh'][0]['data'])) {
if (is_array($thisfile_riff['AVI ']['hdrl']['strl']['strh'])) {
+ $thisfile_riff_raw_strf_strhfccType_streamindex = null;
for ($i = 0; $i < count($thisfile_riff['AVI ']['hdrl']['strl']['strh']); $i++) {
if (isset($thisfile_riff['AVI ']['hdrl']['strl']['strh'][$i]['data'])) {
$strhData = $thisfile_riff['AVI ']['hdrl']['strl']['strh'][$i]['data'];
@@ -1069,7 +1136,7 @@
if (isset($thisfile_riff[$RIFFsubtype]['ID3 '])) {
getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.tag.id3v2.php', __FILE__, true);
$getid3_temp = new getID3();
- $getid3_temp->openfile($this->getid3->filename, null, $this->getid3->fp);
+ $getid3_temp->openfile($this->getid3->filename, $this->getid3->info['filesize'], $this->getid3->fp);
$getid3_id3v2 = new getid3_id3v2($getid3_temp);
$getid3_id3v2->StartingOffset = $thisfile_riff[$RIFFsubtype]['ID3 '][0]['offset'] + 8;
if ($thisfile_riff[$RIFFsubtype]['ID3 '][0]['valid'] = $getid3_id3v2->Analyze()) {
@@ -1172,7 +1239,7 @@
getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio-video.mpeg.php', __FILE__, true);
$getid3_temp = new getID3();
- $getid3_temp->openfile($this->getid3->filename, null, $this->getid3->fp);
+ $getid3_temp->openfile($this->getid3->filename, $this->getid3->info['filesize'], $this->getid3->fp);
$getid3_mpeg = new getid3_mpeg($getid3_temp);
$getid3_mpeg->Analyze();
if (empty($getid3_temp->info['error'])) {
@@ -1258,7 +1325,7 @@
getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.tag.id3v2.php', __FILE__, true);
$getid3_temp = new getID3();
- $getid3_temp->openfile($this->getid3->filename, null, $this->getid3->fp);
+ $getid3_temp->openfile($this->getid3->filename, $this->getid3->info['filesize'], $this->getid3->fp);
$getid3_id3v2 = new getid3_id3v2($getid3_temp);
$getid3_id3v2->StartingOffset = $thisfile_riff[$RIFFsubtype]['id3 '][0]['offset'] + 8;
if ($thisfile_riff[$RIFFsubtype]['id3 '][0]['valid'] = $getid3_id3v2->Analyze()) {
@@ -1514,6 +1581,9 @@
$RIFFchunk = false;
$FoundAllChunksWeNeed = false;
+ $LISTchunkParent = null;
+ $LISTchunkMaxOffset = null;
+ $AC3syncwordBytes = pack('n', getid3_ac3::syncword); // 0x0B77 -> "\x0B\x77"
try {
$this->fseek($startoffset);
@@ -1557,7 +1627,7 @@
// MP3
if (getid3_mp3::MPEGaudioHeaderBytesValid($FirstFourBytes)) {
$getid3_temp = new getID3();
- $getid3_temp->openfile($this->getid3->filename, null, $this->getid3->fp);
+ $getid3_temp->openfile($this->getid3->filename, $this->getid3->info['filesize'], $this->getid3->fp);
$getid3_temp->info['avdataoffset'] = $this->ftell() - 4;
$getid3_temp->info['avdataend'] = $this->ftell() + $AudioChunkSize;
$getid3_mp3 = new getid3_mp3($getid3_temp, __CLASS__);
@@ -1575,11 +1645,10 @@
unset($getid3_temp, $getid3_mp3);
}
- } elseif (strpos($FirstFourBytes, getid3_ac3::syncword) === 0) {
-
+ } elseif (strpos($FirstFourBytes, $AC3syncwordBytes) === 0) {
// AC3
$getid3_temp = new getID3();
- $getid3_temp->openfile($this->getid3->filename, null, $this->getid3->fp);
+ $getid3_temp->openfile($this->getid3->filename, $this->getid3->info['filesize'], $this->getid3->fp);
$getid3_temp->info['avdataoffset'] = $this->ftell() - 4;
$getid3_temp->info['avdataend'] = $this->ftell() + $AudioChunkSize;
$getid3_ac3 = new getid3_ac3($getid3_temp);
@@ -1640,7 +1709,7 @@
// Probably is MP3 data
if (getid3_mp3::MPEGaudioHeaderBytesValid(substr($testData, 0, 4))) {
$getid3_temp = new getID3();
- $getid3_temp->openfile($this->getid3->filename, null, $this->getid3->fp);
+ $getid3_temp->openfile($this->getid3->filename, $this->getid3->info['filesize'], $this->getid3->fp);
$getid3_temp->info['avdataoffset'] = $info['avdataoffset'];
$getid3_temp->info['avdataend'] = $info['avdataend'];
$getid3_mp3 = new getid3_mp3($getid3_temp, __CLASS__);
@@ -1652,12 +1721,12 @@
unset($getid3_temp, $getid3_mp3);
}
- } elseif (($isRegularAC3 = (substr($testData, 0, 2) == getid3_ac3::syncword)) || substr($testData, 8, 2) == strrev(getid3_ac3::syncword)) {
+ } elseif (($isRegularAC3 = (substr($testData, 0, 2) == $AC3syncwordBytes)) || substr($testData, 8, 2) == strrev($AC3syncwordBytes)) {
// This is probably AC-3 data
$getid3_temp = new getID3();
if ($isRegularAC3) {
- $getid3_temp->openfile($this->getid3->filename, null, $this->getid3->fp);
+ $getid3_temp->openfile($this->getid3->filename, $this->getid3->info['filesize'], $this->getid3->fp);
$getid3_temp->info['avdataoffset'] = $info['avdataoffset'];
$getid3_temp->info['avdataend'] = $info['avdataend'];
}
@@ -1673,6 +1742,8 @@
$ac3_data .= substr($testData, 8 + $i + 1, 1);
$ac3_data .= substr($testData, 8 + $i + 0, 1);
}
+ $getid3_ac3->getid3->info['avdataoffset'] = 0;
+ $getid3_ac3->getid3->info['avdataend'] = strlen($ac3_data);
$getid3_ac3->AnalyzeString($ac3_data);
}
@@ -1691,7 +1762,7 @@
// This is probably DTS data
$getid3_temp = new getID3();
- $getid3_temp->openfile($this->getid3->filename, null, $this->getid3->fp);
+ $getid3_temp->openfile($this->getid3->filename, $this->getid3->info['filesize'], $this->getid3->fp);
$getid3_temp->info['avdataoffset'] = $info['avdataoffset'];
$getid3_dts = new getid3_dts($getid3_temp);
$getid3_dts->Analyze();
@@ -1732,6 +1803,8 @@
case 'indx':
case 'MEXT':
case 'DISP':
+ case 'wamd':
+ case 'guan':
// always read data in
case 'JUNK':
// should be: never read data in
@@ -2076,6 +2149,7 @@
*/
public static function ParseBITMAPINFOHEADER($BITMAPINFOHEADER, $littleEndian=true) {
+ $parsed = array();
$parsed['biSize'] = substr($BITMAPINFOHEADER, 0, 4); // number of bytes required by the BITMAPINFOHEADER structure
$parsed['biWidth'] = substr($BITMAPINFOHEADER, 4, 4); // width of the bitmap in pixels
$parsed['biHeight'] = substr($BITMAPINFOHEADER, 8, 4); // height of the bitmap in pixels. If biHeight is positive, the bitmap is a 'bottom-up' DIB and its origin is the lower left corner. If biHeight is negative, the bitmap is a 'top-down' DIB and its origin is the upper left corner