wp/wp-includes/ID3/module.tag.id3v1.php
changeset 16 a86126ab1dd4
parent 7 cf61fcea0001
child 19 3d72ae0968f4
--- a/wp/wp-includes/ID3/module.tag.id3v1.php	Tue Oct 22 16:11:46 2019 +0200
+++ b/wp/wp-includes/ID3/module.tag.id3v1.php	Tue Dec 15 13:49:49 2020 +0100
@@ -1,11 +1,11 @@
 <?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.id3v1.php                                        //
@@ -14,10 +14,15 @@
 //                                                            ///
 /////////////////////////////////////////////////////////////////
 
+if (!defined('GETID3_INCLUDEPATH')) { // prevent path-exposing attacks that access modules directly on public webservers
+	exit;
+}
 
 class getid3_id3v1 extends getid3_handler
 {
-
+	/**
+	 * @return bool
+	 */
 	public function Analyze() {
 		$info = &$this->getid3->info;
 
@@ -43,9 +48,9 @@
 
 			// If second-last byte of comment field is null and last byte of comment field is non-null
 			// then this is ID3v1.1 and the comment field is 28 bytes long and the 30th byte is the track number
-			if (($id3v1tag{125} === "\x00") && ($id3v1tag{126} !== "\x00")) {
-				$ParsedID3v1['track']   = ord(substr($ParsedID3v1['comment'], 29,  1));
-				$ParsedID3v1['comment'] =     substr($ParsedID3v1['comment'],  0, 28);
+			if (($id3v1tag[125] === "\x00") && ($id3v1tag[126] !== "\x00")) {
+				$ParsedID3v1['track_number'] = ord(substr($ParsedID3v1['comment'], 29,  1));
+				$ParsedID3v1['comment']      =     substr($ParsedID3v1['comment'],  0, 28);
 			}
 			$ParsedID3v1['comment'] = $this->cutfield($ParsedID3v1['comment']);
 
@@ -60,26 +65,30 @@
 			foreach ($ParsedID3v1 as $key => $value) {
 				$ParsedID3v1['comments'][$key][0] = $value;
 			}
-			// ID3v1 encoding detection hack START
-			// ID3v1 is defined as always using ISO-8859-1 encoding, but it is not uncommon to find files tagged with ID3v1 using Windows-1251 or other character sets
-			// Since ID3v1 has no concept of character sets there is no certain way to know we have the correct non-ISO-8859-1 character set, but we can guess
-			$ID3v1encoding = 'ISO-8859-1';
-			foreach ($ParsedID3v1['comments'] as $tag_key => $valuearray) {
-				foreach ($valuearray as $key => $value) {
-					if (preg_match('#^[\\x00-\\x40\\xA8\\B8\\x80-\\xFF]+$#', $value)) {
-						foreach (array('Windows-1251', 'KOI8-R') as $id3v1_bad_encoding) {
-							if (function_exists('mb_convert_encoding') && @mb_convert_encoding($value, $id3v1_bad_encoding, $id3v1_bad_encoding) === $value) {
-								$ID3v1encoding = $id3v1_bad_encoding;
-								break 3;
-							} elseif (function_exists('iconv') && @iconv($id3v1_bad_encoding, $id3v1_bad_encoding, $value) === $value) {
-								$ID3v1encoding = $id3v1_bad_encoding;
-								break 3;
+			$ID3v1encoding = $this->getid3->encoding_id3v1;
+			if ($this->getid3->encoding_id3v1_autodetect) {
+				// ID3v1 encoding detection hack START
+				// ID3v1 is defined as always using ISO-8859-1 encoding, but it is not uncommon to find files tagged with ID3v1 using Windows-1251 or other character sets
+				// Since ID3v1 has no concept of character sets there is no certain way to know we have the correct non-ISO-8859-1 character set, but we can guess
+				foreach ($ParsedID3v1['comments'] as $tag_key => $valuearray) {
+					foreach ($valuearray as $key => $value) {
+						if (preg_match('#^[\\x00-\\x40\\x80-\\xFF]+$#', $value) && !ctype_digit((string) $value)) { // check for strings with only characters above chr(128) and punctuation/numbers, but not just numeric strings (e.g. track numbers or years)
+							foreach (array('Windows-1251', 'KOI8-R') as $id3v1_bad_encoding) {
+								if (function_exists('mb_convert_encoding') && @mb_convert_encoding($value, $id3v1_bad_encoding, $id3v1_bad_encoding) === $value) {
+									$ID3v1encoding = $id3v1_bad_encoding;
+									$this->warning('ID3v1 detected as '.$id3v1_bad_encoding.' text encoding in '.$tag_key);
+									break 3;
+								} elseif (function_exists('iconv') && @iconv($id3v1_bad_encoding, $id3v1_bad_encoding, $value) === $value) {
+									$ID3v1encoding = $id3v1_bad_encoding;
+									$this->warning('ID3v1 detected as '.$id3v1_bad_encoding.' text encoding in '.$tag_key);
+									break 3;
+								}
 							}
 						}
 					}
 				}
+				// ID3v1 encoding detection hack END
 			}
-			// ID3v1 encoding detection hack END
 
 			// ID3v1 data is supposed to be padded with NULL characters, but some taggers pad with spaces
 			$GoodFormatID3v1tag = $this->GenerateID3v1Tag(
@@ -89,7 +98,7 @@
 											$ParsedID3v1['year'],
 											(isset($ParsedID3v1['genre']) ? $this->LookupGenreID($ParsedID3v1['genre']) : false),
 											$ParsedID3v1['comment'],
-											(!empty($ParsedID3v1['track']) ? $ParsedID3v1['track'] : ''));
+											(!empty($ParsedID3v1['track_number']) ? $ParsedID3v1['track_number'] : ''));
 			$ParsedID3v1['padding_valid'] = true;
 			if ($id3v1tag !== $GoodFormatID3v1tag) {
 				$ParsedID3v1['padding_valid'] = false;
@@ -124,10 +133,20 @@
 		return true;
 	}
 
+	/**
+	 * @param string $str
+	 *
+	 * @return string
+	 */
 	public static function cutfield($str) {
 		return trim(substr($str, 0, strcspn($str, "\x00")));
 	}
 
+	/**
+	 * @param bool $allowSCMPXextended
+	 *
+	 * @return string[]
+	 */
 	public static function ArrayOfGenres($allowSCMPXextended=false) {
 		static $GenreLookup = array(
 			0    => 'Blues',
@@ -312,6 +331,12 @@
 		return ($allowSCMPXextended ? $GenreLookupSCMPX : $GenreLookup);
 	}
 
+	/**
+	 * @param string $genreid
+	 * @param bool   $allowSCMPXextended
+	 *
+	 * @return string|false
+	 */
 	public static function LookupGenreName($genreid, $allowSCMPXextended=true) {
 		switch ($genreid) {
 			case 'RX':
@@ -328,6 +353,12 @@
 		return (isset($GenreLookup[$genreid]) ? $GenreLookup[$genreid] : false);
 	}
 
+	/**
+	 * @param string $genre
+	 * @param bool   $allowSCMPXextended
+	 *
+	 * @return string|false
+	 */
 	public static function LookupGenreID($genre, $allowSCMPXextended=false) {
 		$GenreLookup = self::ArrayOfGenres($allowSCMPXextended);
 		$LowerCaseNoSpaceSearchTerm = strtolower(str_replace(' ', '', $genre));
@@ -339,6 +370,11 @@
 		return false;
 	}
 
+	/**
+	 * @param string $OriginalGenre
+	 *
+	 * @return string|false
+	 */
 	public static function StandardiseID3v1GenreName($OriginalGenre) {
 		if (($GenreID = self::LookupGenreID($OriginalGenre)) !== false) {
 			return self::LookupGenreName($GenreID);
@@ -346,6 +382,17 @@
 		return $OriginalGenre;
 	}
 
+	/**
+	 * @param string     $title
+	 * @param string     $artist
+	 * @param string     $album
+	 * @param string     $year
+	 * @param int        $genreid
+	 * @param string     $comment
+	 * @param int|string $track
+	 *
+	 * @return string
+	 */
 	public static function GenerateID3v1Tag($title, $artist, $album, $year, $genreid, $comment, $track='') {
 		$ID3v1Tag  = 'TAG';
 		$ID3v1Tag .= str_pad(trim(substr($title,  0, 30)), 30, "\x00", STR_PAD_RIGHT);