This file is indexed.

/usr/lib/python2.7/dist-packages/eyed3/mp3/__init__.py is in python-eyed3 0.7.10-1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
################################################################################
#  Copyright (C) 2002-2007  Travis Shirk <travis@pobox.com>
#
#  This program is free software; you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation; either version 2 of the License, or
#  (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program; if not, see <http://www.gnu.org/licenses/>.
#
################################################################################
import os, re

from .. import Error
from .. import id3
from .. import core, utils

from ..utils.log import getLogger
log = getLogger(__name__)

##
# \brief used to signal mp3-related errors.
class Mp3Exception(Error):
    pass


NAME = "mpeg"
MIME_TYPES = ["audio/mpeg", "audio/mp3", "audio/x-mp3", "audio/x-mpeg",
              "audio/mpeg3", "audio/x-mpeg3", "audio/mpg", "audio/x-mpg",
              "audio/x-mpegaudio",
             ]
'''Mime-types that are recognized at MP3'''

OTHER_MIME_TYPES = ['application/octet-stream', # ???
                    'audio/x-hx-aac-adts', # ???
                    'audio/x-wav',  #RIFF wrapped mp3s
                   ]
'''Mime-types that have been seen to contain mp3 data.'''

EXTENSIONS = [".mp3"]
'''Valid file extensions.'''


def isMp3File(file_name):
    '''Does a mime-type check on ``file_name`` and returns ``True`` it the
    file is mp3, and ``False`` otherwise.'''
    return utils.guessMimetype(file_name) in MIME_TYPES

class Mp3AudioInfo(core.AudioInfo):
    def __init__(self, file_obj, start_offset, tag):
        from . import headers
        from .headers import timePerFrame

        log.debug("mp3 header search starting @ %x" % start_offset)
        core.AudioInfo.__init__(self)

        self.mp3_header = None
        self.xing_header = None
        self.vbri_header = None
        self.lame_tag = None
        '''If not ``None``, the Lame header.
        See :class:`eyed3.mp3.headers.LameHeader`'''
        self.bit_rate = (None, None)
        '''2-tuple, (vrb?:boolean, bitrate:int)'''

        while self.mp3_header is None:
            # Find first mp3 header
            (header_pos,
             header_int,
             header_bytes) = headers.findHeader(file_obj, start_offset)
            if not header_int:
                try:
                    fname = file_obj.name
                except AttributeError:
                    fname = 'unknown'
                raise headers.Mp3Exception("Unable to find a valid mp3 frame in '%s'" % fname)

            try:
                self.mp3_header = headers.Mp3Header(header_int)
                log.debug("mp3 header %x found at position: 0x%x" %
                          (header_int, header_pos))
            except headers.Mp3Exception as ex:
                log.debug("Invalid mp3 header: %s" % str(ex))
                # keep looking...
                start_offset += 4

        file_obj.seek(header_pos)
        mp3_frame = file_obj.read(self.mp3_header.frame_length)
        if re.compile(b'Xing|Info').search(mp3_frame):
            # Check for Xing/Info header information.
            self.xing_header = headers.XingHeader()
            if not self.xing_header.decode(mp3_frame):
                log.debug("Ignoring corrupt Xing header")
                self.xing_header = None
        elif mp3_frame.find(b'VBRI') >= 0:
            # Check for VBRI header information.
            self.vbri_header = headers.VbriHeader()
            if not self.vbri_header.decode(mp3_frame):
                log.debug("Ignoring corrupt VBRI header")
                self.vbri_header = None

        # Check for LAME Tag
        self.lame_tag = headers.LameHeader(mp3_frame)

        # Set file size
        import stat
        self.size_bytes = os.stat(file_obj.name)[stat.ST_SIZE]

        # Compute track play time.
        tpf = None
        if self.xing_header and self.xing_header.vbr:
            tpf = timePerFrame(self.mp3_header, True)
            self.time_secs = int(tpf * self.xing_header.numFrames)
        elif self.vbri_header and self.vbri_header.version == 1:
            tpf = timePerFrame(self.mp3_header, True)
            self.time_secs = int(tpf * self.vbri_header.num_frames)
        else:
            tpf = timePerFrame(self.mp3_header, False)
            length = self.size_bytes
            if tag and tag.isV2():
                length -= tag.header.SIZE + tag.header.tag_size
                # Handle the case where there is a v2 tag and a v1 tag.
                file_obj.seek(-128, 2)
                if file_obj.read(3) == "TAG":
                    length -= 128
            elif tag and tag.isV1():
                length -= 128
            self.time_secs = int((length / self.mp3_header.frame_length) * tpf)

        # Compute bitate
        if (self.xing_header and self.xing_header.vbr and
                self.xing_header.numFrames): # if xing_header.numFrames == 0
                                             # ZeroDivisionError
            br = int((self.xing_header.numBytes * 8) /
                     (tpf * self.xing_header.numFrames * 1000))
            vbr = True
        else:
            br = self.mp3_header.bit_rate
            vbr = False
        self.bit_rate = (vbr, br)

        self.sample_freq = self.mp3_header.sample_freq
        self.mode = self.mp3_header.mode

    ##
    # Helper to get the bitrate as a string. The prefix '~' is used to denote
    # variable bit rates.
    @property
    def bit_rate_str(self):
       (vbr, bit_rate) = self.bit_rate
       brs = "%d kb/s" % bit_rate
       if vbr:
          brs = "~" + brs
       return brs

class Mp3AudioFile(core.AudioFile):
    '''Audio file container for mp3 files.'''

    def __init__(self, path, version=id3.ID3_ANY_VERSION):
        self._tag_version = version

        core.AudioFile.__init__(self, path)
        assert(self.type == core.AUDIO_MP3)

    def _read(self):
        with open(self.path, 'rb') as file_obj:
            self._tag = id3.Tag()
            tag_found = self._tag.parse(file_obj, self._tag_version)

            # Compute offset for starting mp3 data search
            if tag_found and self._tag.isV1():
                mp3_offset = 0
            elif tag_found and self._tag.isV2():
                mp3_offset = self._tag.header.SIZE + self._tag.header.tag_size
            else:
                mp3_offset = 0
                self._tag = None

            try:
                self._info = Mp3AudioInfo(file_obj, mp3_offset, self._tag)
            except Mp3Exception as ex:
                # Only logging a warning here since we can still operate on
                # the tag.
                log.warning(ex)
                self._info = None

            self.type = core.AUDIO_MP3

    def initTag(self, version=id3.ID3_DEFAULT_VERSION):
        '''Add a id3.Tag to the file (removing any existing tag if one exists).
        '''
        self.tag = id3.Tag()
        self.tag.version = version
        self.tag.file_info = id3.FileInfo(self.path)