Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 37
0.00% covered (danger)
0.00%
0 / 10
CRAP
0.00% covered (danger)
0.00%
0 / 1
File_Ogg_Media
0.00% covered (danger)
0.00%
0 / 37
0.00% covered (danger)
0.00%
0 / 10
506
0.00% covered (danger)
0.00%
0 / 1
 getType
n/a
0 / 0
n/a
0 / 0
0
 getIdentificationString
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 _decodeCommonHeader
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
30
 _decodeBareCommentsHeader
0.00% covered (danger)
0.00%
0 / 17
0.00% covered (danger)
0.00%
0 / 1
56
 getCommentList
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getField
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
12
 getComments
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getVendor
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getHeader
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getLength
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getStartOffset
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2/* vim: set expandtab tabstop=4 shiftwidth=4: */
3// +----------------------------------------------------------------------------+
4// | File_Ogg PEAR Package for Accessing Ogg Bitstreams                         |
5// | Copyright (c) 2005-2007                                                    |
6// | David Grant <david@grant.org.uk>                                           |
7// | Tim Starling <tstarling@wikimedia.org>                                     |
8// +----------------------------------------------------------------------------+
9// | This library is free software; you can redistribute it and/or              |
10// | modify it under the terms of the GNU Lesser General Public                 |
11// | License as published by the Free Software Foundation; either               |
12// | version 2.1 of the License, or (at your option) any later version.         |
13// |                                                                            |
14// | This library is distributed in the hope that it will be useful,            |
15// | but WITHOUT ANY WARRANTY; without even the implied warranty of             |
16// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU          |
17// | Lesser General Public License for more details.                            |
18// |                                                                            |
19// | You should have received a copy of the GNU Lesser General Public           |
20// | License along with this library; if not, write to the Free Software        |
21// | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA |
22// +----------------------------------------------------------------------------+
23use MediaWiki\TimedMediaHandler\Handlers\OggHandler\OggException;
24
25/**
26 * Parent class for media bitstreams
27 * Contains some functions common to various media formats
28 */
29abstract class File_Ogg_Media extends File_Ogg_Bitstream
30{
31    /**
32     * Maximum size of header comment to parse.
33     * Set to 1 MB by default. Make sure this is less than your PHP memory_limit.
34     */
35    private const COMMENT_MAX_SIZE = 1000000;
36
37    /**
38     * Array to hold each of the comments.
39     *
40     * @access  private
41     * @var     array
42     */
43    var $_comments = array();
44
45    /**
46     * Vendor string for the stream.
47     *
48     * @access  private
49     * @var     string
50     */
51    var $_vendor;
52
53    /**
54     * Length of the stream in seconds
55     */
56    var $_streamLength;
57
58    /* Start offset of the stream in seconds */
59    var $_startOffset = 0;
60
61    /**
62     * Average bitrate for the stream.
63     *
64     * @access  private
65     * @var     float
66     */
67    var $_avgBitrate;
68
69    /**
70     * Get a short string describing the type of the stream
71     * @return string
72     */
73    abstract function getType();
74
75    /**
76     * Get the 6-byte identification string expected in the common header
77     * @return string
78     */
79    function getIdentificationString()
80    {
81        return '';
82    }
83
84    /**
85     * @access  private
86     * @param   int|false $packetType
87     * @param   int       $pageOffset
88     */
89    function _decodeCommonHeader($packetType, $pageOffset)
90    {
91        fseek($this->_filePointer, $this->_streamData['pages'][$pageOffset]['body_offset'], SEEK_SET);
92        if ($packetType !== false) {
93            // Check if this is the correct header.
94            $packet = unpack("Cdata", fread($this->_filePointer, 1));
95            if ($packet['data'] != $packetType)
96                throw new OggException("Stream Undecodable", OGG_ERROR_UNDECODABLE);
97
98            // The following six characters should be equal to getIdentificationString()
99            $id = $this->getIdentificationString();
100            if ($id !== '' && fread($this->_filePointer, strlen($id)) !== $id)
101                throw new OggException("Stream is undecodable due to a malformed header.", OGG_ERROR_UNDECODABLE);
102        } // else seek only, no common header
103    }
104
105    /**
106     * Parse a Vorbis-style comments header.
107     *
108     * This function parses the comments header.  The comments header contains a series of
109     * UTF-8 comments related to the audio encoded in the stream.  This header also contains
110     * a string to identify the encoding software.  More details on the comments header can
111     * be found at the following location: http://xiph.org/vorbis/doc/v-comment.html
112     *
113     * @access  private
114     */
115    function _decodeBareCommentsHeader()
116    {
117        // Decode the vendor string length as a 32-bit unsigned integer.
118        $vendor_len = unpack("Vdata", fread($this->_filePointer, 4));
119        if ( $vendor_len['data'] > 0 ) {
120            // Retrieve the vendor string from the stream.
121            $this->_vendor  = fread($this->_filePointer, $vendor_len['data']);
122        } else {
123            $this->_vendor = '';
124        }
125        // Decode the size of the comments list as a 32-bit unsigned integer.
126        $comment_list_length = unpack("Vdata", fread($this->_filePointer, 4));
127        // Iterate through the comments list.
128        for ($i = 0; $i < $comment_list_length['data']; ++$i) {
129            // Unpack the length of this comment.
130            $comment_length = unpack("Vdata", fread($this->_filePointer, 4));
131
132            if ( $comment_length['data'] <= 0 || $comment_length['data'] > self::COMMENT_MAX_SIZE ) {
133                continue;
134            }
135
136            // Comments are in the format 'ARTIST=Super Furry Animals', so split it on the equals character.
137            // NOTE: Equals characters are strictly prohibited in the title part of a comment
138            $comment        = explode("=", fread($this->_filePointer, $comment_length['data']), 2);
139            $comment_title  = (string) $comment[0];
140            $comment_value  = (string)( $comment[1] ?? '' );
141
142            // Check if the comment type (e.g. ARTIST) already exists.  If it does,
143            // take the new value, and the existing value (or array) and insert it
144            // into a new array.  This is important, since each comment type may have
145            // multiple instances (e.g. ARTIST for a collaboration) and we should not
146            // overwrite the previous value.
147            if (isset($this->_comments[$comment_title])) {
148                if (is_array($this->_comments[$comment_title]))
149                    $this->_comments[$comment_title][] = $comment_value;
150                else
151                    $this->_comments[$comment_title] = array($this->_comments[$comment_title], $comment_value);
152            } else
153                $this->_comments[$comment_title] = $comment_value;
154        }
155    }
156
157    /**
158     * Provides a list of the comments extracted from the Vorbis stream.
159     *
160     * It is recommended that the user fully inspect the array returned by this function
161     * rather than blindly requesting a comment in false belief that it will always
162     * be present.  Whilst the Vorbis specification dictates a number of popular
163     * comments (e.g. TITLE, ARTIST, etc.) for use in Vorbis streams, they are not
164     * guaranteed to appear.
165     *
166     * @access  public
167     * @return  array
168     */
169    function getCommentList()
170    {
171        return (array_keys($this->_comments));
172    }
173
174    /**
175     * Provides an interface to the numerous comments located with a Vorbis stream.
176     *
177     * A Vorbis stream may contain one or more instances of each comment, so the user
178     * should check the variable type before printing out the result of this method.
179     * The situation in which multiple instances of a comment occurring are not as
180     * rare as one might think, since they are conceivable at least for ARTIST comments
181     * in the situation where a track is a duet.
182     *
183     * @access  public
184     * @param   string  $commentTitle   Comment title to search for, e.g. TITLE.
185     * @param   string  $separator      String to separate multiple values.
186     * @return  string
187     */
188    function getField($commentTitle, $separator = ", ")
189    {
190    if (isset($this->_comments[$commentTitle])) {
191        if (is_array($this->_comments[$commentTitle]))
192            return (implode($separator, $this->_comments[$commentTitle]));
193        else
194            return ($this->_comments[$commentTitle]);
195    } else
196        // The comment doesn't exist in this file.  The user should've called getCommentList first.
197        return ("");
198    }
199
200    /**
201     * Get the entire comments array.
202     * May return an empty array if the bitstream does not support comments.
203     *
204     * @access  public
205     * @return  array
206     */
207    function getComments() {
208        return $this->_comments;
209    }
210
211    /**
212     * Vendor of software used to encode this stream.
213     *
214     * Gives the vendor string for the software used to encode this stream.
215     * It is common to find libVorbis here.  The majority of encoders appear
216     * to use libvorbis from Xiph.org.
217     *
218     * @access  public
219     * @return  string
220     */
221    function getVendor()
222    {
223        return ($this->_vendor);
224    }
225
226    /**
227     * Get an associative array containing header information about the stream
228     * @access  public
229     * @return  array
230     */
231    function getHeader()
232    {
233        return array();
234    }
235
236    /**
237     * Get the length of the stream in seconds
238     * @return float
239     */
240    function getLength()
241    {
242        return $this->_streamLength;
243    }
244    /**
245     * Get the start offset of the stream in seconds
246     *
247     * @return float
248     */
249    function getStartOffset(){
250        return $this->_startOffset;
251    }
252}