Mercurial > judyates
view e2gallerypro/e2upload/Backend/Assets/getid3/module.tag.apetag.php @ 3:3f6b44aa6b35 judyates
[svn r4] added ability to buy stuff, from a Prints page, but it doesn't work well with the css, and it also has not been fitted into the perl make system.
author | rlm |
---|---|
date | Mon, 22 Feb 2010 08:02:39 -0500 |
parents | |
children |
line wrap: on
line source
1 <?php2 // +----------------------------------------------------------------------+3 // | PHP version 5 |4 // +----------------------------------------------------------------------+5 // | Copyright (c) 2002-2006 James Heinrich, Allan Hansen |6 // +----------------------------------------------------------------------+7 // | This source file is subject to version 2 of the GPL license, |8 // | that is bundled with this package in the file license.txt and is |9 // | available through the world-wide-web at the following url: |10 // | http://www.gnu.org/copyleft/gpl.html |11 // +----------------------------------------------------------------------+12 // | getID3() - http://getid3.sourceforge.net or http://www.getid3.org |13 // +----------------------------------------------------------------------+14 // | Authors: James Heinrich <infoØgetid3*org> |15 // | Allan Hansen <ahØartemis*dk> |16 // +----------------------------------------------------------------------+17 // | module.tag.apetag.php |18 // | module for analyzing APE tags |19 // | dependencies: NONE |20 // +----------------------------------------------------------------------+21 //22 // $Id: module.tag.apetag.php,v 1.5 2006/11/16 14:05:21 ah Exp $26 class getid3_apetag extends getid3_handler27 {28 /*29 ID3v1_TAG_SIZE = 128;30 APETAG_HEADER_SIZE = 32;31 LYRICS3_TAG_SIZE = 10;32 */34 public $option_override_end_offset = 0;38 public function Analyze() {40 $getid3 = $this->getid3;42 if ($this->option_override_end_offset == 0) {44 fseek($getid3->fp, 0 - 170, SEEK_END); // 170 = ID3v1_TAG_SIZE + APETAG_HEADER_SIZE + LYRICS3_TAG_SIZE45 $apetag_footer_id3v1 = fread($getid3->fp, 170); // 170 = ID3v1_TAG_SIZE + APETAG_HEADER_SIZE + LYRICS3_TAG_SIZE47 // APE tag found before ID3v148 if (substr($apetag_footer_id3v1, strlen($apetag_footer_id3v1) - 160, 8) == 'APETAGEX') { // 160 = ID3v1_TAG_SIZE + APETAG_HEADER_SIZE49 $getid3->info['ape']['tag_offset_end'] = filesize($getid3->filename) - 128; // 128 = ID3v1_TAG_SIZE50 }52 // APE tag found, no ID3v153 elseif (substr($apetag_footer_id3v1, strlen($apetag_footer_id3v1) - 32, 8) == 'APETAGEX') { // 32 = APETAG_HEADER_SIZE54 $getid3->info['ape']['tag_offset_end'] = filesize($getid3->filename);55 }57 }58 else {60 fseek($getid3->fp, $this->option_override_end_offset - 32, SEEK_SET); // 32 = APETAG_HEADER_SIZE61 if (fread($getid3->fp, 8) == 'APETAGEX') {62 $getid3->info['ape']['tag_offset_end'] = $this->option_override_end_offset;63 }65 }67 // APE tag not found68 if (!@$getid3->info['ape']['tag_offset_end']) {69 return false;70 }72 // Shortcut73 $info_ape = &$getid3->info['ape'];75 // Read and parse footer76 fseek($getid3->fp, $info_ape['tag_offset_end'] - 32, SEEK_SET); // 32 = APETAG_HEADER_SIZE77 $apetag_footer_data = fread($getid3->fp, 32);78 if (!($this->ParseAPEHeaderFooter($apetag_footer_data, $info_ape['footer']))) {79 throw new getid3_exception('Error parsing APE footer at offset '.$info_ape['tag_offset_end']);80 }82 if (isset($info_ape['footer']['flags']['header']) && $info_ape['footer']['flags']['header']) {83 fseek($getid3->fp, $info_ape['tag_offset_end'] - $info_ape['footer']['raw']['tagsize'] - 32, SEEK_SET);84 $info_ape['tag_offset_start'] = ftell($getid3->fp);85 $apetag_data = fread($getid3->fp, $info_ape['footer']['raw']['tagsize'] + 32);86 }87 else {88 $info_ape['tag_offset_start'] = $info_ape['tag_offset_end'] - $info_ape['footer']['raw']['tagsize'];89 fseek($getid3->fp, $info_ape['tag_offset_start'], SEEK_SET);90 $apetag_data = fread($getid3->fp, $info_ape['footer']['raw']['tagsize']);91 }92 $getid3->info['avdataend'] = $info_ape['tag_offset_start'];94 if (isset($getid3->info['id3v1']['tag_offset_start']) && ($getid3->info['id3v1']['tag_offset_start'] < $info_ape['tag_offset_end'])) {95 $getid3->warning('ID3v1 tag information ignored since it appears to be a false synch in APEtag data');96 unset($getid3->info['id3v1']);97 }99 $offset = 0;100 if (isset($info_ape['footer']['flags']['header']) && $info_ape['footer']['flags']['header']) {101 if (!$this->ParseAPEHeaderFooter(substr($apetag_data, 0, 32), $info_ape['header'])) {102 throw new getid3_exception('Error parsing APE header at offset '.$info_ape['tag_offset_start']);103 }104 $offset = 32;105 }107 // Shortcut108 $getid3->info['replay_gain'] = array ();109 $info_replaygain = &$getid3->info['replay_gain'];111 for ($i = 0; $i < $info_ape['footer']['raw']['tag_items']; $i++) {112 $value_size = getid3_lib::LittleEndian2Int(substr($apetag_data, $offset, 4));113 $item_flags = getid3_lib::LittleEndian2Int(substr($apetag_data, $offset + 4, 4));114 $offset += 8;116 if (strstr(substr($apetag_data, $offset), "\x00") === false) {117 throw new getid3_exception('Cannot find null-byte (0x00) seperator between ItemKey #'.$i.' and value. ItemKey starts ' . $offset . ' bytes into the APE tag, at file offset '.($info_ape['tag_offset_start'] + $offset));118 }120 $item_key_length = strpos($apetag_data, "\x00", $offset) - $offset;121 $item_key = strtolower(substr($apetag_data, $offset, $item_key_length));123 // Shortcut124 $info_ape['items'][$item_key] = array ();125 $info_ape_items_current = &$info_ape['items'][$item_key];127 $offset += $item_key_length + 1; // skip 0x00 terminator128 $info_ape_items_current['data'] = substr($apetag_data, $offset, $value_size);129 $offset += $value_size;132 $info_ape_items_current['flags'] = $this->ParseAPEtagFlags($item_flags);134 switch ($info_ape_items_current['flags']['item_contents_raw']) {135 case 0: // UTF-8136 case 3: // Locator (URL, filename, etc), UTF-8 encoded137 $info_ape_items_current['data'] = explode("\x00", trim($info_ape_items_current['data']));138 break;140 default: // binary data141 break;142 }144 switch (strtolower($item_key)) {145 case 'replaygain_track_gain':146 $info_replaygain['track']['adjustment'] = (float)str_replace(',', '.', $info_ape_items_current['data'][0]); // float casting will see "0,95" as zero!147 $info_replaygain['track']['originator'] = 'unspecified';148 break;150 case 'replaygain_track_peak':151 $info_replaygain['track']['peak'] = (float)str_replace(',', '.', $info_ape_items_current['data'][0]); // float casting will see "0,95" as zero!152 $info_replaygain['track']['originator'] = 'unspecified';153 if ($info_replaygain['track']['peak'] <= 0) {154 $getid3->warning('ReplayGain Track peak from APEtag appears invalid: '.$info_replaygain['track']['peak'].' (original value = "'.$info_ape_items_current['data'][0].'")');155 }156 break;158 case 'replaygain_album_gain':159 $info_replaygain['album']['adjustment'] = (float)str_replace(',', '.', $info_ape_items_current['data'][0]); // float casting will see "0,95" as zero!160 $info_replaygain['album']['originator'] = 'unspecified';161 break;163 case 'replaygain_album_peak':164 $info_replaygain['album']['peak'] = (float)str_replace(',', '.', $info_ape_items_current['data'][0]); // float casting will see "0,95" as zero!165 $info_replaygain['album']['originator'] = 'unspecified';166 if ($info_replaygain['album']['peak'] <= 0) {167 $getid3->warning('ReplayGain Album peak from APEtag appears invalid: '.$info_replaygain['album']['peak'].' (original value = "'.$info_ape_items_current['data'][0].'")');168 }169 break;171 case 'mp3gain_undo':172 list($mp3gain_undo_left, $mp3gain_undo_right, $mp3gain_undo_wrap) = explode(',', $info_ape_items_current['data'][0]);173 $info_replaygain['mp3gain']['undo_left'] = intval($mp3gain_undo_left);174 $info_replaygain['mp3gain']['undo_right'] = intval($mp3gain_undo_right);175 $info_replaygain['mp3gain']['undo_wrap'] = (($mp3gain_undo_wrap == 'Y') ? true : false);176 break;178 case 'mp3gain_minmax':179 list($mp3gain_globalgain_min, $mp3gain_globalgain_max) = explode(',', $info_ape_items_current['data'][0]);180 $info_replaygain['mp3gain']['globalgain_track_min'] = intval($mp3gain_globalgain_min);181 $info_replaygain['mp3gain']['globalgain_track_max'] = intval($mp3gain_globalgain_max);182 break;184 case 'mp3gain_album_minmax':185 list($mp3gain_globalgain_album_min, $mp3gain_globalgain_album_max) = explode(',', $info_ape_items_current['data'][0]);186 $info_replaygain['mp3gain']['globalgain_album_min'] = intval($mp3gain_globalgain_album_min);187 $info_replaygain['mp3gain']['globalgain_album_max'] = intval($mp3gain_globalgain_album_max);188 break;190 case 'tracknumber':191 foreach ($info_ape_items_current['data'] as $comment) {192 $info_ape['comments']['track'][] = $comment;193 }194 break;196 default:197 foreach ($info_ape_items_current['data'] as $comment) {198 $info_ape['comments'][strtolower($item_key)][] = $comment;199 }200 break;201 }203 }204 if (empty($info_replaygain)) {205 unset($getid3->info['replay_gain']);206 }208 return true;209 }213 protected function ParseAPEheaderFooter($data, &$target) {215 // http://www.uni-jena.de/~pfk/mpp/sv8/apeheader.html217 if (substr($data, 0, 8) != 'APETAGEX') {218 return false;219 }221 // shortcut222 $target['raw'] = array ();223 $target_raw = &$target['raw'];225 $target_raw['footer_tag'] = 'APETAGEX';227 getid3_lib::ReadSequence("LittleEndian2Int", $target_raw, $data, 8,228 array (229 'version' => 4,230 'tagsize' => 4,231 'tag_items' => 4,232 'global_flags' => 4233 )234 );235 $target_raw['reserved'] = substr($data, 24, 8);237 $target['tag_version'] = $target_raw['version'] / 1000;238 if ($target['tag_version'] >= 2) {240 $target['flags'] = $this->ParseAPEtagFlags($target_raw['global_flags']);241 }243 return true;244 }248 protected function ParseAPEtagFlags($raw_flag_int) {250 // "Note: APE Tags 1.0 do not use any of the APE Tag flags.251 // All are set to zero on creation and ignored on reading."252 // http://www.uni-jena.de/~pfk/mpp/sv8/apetagflags.html254 $target['header'] = (bool) ($raw_flag_int & 0x80000000);255 $target['footer'] = (bool) ($raw_flag_int & 0x40000000);256 $target['this_is_header'] = (bool) ($raw_flag_int & 0x20000000);257 $target['item_contents_raw'] = ($raw_flag_int & 0x00000006) >> 1;258 $target['read_only'] = (bool) ($raw_flag_int & 0x00000001);260 $target['item_contents'] = getid3_apetag::APEcontentTypeFlagLookup($target['item_contents_raw']);262 return $target;263 }267 public static function APEcontentTypeFlagLookup($content_type_id) {269 static $lookup = array (270 0 => 'utf-8',271 1 => 'binary',272 2 => 'external',273 3 => 'reserved'274 );275 return (isset($lookup[$content_type_id]) ? $lookup[$content_type_id] : 'invalid');276 }280 public static function APEtagItemIsUTF8Lookup($item_key) {282 static $lookup = array (283 'title',284 'subtitle',285 'artist',286 'album',287 'debut album',288 'publisher',289 'conductor',290 'track',291 'composer',292 'comment',293 'copyright',294 'publicationright',295 'file',296 'year',297 'record date',298 'record location',299 'genre',300 'media',301 'related',302 'isrc',303 'abstract',304 'language',305 'bibliography'306 );307 return in_array(strtolower($item_key), $lookup);308 }310 }312 ?>