⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 module.tag.id3v2.php

📁 一个用PHP编写的
💻 PHP
📖 第 1 页 / 共 5 页
字号:
<?php//////////////////////////////////////////////////////////////////// getID3() by James Heinrich <info@getid3.org>               ////  available at http://getid3.sourceforge.net                 ////            or http://www.getid3.org                         ///////////////////////////////////////////////////////////////////// See readme.txt for more details                             //////////////////////////////////////////////////////////////////////                                                            //// module.tag.id3v2.php                                        //// module for analyzing ID3v2 tags                             //// dependencies: module.tag.id3v1.php                          ////                                                            ////////////////////////////////////////////////////////////////////getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.tag.id3v1.php', __FILE__, true);class getid3_id3v2{	function getid3_id3v2(&$fd, &$ThisFileInfo, $StartingOffset=0) {		//    Overall tag structure:		//        +-----------------------------+		//        |      Header (10 bytes)      |		//        +-----------------------------+		//        |       Extended Header       |		//        | (variable length, OPTIONAL) |		//        +-----------------------------+		//        |   Frames (variable length)  |		//        +-----------------------------+		//        |           Padding           |		//        | (variable length, OPTIONAL) |		//        +-----------------------------+		//        | Footer (10 bytes, OPTIONAL) |		//        +-----------------------------+		//    Header		//        ID3v2/file identifier      "ID3"		//        ID3v2 version              $04 00		//        ID3v2 flags                (%ab000000 in v2.2, %abc00000 in v2.3, %abcd0000 in v2.4.x)		//        ID3v2 size             4 * %0xxxxxxx		// shortcuts		$ThisFileInfo['id3v2']['header'] = true;		$thisfile_id3v2                  = &$ThisFileInfo['id3v2'];		$thisfile_id3v2['flags']         =  array();		$thisfile_id3v2_flags            = &$thisfile_id3v2['flags'];		fseek($fd, $StartingOffset, SEEK_SET);		$header = fread($fd, 10);		if (substr($header, 0, 3) == 'ID3') {			$thisfile_id3v2['majorversion'] = ord($header{3});			$thisfile_id3v2['minorversion'] = ord($header{4});			// shortcut			$id3v2_majorversion = &$thisfile_id3v2['majorversion'];		} else {			unset($ThisFileInfo['id3v2']);			return false;		}		if ($id3v2_majorversion > 4) { // this script probably won't correctly parse ID3v2.5.x and above (if it ever exists)			$ThisFileInfo['error'][] = 'this script only parses up to ID3v2.4.x - this tag is ID3v2.'.$id3v2_majorversion.'.'.$thisfile_id3v2['minorversion'];			return false;		}		$id3_flags = ord($header{5});		switch ($id3v2_majorversion) {			case 2:				// %ab000000 in v2.2				$thisfile_id3v2_flags['unsynch']     = (bool) ($id3_flags & 0x80); // a - Unsynchronisation				$thisfile_id3v2_flags['compression'] = (bool) ($id3_flags & 0x40); // b - Compression				break;			case 3:				// %abc00000 in v2.3				$thisfile_id3v2_flags['unsynch']     = (bool) ($id3_flags & 0x80); // a - Unsynchronisation				$thisfile_id3v2_flags['exthead']     = (bool) ($id3_flags & 0x40); // b - Extended header				$thisfile_id3v2_flags['experim']     = (bool) ($id3_flags & 0x20); // c - Experimental indicator				break;			case 4:				// %abcd0000 in v2.4				$thisfile_id3v2_flags['unsynch']     = (bool) ($id3_flags & 0x80); // a - Unsynchronisation				$thisfile_id3v2_flags['exthead']     = (bool) ($id3_flags & 0x40); // b - Extended header				$thisfile_id3v2_flags['experim']     = (bool) ($id3_flags & 0x20); // c - Experimental indicator				$thisfile_id3v2_flags['isfooter']    = (bool) ($id3_flags & 0x10); // d - Footer present				break;		}		$thisfile_id3v2['headerlength'] = getid3_lib::BigEndian2Int(substr($header, 6, 4), 1) + 10; // length of ID3v2 tag in 10-byte header doesn't include 10-byte header length		$thisfile_id3v2['tag_offset_start'] = $StartingOffset;		$thisfile_id3v2['tag_offset_end']   = $thisfile_id3v2['tag_offset_start'] + $thisfile_id3v2['headerlength'];		//    Extended Header		if (isset($thisfile_id3v2_flags['exthead']) && $thisfile_id3v2_flags['exthead']) {			// Extended header size   4 * %0xxxxxxx			// Number of flag bytes       $01			// Extended Flags             $xx			// Where the 'Extended header size' is the size of the whole extended header, stored as a 32 bit synchsafe integer.			$thisfile_id3v2['exthead_length'] = getid3_lib::BigEndian2Int(fread($fd, 4), 1);			$thisfile_id3v2['exthead_flag_bytes'] = ord(fread($fd, 1));			if ($thisfile_id3v2['exthead_flag_bytes'] == 1) {				// The extended flags field, with its size described by 'number of flag  bytes', is defined as:				//     %0bcd0000				// b - Tag is an update				//     Flag data length       $00				// c - CRC data present				//     Flag data length       $05				//     Total frame CRC    5 * %0xxxxxxx				// d - Tag restrictions				//     Flag data length       $01				$extheaderflags    = fread($fd, $thisfile_id3v2['exthead_flag_bytes']);				$id3_exthead_flags = getid3_lib::BigEndian2Bin(substr($header, 5, 1));				$thisfile_id3v2['exthead_flags']['update']       = substr($id3_exthead_flags, 1, 1);				$thisfile_id3v2['exthead_flags']['CRC']          = substr($id3_exthead_flags, 2, 1);				if ($thisfile_id3v2['exthead_flags']['CRC']) {					$extheaderrawCRC = fread($fd, 5);					$thisfile_id3v2['exthead_flags']['CRC'] = getid3_lib::BigEndian2Int($extheaderrawCRC, 1);				}				$thisfile_id3v2['exthead_flags']['restrictions'] = substr($id3_exthead_flags, 3, 1);				if ($thisfile_id3v2['exthead_flags']['restrictions']) {					// Restrictions           %ppqrrstt					$extheaderrawrestrictions = fread($fd, 1);					$thisfile_id3v2['exthead_flags']['restrictions_tagsize']  = (bindec('11000000') & ord($extheaderrawrestrictions)) >> 6; // p - Tag size restrictions					$thisfile_id3v2['exthead_flags']['restrictions_textenc']  = (bindec('00100000') & ord($extheaderrawrestrictions)) >> 5; // q - Text encoding restrictions					$thisfile_id3v2['exthead_flags']['restrictions_textsize'] = (bindec('00011000') & ord($extheaderrawrestrictions)) >> 3; // r - Text fields size restrictions					$thisfile_id3v2['exthead_flags']['restrictions_imgenc']   = (bindec('00000100') & ord($extheaderrawrestrictions)) >> 2; // s - Image encoding restrictions					$thisfile_id3v2['exthead_flags']['restrictions_imgsize']  = (bindec('00000011') & ord($extheaderrawrestrictions)) >> 0; // t - Image size restrictions				}			} else {				$ThisFileInfo['warning'][] = '$thisfile_id3v2[exthead_flag_bytes] = "'.$thisfile_id3v2['exthead_flag_bytes'].'" (expecting "1")';				fseek($fd, $thisfile_id3v2['exthead_length'] - 1, SEEK_CUR);				//return false;			}		} // end extended header		// create 'encoding' key - used by getid3::HandleAllTags()		// in ID3v2 every field can have it's own encoding type		// so force everything to UTF-8 so it can be handled consistantly		$thisfile_id3v2['encoding'] = 'UTF-8';	//    Frames	//        All ID3v2 frames consists of one frame header followed by one or more	//        fields containing the actual information. The header is always 10	//        bytes and laid out as follows:	//	//        Frame ID      $xx xx xx xx  (four characters)	//        Size      4 * %0xxxxxxx	//        Flags         $xx xx		$sizeofframes = $thisfile_id3v2['headerlength'] - 10; // not including 10-byte initial header		if (@$thisfile_id3v2['exthead_length']) {			$sizeofframes -= ($thisfile_id3v2['exthead_length'] + 4);		}		if (@$thisfile_id3v2_flags['isfooter']) {			$sizeofframes -= 10; // footer takes last 10 bytes of ID3v2 header, after frame data, before audio		}		if ($sizeofframes > 0) {			$framedata = fread($fd, $sizeofframes); // read all frames from file into $framedata variable			//    if entire frame data is unsynched, de-unsynch it now (ID3v2.3.x)			if (@$thisfile_id3v2_flags['unsynch'] && ($id3v2_majorversion <= 3)) {				$framedata = $this->DeUnsynchronise($framedata);			}			//        [in ID3v2.4.0] Unsynchronisation [S:6.1] is done on frame level, instead			//        of on tag level, making it easier to skip frames, increasing the streamability			//        of the tag. The unsynchronisation flag in the header [S:3.1] indicates that			//        there exists an unsynchronised frame, while the new unsynchronisation flag in			//        the frame header [S:4.1.2] indicates unsynchronisation.			$framedataoffset = 10 + (@$thisfile_id3v2['exthead_length'] ? $thisfile_id3v2['exthead_length'] + 4 : 0); // how many bytes into the stream - start from after the 10-byte header (and extended header length+4, if present)			while (isset($framedata) && (strlen($framedata) > 0)) { // cycle through until no more frame data is left to parse				if (strlen($framedata) <= $this->ID3v2HeaderLength($id3v2_majorversion)) {					// insufficient room left in ID3v2 header for actual data - must be padding					$thisfile_id3v2['padding']['start']  = $framedataoffset;					$thisfile_id3v2['padding']['length'] = strlen($framedata);					$thisfile_id3v2['padding']['valid']  = true;					for ($i = 0; $i < $thisfile_id3v2['padding']['length']; $i++) {						if ($framedata{$i} != "\x00") {							$thisfile_id3v2['padding']['valid'] = false;							$thisfile_id3v2['padding']['errorpos'] = $thisfile_id3v2['padding']['start'] + $i;							$ThisFileInfo['warning'][] = 'Invalid ID3v2 padding found at offset '.$thisfile_id3v2['padding']['errorpos'].' (the remaining '.($thisfile_id3v2['padding']['length'] - $i).' bytes are considered invalid)';							break;						}					}					break; // skip rest of ID3v2 header				}				if ($id3v2_majorversion == 2) {					// Frame ID  $xx xx xx (three characters)					// Size      $xx xx xx (24-bit integer)					// Flags     $xx xx					$frame_header = substr($framedata, 0, 6); // take next 6 bytes for header					$framedata    = substr($framedata, 6);    // and leave the rest in $framedata					$frame_name   = substr($frame_header, 0, 3);					$frame_size   = getid3_lib::BigEndian2Int(substr($frame_header, 3, 3), 0);					$frame_flags  = 0; // not used for anything in ID3v2.2, just set to avoid E_NOTICEs				} elseif ($id3v2_majorversion > 2) {					// Frame ID  $xx xx xx xx (four characters)					// Size      $xx xx xx xx (32-bit integer in v2.3, 28-bit synchsafe in v2.4+)					// Flags     $xx xx					$frame_header = substr($framedata, 0, 10); // take next 10 bytes for header					$framedata    = substr($framedata, 10);    // and leave the rest in $framedata					$frame_name = substr($frame_header, 0, 4);					if ($id3v2_majorversion == 3) {						$frame_size = getid3_lib::BigEndian2Int(substr($frame_header, 4, 4), 0); // 32-bit integer					} else { // ID3v2.4+						$frame_size = getid3_lib::BigEndian2Int(substr($frame_header, 4, 4), 1); // 32-bit synchsafe integer (28-bit value)					}					if ($frame_size < (strlen($framedata) + 4)) {						$nextFrameID = substr($framedata, $frame_size, 4);						if ($this->IsValidID3v2FrameName($nextFrameID, $id3v2_majorversion)) {							// next frame is OK						} elseif (($frame_name == "\x00".'MP3') || ($frame_name == "\x00\x00".'MP') || ($frame_name == ' MP3') || ($frame_name == 'MP3e')) {							// MP3ext known broken frames - "ok" for the purposes of this test						} elseif (($id3v2_majorversion == 4) && ($this->IsValidID3v2FrameName(substr($framedata, getid3_lib::BigEndian2Int(substr($frame_header, 4, 4), 0), 4), 3))) {							$ThisFileInfo['warning'][] = 'ID3v2 tag written as ID3v2.4, but with non-synchsafe integers (ID3v2.3 style). Older versions of (Helium2; iTunes) are known culprits of this. Tag has been parsed as ID3v2.3';							$id3v2_majorversion = 3;							$frame_size = getid3_lib::BigEndian2Int(substr($frame_header, 4, 4), 0); // 32-bit integer						}					}					$frame_flags = getid3_lib::BigEndian2Int(substr($frame_header, 8, 2));				}				if ((($id3v2_majorversion == 2) && ($frame_name == "\x00\x00\x00")) || ($frame_name == "\x00\x00\x00\x00")) {					// padding encountered

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -