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