Mercurial > judyates
diff 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 diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/e2gallerypro/e2upload/Backend/Assets/getid3/module.tag.apetag.php Mon Feb 22 08:02:39 2010 -0500 1.3 @@ -0,0 +1,312 @@ 1.4 +<?php 1.5 +// +----------------------------------------------------------------------+ 1.6 +// | PHP version 5 | 1.7 +// +----------------------------------------------------------------------+ 1.8 +// | Copyright (c) 2002-2006 James Heinrich, Allan Hansen | 1.9 +// +----------------------------------------------------------------------+ 1.10 +// | This source file is subject to version 2 of the GPL license, | 1.11 +// | that is bundled with this package in the file license.txt and is | 1.12 +// | available through the world-wide-web at the following url: | 1.13 +// | http://www.gnu.org/copyleft/gpl.html | 1.14 +// +----------------------------------------------------------------------+ 1.15 +// | getID3() - http://getid3.sourceforge.net or http://www.getid3.org | 1.16 +// +----------------------------------------------------------------------+ 1.17 +// | Authors: James Heinrich <infoØgetid3*org> | 1.18 +// | Allan Hansen <ahØartemis*dk> | 1.19 +// +----------------------------------------------------------------------+ 1.20 +// | module.tag.apetag.php | 1.21 +// | module for analyzing APE tags | 1.22 +// | dependencies: NONE | 1.23 +// +----------------------------------------------------------------------+ 1.24 +// 1.25 +// $Id: module.tag.apetag.php,v 1.5 2006/11/16 14:05:21 ah Exp $ 1.26 + 1.27 + 1.28 + 1.29 +class getid3_apetag extends getid3_handler 1.30 +{ 1.31 + /* 1.32 + ID3v1_TAG_SIZE = 128; 1.33 + APETAG_HEADER_SIZE = 32; 1.34 + LYRICS3_TAG_SIZE = 10; 1.35 + */ 1.36 + 1.37 + public $option_override_end_offset = 0; 1.38 + 1.39 + 1.40 + 1.41 + public function Analyze() { 1.42 + 1.43 + $getid3 = $this->getid3; 1.44 + 1.45 + if ($this->option_override_end_offset == 0) { 1.46 + 1.47 + fseek($getid3->fp, 0 - 170, SEEK_END); // 170 = ID3v1_TAG_SIZE + APETAG_HEADER_SIZE + LYRICS3_TAG_SIZE 1.48 + $apetag_footer_id3v1 = fread($getid3->fp, 170); // 170 = ID3v1_TAG_SIZE + APETAG_HEADER_SIZE + LYRICS3_TAG_SIZE 1.49 + 1.50 + // APE tag found before ID3v1 1.51 + if (substr($apetag_footer_id3v1, strlen($apetag_footer_id3v1) - 160, 8) == 'APETAGEX') { // 160 = ID3v1_TAG_SIZE + APETAG_HEADER_SIZE 1.52 + $getid3->info['ape']['tag_offset_end'] = filesize($getid3->filename) - 128; // 128 = ID3v1_TAG_SIZE 1.53 + } 1.54 + 1.55 + // APE tag found, no ID3v1 1.56 + elseif (substr($apetag_footer_id3v1, strlen($apetag_footer_id3v1) - 32, 8) == 'APETAGEX') { // 32 = APETAG_HEADER_SIZE 1.57 + $getid3->info['ape']['tag_offset_end'] = filesize($getid3->filename); 1.58 + } 1.59 + 1.60 + } 1.61 + else { 1.62 + 1.63 + fseek($getid3->fp, $this->option_override_end_offset - 32, SEEK_SET); // 32 = APETAG_HEADER_SIZE 1.64 + if (fread($getid3->fp, 8) == 'APETAGEX') { 1.65 + $getid3->info['ape']['tag_offset_end'] = $this->option_override_end_offset; 1.66 + } 1.67 + 1.68 + } 1.69 + 1.70 + // APE tag not found 1.71 + if (!@$getid3->info['ape']['tag_offset_end']) { 1.72 + return false; 1.73 + } 1.74 + 1.75 + // Shortcut 1.76 + $info_ape = &$getid3->info['ape']; 1.77 + 1.78 + // Read and parse footer 1.79 + fseek($getid3->fp, $info_ape['tag_offset_end'] - 32, SEEK_SET); // 32 = APETAG_HEADER_SIZE 1.80 + $apetag_footer_data = fread($getid3->fp, 32); 1.81 + if (!($this->ParseAPEHeaderFooter($apetag_footer_data, $info_ape['footer']))) { 1.82 + throw new getid3_exception('Error parsing APE footer at offset '.$info_ape['tag_offset_end']); 1.83 + } 1.84 + 1.85 + if (isset($info_ape['footer']['flags']['header']) && $info_ape['footer']['flags']['header']) { 1.86 + fseek($getid3->fp, $info_ape['tag_offset_end'] - $info_ape['footer']['raw']['tagsize'] - 32, SEEK_SET); 1.87 + $info_ape['tag_offset_start'] = ftell($getid3->fp); 1.88 + $apetag_data = fread($getid3->fp, $info_ape['footer']['raw']['tagsize'] + 32); 1.89 + } 1.90 + else { 1.91 + $info_ape['tag_offset_start'] = $info_ape['tag_offset_end'] - $info_ape['footer']['raw']['tagsize']; 1.92 + fseek($getid3->fp, $info_ape['tag_offset_start'], SEEK_SET); 1.93 + $apetag_data = fread($getid3->fp, $info_ape['footer']['raw']['tagsize']); 1.94 + } 1.95 + $getid3->info['avdataend'] = $info_ape['tag_offset_start']; 1.96 + 1.97 + if (isset($getid3->info['id3v1']['tag_offset_start']) && ($getid3->info['id3v1']['tag_offset_start'] < $info_ape['tag_offset_end'])) { 1.98 + $getid3->warning('ID3v1 tag information ignored since it appears to be a false synch in APEtag data'); 1.99 + unset($getid3->info['id3v1']); 1.100 + } 1.101 + 1.102 + $offset = 0; 1.103 + if (isset($info_ape['footer']['flags']['header']) && $info_ape['footer']['flags']['header']) { 1.104 + if (!$this->ParseAPEHeaderFooter(substr($apetag_data, 0, 32), $info_ape['header'])) { 1.105 + throw new getid3_exception('Error parsing APE header at offset '.$info_ape['tag_offset_start']); 1.106 + } 1.107 + $offset = 32; 1.108 + } 1.109 + 1.110 + // Shortcut 1.111 + $getid3->info['replay_gain'] = array (); 1.112 + $info_replaygain = &$getid3->info['replay_gain']; 1.113 + 1.114 + for ($i = 0; $i < $info_ape['footer']['raw']['tag_items']; $i++) { 1.115 + $value_size = getid3_lib::LittleEndian2Int(substr($apetag_data, $offset, 4)); 1.116 + $item_flags = getid3_lib::LittleEndian2Int(substr($apetag_data, $offset + 4, 4)); 1.117 + $offset += 8; 1.118 + 1.119 + if (strstr(substr($apetag_data, $offset), "\x00") === false) { 1.120 + 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)); 1.121 + } 1.122 + 1.123 + $item_key_length = strpos($apetag_data, "\x00", $offset) - $offset; 1.124 + $item_key = strtolower(substr($apetag_data, $offset, $item_key_length)); 1.125 + 1.126 + // Shortcut 1.127 + $info_ape['items'][$item_key] = array (); 1.128 + $info_ape_items_current = &$info_ape['items'][$item_key]; 1.129 + 1.130 + $offset += $item_key_length + 1; // skip 0x00 terminator 1.131 + $info_ape_items_current['data'] = substr($apetag_data, $offset, $value_size); 1.132 + $offset += $value_size; 1.133 + 1.134 + 1.135 + $info_ape_items_current['flags'] = $this->ParseAPEtagFlags($item_flags); 1.136 + 1.137 + switch ($info_ape_items_current['flags']['item_contents_raw']) { 1.138 + case 0: // UTF-8 1.139 + case 3: // Locator (URL, filename, etc), UTF-8 encoded 1.140 + $info_ape_items_current['data'] = explode("\x00", trim($info_ape_items_current['data'])); 1.141 + break; 1.142 + 1.143 + default: // binary data 1.144 + break; 1.145 + } 1.146 + 1.147 + switch (strtolower($item_key)) { 1.148 + case 'replaygain_track_gain': 1.149 + $info_replaygain['track']['adjustment'] = (float)str_replace(',', '.', $info_ape_items_current['data'][0]); // float casting will see "0,95" as zero! 1.150 + $info_replaygain['track']['originator'] = 'unspecified'; 1.151 + break; 1.152 + 1.153 + case 'replaygain_track_peak': 1.154 + $info_replaygain['track']['peak'] = (float)str_replace(',', '.', $info_ape_items_current['data'][0]); // float casting will see "0,95" as zero! 1.155 + $info_replaygain['track']['originator'] = 'unspecified'; 1.156 + if ($info_replaygain['track']['peak'] <= 0) { 1.157 + $getid3->warning('ReplayGain Track peak from APEtag appears invalid: '.$info_replaygain['track']['peak'].' (original value = "'.$info_ape_items_current['data'][0].'")'); 1.158 + } 1.159 + break; 1.160 + 1.161 + case 'replaygain_album_gain': 1.162 + $info_replaygain['album']['adjustment'] = (float)str_replace(',', '.', $info_ape_items_current['data'][0]); // float casting will see "0,95" as zero! 1.163 + $info_replaygain['album']['originator'] = 'unspecified'; 1.164 + break; 1.165 + 1.166 + case 'replaygain_album_peak': 1.167 + $info_replaygain['album']['peak'] = (float)str_replace(',', '.', $info_ape_items_current['data'][0]); // float casting will see "0,95" as zero! 1.168 + $info_replaygain['album']['originator'] = 'unspecified'; 1.169 + if ($info_replaygain['album']['peak'] <= 0) { 1.170 + $getid3->warning('ReplayGain Album peak from APEtag appears invalid: '.$info_replaygain['album']['peak'].' (original value = "'.$info_ape_items_current['data'][0].'")'); 1.171 + } 1.172 + break; 1.173 + 1.174 + case 'mp3gain_undo': 1.175 + list($mp3gain_undo_left, $mp3gain_undo_right, $mp3gain_undo_wrap) = explode(',', $info_ape_items_current['data'][0]); 1.176 + $info_replaygain['mp3gain']['undo_left'] = intval($mp3gain_undo_left); 1.177 + $info_replaygain['mp3gain']['undo_right'] = intval($mp3gain_undo_right); 1.178 + $info_replaygain['mp3gain']['undo_wrap'] = (($mp3gain_undo_wrap == 'Y') ? true : false); 1.179 + break; 1.180 + 1.181 + case 'mp3gain_minmax': 1.182 + list($mp3gain_globalgain_min, $mp3gain_globalgain_max) = explode(',', $info_ape_items_current['data'][0]); 1.183 + $info_replaygain['mp3gain']['globalgain_track_min'] = intval($mp3gain_globalgain_min); 1.184 + $info_replaygain['mp3gain']['globalgain_track_max'] = intval($mp3gain_globalgain_max); 1.185 + break; 1.186 + 1.187 + case 'mp3gain_album_minmax': 1.188 + list($mp3gain_globalgain_album_min, $mp3gain_globalgain_album_max) = explode(',', $info_ape_items_current['data'][0]); 1.189 + $info_replaygain['mp3gain']['globalgain_album_min'] = intval($mp3gain_globalgain_album_min); 1.190 + $info_replaygain['mp3gain']['globalgain_album_max'] = intval($mp3gain_globalgain_album_max); 1.191 + break; 1.192 + 1.193 + case 'tracknumber': 1.194 + foreach ($info_ape_items_current['data'] as $comment) { 1.195 + $info_ape['comments']['track'][] = $comment; 1.196 + } 1.197 + break; 1.198 + 1.199 + default: 1.200 + foreach ($info_ape_items_current['data'] as $comment) { 1.201 + $info_ape['comments'][strtolower($item_key)][] = $comment; 1.202 + } 1.203 + break; 1.204 + } 1.205 + 1.206 + } 1.207 + if (empty($info_replaygain)) { 1.208 + unset($getid3->info['replay_gain']); 1.209 + } 1.210 + 1.211 + return true; 1.212 + } 1.213 + 1.214 + 1.215 + 1.216 + protected function ParseAPEheaderFooter($data, &$target) { 1.217 + 1.218 + // http://www.uni-jena.de/~pfk/mpp/sv8/apeheader.html 1.219 + 1.220 + if (substr($data, 0, 8) != 'APETAGEX') { 1.221 + return false; 1.222 + } 1.223 + 1.224 + // shortcut 1.225 + $target['raw'] = array (); 1.226 + $target_raw = &$target['raw']; 1.227 + 1.228 + $target_raw['footer_tag'] = 'APETAGEX'; 1.229 + 1.230 + getid3_lib::ReadSequence("LittleEndian2Int", $target_raw, $data, 8, 1.231 + array ( 1.232 + 'version' => 4, 1.233 + 'tagsize' => 4, 1.234 + 'tag_items' => 4, 1.235 + 'global_flags' => 4 1.236 + ) 1.237 + ); 1.238 + $target_raw['reserved'] = substr($data, 24, 8); 1.239 + 1.240 + $target['tag_version'] = $target_raw['version'] / 1000; 1.241 + if ($target['tag_version'] >= 2) { 1.242 + 1.243 + $target['flags'] = $this->ParseAPEtagFlags($target_raw['global_flags']); 1.244 + } 1.245 + 1.246 + return true; 1.247 + } 1.248 + 1.249 + 1.250 + 1.251 + protected function ParseAPEtagFlags($raw_flag_int) { 1.252 + 1.253 + // "Note: APE Tags 1.0 do not use any of the APE Tag flags. 1.254 + // All are set to zero on creation and ignored on reading." 1.255 + // http://www.uni-jena.de/~pfk/mpp/sv8/apetagflags.html 1.256 + 1.257 + $target['header'] = (bool) ($raw_flag_int & 0x80000000); 1.258 + $target['footer'] = (bool) ($raw_flag_int & 0x40000000); 1.259 + $target['this_is_header'] = (bool) ($raw_flag_int & 0x20000000); 1.260 + $target['item_contents_raw'] = ($raw_flag_int & 0x00000006) >> 1; 1.261 + $target['read_only'] = (bool) ($raw_flag_int & 0x00000001); 1.262 + 1.263 + $target['item_contents'] = getid3_apetag::APEcontentTypeFlagLookup($target['item_contents_raw']); 1.264 + 1.265 + return $target; 1.266 + } 1.267 + 1.268 + 1.269 + 1.270 + public static function APEcontentTypeFlagLookup($content_type_id) { 1.271 + 1.272 + static $lookup = array ( 1.273 + 0 => 'utf-8', 1.274 + 1 => 'binary', 1.275 + 2 => 'external', 1.276 + 3 => 'reserved' 1.277 + ); 1.278 + return (isset($lookup[$content_type_id]) ? $lookup[$content_type_id] : 'invalid'); 1.279 + } 1.280 + 1.281 + 1.282 + 1.283 + public static function APEtagItemIsUTF8Lookup($item_key) { 1.284 + 1.285 + static $lookup = array ( 1.286 + 'title', 1.287 + 'subtitle', 1.288 + 'artist', 1.289 + 'album', 1.290 + 'debut album', 1.291 + 'publisher', 1.292 + 'conductor', 1.293 + 'track', 1.294 + 'composer', 1.295 + 'comment', 1.296 + 'copyright', 1.297 + 'publicationright', 1.298 + 'file', 1.299 + 'year', 1.300 + 'record date', 1.301 + 'record location', 1.302 + 'genre', 1.303 + 'media', 1.304 + 'related', 1.305 + 'isrc', 1.306 + 'abstract', 1.307 + 'language', 1.308 + 'bibliography' 1.309 + ); 1.310 + return in_array(strtolower($item_key), $lookup); 1.311 + } 1.312 + 1.313 +} 1.314 + 1.315 +?> 1.316 \ No newline at end of file