<?php
+
/////////////////////////////////////////////////////////////////
/// getID3() by James Heinrich <info@getid3.org> //
-// available at http://getid3.sourceforge.net //
-// or http://www.getid3.org //
-// also https://github.com/JamesHeinrich/getID3 //
-/////////////////////////////////////////////////////////////////
-// See readme.txt for more details //
+// available at https://github.com/JamesHeinrich/getID3 //
+// or https://www.getid3.org //
+// or http://getid3.sourceforge.net //
+// see readme.txt for more details //
/////////////////////////////////////////////////////////////////
/// //
// module.tag.id3v2.php //
{
public $StartingOffset = 0;
+ /**
+ * @return bool
+ */
public function Analyze() {
$info = &$this->getid3->info;
}
break; // skip rest of ID3v2 header
}
+ $frame_header = null;
+ $frame_name = null;
+ $frame_size = null;
+ $frame_flags = null;
if ($id3v2_majorversion == 2) {
// Frame ID $xx xx xx (three characters)
// Size $xx xx xx (24-bit integer)
$thisfile_id3v2['minorversion_footer'] = ord($footer{4});
}
if ($thisfile_id3v2['majorversion_footer'] <= 4) {
- $id3_flags = ord(substr($footer{5}));
+ $id3_flags = ord($footer{5});
$thisfile_id3v2_flags['unsynch_footer'] = (bool) ($id3_flags & 0x80);
$thisfile_id3v2_flags['extfoot_footer'] = (bool) ($id3_flags & 0x40);
$thisfile_id3v2_flags['experim_footer'] = (bool) ($id3_flags & 0x20);
return true;
}
-
+ /**
+ * @param string $genrestring
+ *
+ * @return array
+ */
public function ParseID3v2GenreString($genrestring) {
// Parse genres into arrays of genreName and genreID
// ID3v2.2.x, ID3v2.3.x: '(21)' or '(4)Eurodisco' or '(51)(39)' or '(55)((I think...)'
foreach ($genre_elements as $element) {
$element = trim($element);
if ($element) {
- if (preg_match('#^[0-9]{1,3}#', $element)) {
+ if (preg_match('#^[0-9]{1,3}$#', $element)) {
$clean_genres[] = getid3_id3v1::LookupGenreName($element);
} else {
$clean_genres[] = str_replace('((', '(', $element);
return $clean_genres;
}
-
+ /**
+ * @param array $parsedFrame
+ *
+ * @return bool
+ */
public function ParseID3v2Frame(&$parsedFrame) {
// shortcuts
$parsedFrame['encodingid'] = $frame_textencoding;
$parsedFrame['encoding'] = $this->TextEncodingNameLookup($frame_textencoding);
- $parsedFrame['url'] = $frame_urldata;
- $parsedFrame['description'] = $frame_description;
+ $parsedFrame['url'] = $frame_urldata; // always ISO-8859-1
+ $parsedFrame['description'] = $frame_description; // according to the frame text encoding
if (!empty($parsedFrame['framenameshort']) && $parsedFrame['url']) {
- $info['id3v2']['comments'][$parsedFrame['framenameshort']][] = getid3_lib::iconv_fallback($parsedFrame['encoding'], $info['id3v2']['encoding'], $parsedFrame['url']);
+ $info['id3v2']['comments'][$parsedFrame['framenameshort']][] = getid3_lib::iconv_fallback('ISO-8859-1', $info['id3v2']['encoding'], $parsedFrame['url']);
}
unset($parsedFrame['data']);
// described in 4.3.2.>
// URL <text string>
- $parsedFrame['url'] = trim($parsedFrame['data']);
+ $parsedFrame['url'] = trim($parsedFrame['data']); // always ISO-8859-1
if (!empty($parsedFrame['framenameshort']) && $parsedFrame['url']) {
- $info['id3v2']['comments'][$parsedFrame['framenameshort']][] = $parsedFrame['url'];
+ $info['id3v2']['comments'][$parsedFrame['framenameshort']][] = getid3_lib::iconv_fallback('ISO-8859-1', $info['id3v2']['encoding'], $parsedFrame['url']);
}
unset($parsedFrame['data']);
$parsedFrame['encoding'] = $this->TextEncodingNameLookup($parsedFrame['encodingid']);
$parsedFrame['data_raw'] = (string) substr($parsedFrame['data'], $frame_offset);
- // http://www.getid3.org/phpBB3/viewtopic.php?t=1369
+ // https://www.getid3.org/phpBB3/viewtopic.php?t=1369
// "this tag typically contains null terminated strings, which are associated in pairs"
// "there are users that use the tag incorrectly"
$IPLS_parts = array();
$parsedFrame['bitsforbytesdeviation'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], 8, 1));
$parsedFrame['bitsformsdeviation'] = getid3_lib::BigEndian2Int(substr($parsedFrame['data'], 9, 1));
$parsedFrame['data'] = substr($parsedFrame['data'], 10);
+ $deviationbitstream = '';
while ($frame_offset < strlen($parsedFrame['data'])) {
$deviationbitstream .= getid3_lib::BigEndian2Bin(substr($parsedFrame['data'], $frame_offset++, 1));
}
$parsedFrame['encoding'] = $this->TextEncodingNameLookup($frame_textencoding);
if ($id3v2_majorversion == 2) {
- $parsedFrame['imagetype'] = $frame_imagetype;
+ $parsedFrame['imagetype'] = isset($frame_imagetype) ? $frame_imagetype : null;
} else {
- $parsedFrame['mime'] = $frame_mimetype;
+ $parsedFrame['mime'] = isset($frame_mimetype) ? $frame_mimetype : null;
}
$parsedFrame['picturetypeid'] = $frame_picturetype;
$parsedFrame['picturetype'] = $this->APICPictureTypeLookup($frame_picturetype);
$imageinfo = array();
if ($imagechunkcheck = getid3_lib::GetDataImageSize($parsedFrame['data'], $imageinfo)) {
if (($imagechunkcheck[2] >= 1) && ($imagechunkcheck[2] <= 3)) {
- $parsedFrame['image_mime'] = 'image/'.getid3_lib::ImageTypesLookup($imagechunkcheck[2]);
+ $parsedFrame['image_mime'] = image_type_to_mime_type($imagechunkcheck[2]);
if ($imagechunkcheck[0]) {
$parsedFrame['image_width'] = $imagechunkcheck[0];
}
unset($parsedFrame['data']);
break;
}
+ $dir = '';
if ($this->getid3->option_save_attachments === true) {
// great
/*
*/
} elseif (is_string($this->getid3->option_save_attachments)) {
$dir = rtrim(str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $this->getid3->option_save_attachments), DIRECTORY_SEPARATOR);
- if (!is_dir($dir) || !is_writable($dir)) {
+ if (!is_dir($dir) || !getID3::is_writable($dir)) {
// cannot write, skip
$this->warning('attachment at '.$frame_offset.' cannot be saved to "'.$dir.'" (not writable)');
unset($parsedFrame['data']);
// if we get this far, must be OK
if (is_string($this->getid3->option_save_attachments)) {
$destination_filename = $dir.DIRECTORY_SEPARATOR.md5($info['filenamepath']).'_'.$frame_offset;
- if (!file_exists($destination_filename) || is_writable($destination_filename)) {
+ if (!file_exists($destination_filename) || getID3::is_writable($destination_filename)) {
file_put_contents($destination_filename, $parsedFrame['data']);
} else {
$this->warning('attachment at '.$frame_offset.' cannot be saved to "'.$destination_filename.'" (not writable)');
return true;
}
-
+ /**
+ * @param string $data
+ *
+ * @return string
+ */
public function DeUnsynchronise($data) {
return str_replace("\xFF\x00", "\xFF", $data);
}
+ /**
+ * @param int $index
+ *
+ * @return string
+ */
public function LookupExtendedHeaderRestrictionsTagSizeLimits($index) {
static $LookupExtendedHeaderRestrictionsTagSizeLimits = array(
0x00 => 'No more than 128 frames and 1 MB total tag size',
return (isset($LookupExtendedHeaderRestrictionsTagSizeLimits[$index]) ? $LookupExtendedHeaderRestrictionsTagSizeLimits[$index] : '');
}
+ /**
+ * @param int $index
+ *
+ * @return string
+ */
public function LookupExtendedHeaderRestrictionsTextEncodings($index) {
static $LookupExtendedHeaderRestrictionsTextEncodings = array(
0x00 => 'No restrictions',
return (isset($LookupExtendedHeaderRestrictionsTextEncodings[$index]) ? $LookupExtendedHeaderRestrictionsTextEncodings[$index] : '');
}
+ /**
+ * @param int $index
+ *
+ * @return string
+ */
public function LookupExtendedHeaderRestrictionsTextFieldSize($index) {
static $LookupExtendedHeaderRestrictionsTextFieldSize = array(
0x00 => 'No restrictions',
return (isset($LookupExtendedHeaderRestrictionsTextFieldSize[$index]) ? $LookupExtendedHeaderRestrictionsTextFieldSize[$index] : '');
}
+ /**
+ * @param int $index
+ *
+ * @return string
+ */
public function LookupExtendedHeaderRestrictionsImageEncoding($index) {
static $LookupExtendedHeaderRestrictionsImageEncoding = array(
0x00 => 'No restrictions',
return (isset($LookupExtendedHeaderRestrictionsImageEncoding[$index]) ? $LookupExtendedHeaderRestrictionsImageEncoding[$index] : '');
}
+ /**
+ * @param int $index
+ *
+ * @return string
+ */
public function LookupExtendedHeaderRestrictionsImageSizeSize($index) {
static $LookupExtendedHeaderRestrictionsImageSizeSize = array(
0x00 => 'No restrictions',
return (isset($LookupExtendedHeaderRestrictionsImageSizeSize[$index]) ? $LookupExtendedHeaderRestrictionsImageSizeSize[$index] : '');
}
+ /**
+ * @param string $currencyid
+ *
+ * @return string
+ */
public function LookupCurrencyUnits($currencyid) {
$begin = __LINE__;
return getid3_lib::EmbeddedLookup($currencyid, $begin, __LINE__, __FILE__, 'id3v2-currency-units');
}
-
+ /**
+ * @param string $currencyid
+ *
+ * @return string
+ */
public function LookupCurrencyCountry($currencyid) {
$begin = __LINE__;
return getid3_lib::EmbeddedLookup($currencyid, $begin, __LINE__, __FILE__, 'id3v2-currency-country');
}
-
-
+ /**
+ * @param string $languagecode
+ * @param bool $casesensitive
+ *
+ * @return string
+ */
public static function LanguageLookup($languagecode, $casesensitive=false) {
if (!$casesensitive) {
return getid3_lib::EmbeddedLookup($languagecode, $begin, __LINE__, __FILE__, 'id3v2-languagecode');
}
-
+ /**
+ * @param int $index
+ *
+ * @return string
+ */
public static function ETCOEventLookup($index) {
if (($index >= 0x17) && ($index <= 0xDF)) {
return 'reserved for future use';
return (isset($EventLookup[$index]) ? $EventLookup[$index] : '');
}
+ /**
+ * @param int $index
+ *
+ * @return string
+ */
public static function SYTLContentTypeLookup($index) {
static $SYTLContentTypeLookup = array(
0x00 => 'other',
return (isset($SYTLContentTypeLookup[$index]) ? $SYTLContentTypeLookup[$index] : '');
}
+ /**
+ * @param int $index
+ * @param bool $returnarray
+ *
+ * @return array|string
+ */
public static function APICPictureTypeLookup($index, $returnarray=false) {
static $APICPictureTypeLookup = array(
0x00 => 'Other',
return (isset($APICPictureTypeLookup[$index]) ? $APICPictureTypeLookup[$index] : '');
}
+ /**
+ * @param int $index
+ *
+ * @return string
+ */
public static function COMRReceivedAsLookup($index) {
static $COMRReceivedAsLookup = array(
0x00 => 'Other',
return (isset($COMRReceivedAsLookup[$index]) ? $COMRReceivedAsLookup[$index] : '');
}
+ /**
+ * @param int $index
+ *
+ * @return string
+ */
public static function RVA2ChannelTypeLookup($index) {
static $RVA2ChannelTypeLookup = array(
0x00 => 'Other',
return (isset($RVA2ChannelTypeLookup[$index]) ? $RVA2ChannelTypeLookup[$index] : '');
}
+ /**
+ * @param string $framename
+ *
+ * @return string
+ */
public static function FrameNameLongLookup($framename) {
$begin = __LINE__;
TYER Year
UFI Unique file identifier
UFID Unique file identifier
- ULT Unsychronised lyric/text transcription
+ ULT Unsynchronised lyric/text transcription
USER Terms of use
USLT Unsynchronised lyric/text transcription
WAF Official audio file webpage
// from http://privatewww.essex.ac.uk/~djmrob/replaygain/file_format_id3v2.html
}
-
+ /**
+ * @param string $framename
+ *
+ * @return string
+ */
public static function FrameNameShortLookup($framename) {
$begin = __LINE__;
TYER year
UFI unique_file_identifier
UFID unique_file_identifier
- ULT unsychronised_lyric
+ ULT unsynchronised_lyric
USER terms_of_use
USLT unsynchronised_lyric
WAF url_file
return getid3_lib::EmbeddedLookup($framename, $begin, __LINE__, __FILE__, 'id3v2-framename_short');
}
+ /**
+ * @param string $encoding
+ *
+ * @return string
+ */
public static function TextEncodingTerminatorLookup($encoding) {
// http://www.id3.org/id3v2.4.0-structure.txt
// Frames that allow different types of text encoding contains a text encoding description byte. Possible encodings:
return (isset($TextEncodingTerminatorLookup[$encoding]) ? $TextEncodingTerminatorLookup[$encoding] : "\x00");
}
+ /**
+ * @param int $encoding
+ *
+ * @return string
+ */
public static function TextEncodingNameLookup($encoding) {
// http://www.id3.org/id3v2.4.0-structure.txt
// Frames that allow different types of text encoding contains a text encoding description byte. Possible encodings:
return (isset($TextEncodingNameLookup[$encoding]) ? $TextEncodingNameLookup[$encoding] : 'ISO-8859-1');
}
+ /**
+ * @param string $framename
+ * @param int $id3v2majorversion
+ *
+ * @return bool|int
+ */
public static function IsValidID3v2FrameName($framename, $id3v2majorversion) {
switch ($id3v2majorversion) {
case 2:
return false;
}
+ /**
+ * @param string $numberstring
+ * @param bool $allowdecimal
+ * @param bool $allownegative
+ *
+ * @return bool
+ */
public static function IsANumber($numberstring, $allowdecimal=false, $allownegative=false) {
for ($i = 0; $i < strlen($numberstring); $i++) {
if ((chr($numberstring{$i}) < chr('0')) || (chr($numberstring{$i}) > chr('9'))) {
return true;
}
+ /**
+ * @param string $datestamp
+ *
+ * @return bool
+ */
public static function IsValidDateStampString($datestamp) {
if (strlen($datestamp) != 8) {
return false;
return true;
}
+ /**
+ * @param int $majorversion
+ *
+ * @return int
+ */
public static function ID3v2HeaderLength($majorversion) {
return (($majorversion == 2) ? 6 : 10);
}
+ /**
+ * @param string $frame_name
+ *
+ * @return string|false
+ */
public static function ID3v22iTunesBrokenFrameName($frame_name) {
// iTunes (multiple versions) has been known to write ID3v2.3 style frames
// but use ID3v2.2 frame names, right-padded using either [space] or [null]