PageRenderTime 14ms CodeModel.GetById 2ms app.highlight 9ms RepoModel.GetById 1ms app.codeStats 0ms

/src/Zend/Media/Asf.php

http://php-reader.googlecode.com/
PHP | 222 lines | 124 code | 15 blank | 83 comment | 20 complexity | 5b7a87b993df8c4034c13cd71f8deab0 MD5 | raw file
  1<?php
  2/**
  3 * Zend Framework
  4 *
  5 * LICENSE
  6 *
  7 * This source file is subject to the new BSD license that is bundled
  8 * with this package in the file LICENSE.txt.
  9 * It is also available through the world-wide-web at this URL:
 10 * http://framework.zend.com/license/new-bsd
 11 * If you did not receive a copy of the license and are unable to
 12 * obtain it through the world-wide-web, please send an email
 13 * to license@zend.com so we can send you a copy immediately.
 14 *
 15 * @category   Zend
 16 * @package    Zend_Media
 17 * @subpackage ASF
 18 * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
 19 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 20 * @version    $Id: Asf.php 272 2012-03-29 19:53:29Z svollbehr $
 21 */
 22
 23/**#@+ @ignore */
 24require_once 'Zend/Media/Asf/Object/Container.php';
 25/**#@-*/
 26
 27/**
 28 * This class represents a file in Advanced Systems Format (ASF) as described in
 29 * {@link http://go.microsoft.com/fwlink/?LinkId=31334 The Advanced Systems
 30 * Format (ASF) Specification}. It is a file format that can contain various
 31 * types of information ranging from audio and video to script commands and
 32 * developer defined custom streams.
 33 *
 34 * The ASF file consists of code blocks that are called content objects. Each
 35 * of these objects have a format of their own. They may contain other objects
 36 * or other specific data. Each supported object has been implemented as their
 37 * own classes to ease the correct use of the information.
 38 *
 39 * @category   Zend
 40 * @package    Zend_Media
 41 * @subpackage ASF
 42 * @author     Sven Vollbehr <sven@vollbehr.eu>
 43 * @author     Elias Haapam?ki <elias.haapamaki@turunhelluntaisrk.fi>
 44 * @copyright  Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
 45 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 46 * @version    $Id: Asf.php 272 2012-03-29 19:53:29Z svollbehr $
 47 */
 48class Zend_Media_Asf extends Zend_Media_Asf_Object_Container
 49{
 50    /** @var string */
 51    private $_filename;
 52
 53    /**
 54     * Constructs the ASF class with given file and options.
 55     *
 56     * The following options are currently recognized:
 57     *   o encoding -- Indicates the encoding that all the texts are presented
 58     *     with. By default this is set to utf-8. See the documentation of iconv
 59     *     for accepted values.
 60     *   o readonly -- Indicates that the file is read from a temporary location
 61     *     or another source it cannot be written back to.
 62     *
 63     * @param string|resource|Zend_Io_Reader $filename The path to the file,
 64     *  file descriptor of an opened file, or a {@link Zend_Io_Reader} instance.
 65     * @param Array                          $options  The options array.
 66     */
 67    public function __construct($filename, $options = array())
 68    {
 69        if ($filename instanceof Zend_Io_Reader) {
 70            $this->_reader = &$filename;
 71        } else {
 72            require_once 'Zend/Io/FileReader.php';
 73            try {
 74                $this->_reader = new Zend_Io_FileReader($filename);
 75            } catch (Zend_Io_Exception $e) {
 76                $this->_reader = null;
 77                require_once 'Zend/Media/Id3/Exception.php';
 78                throw new Zend_Media_Asf_Exception($e->getMessage());
 79            }
 80            if (is_string($filename) && !isset($options['readonly'])) {
 81                $this->_filename = $filename;
 82            }
 83        }
 84        $this->setOptions($options);
 85        if ($this->getOption('encoding', null) === null) {
 86            $this->setOption('encoding', 'utf-8');
 87        }
 88        $this->setOffset(0);
 89        $this->setSize($this->_reader->getSize());
 90        $this->constructObjects
 91            (array
 92             (self::HEADER => 'Header',
 93                self::DATA => 'Data',
 94                self::SIMPLE_INDEX => 'SimpleIndex',
 95                self::INDEX => 'Index',
 96                self::MEDIA_OBJECT_INDEX => 'MediaObjectIndex',
 97                self::TIMECODE_INDEX => 'TimecodeIndex'));
 98    }
 99
100    /**
101     * Returns the mandatory header object contained in this file.
102     *
103     * @return Zend_Media_Asf_Object_Header
104     */
105    public function getHeader()
106    {
107        $header = $this->getObjectsByIdentifier(self::HEADER);
108        return $header[0];
109    }
110
111    /**
112     * Returns the mandatory data object contained in this file.
113     *
114     * @return Zend_Media_Asf_Object_Data
115     */
116    public function getData()
117    {
118        $data = $this->getObjectsByIdentifier(self::DATA);
119        return $data[0];
120    }
121
122    /**
123     * Returns an array of index objects contained in this file.
124     *
125     * @return Array
126     */
127    public function getIndices()
128    {
129        return $this->getObjectsByIdentifier
130            (self::SIMPLE_INDEX . '|' . self::INDEX . '|' .
131             self::MEDIA_OBJECT_INDEX . '|' . self::TIMECODE_INDEX);
132    }
133
134    /**
135     * Writes the changes to given media file. All object offsets must be
136     * assumed to be invalid after the write operation.
137     *
138     * @param string $filename The optional path to the file, use null to save
139     *                         to the same file.
140     */
141    public function write($filename)
142    {
143        if ($filename === null && ($filename = $this->_filename) === null) {
144            require_once 'Zend/Media/Asf/Exception.php';
145            throw new Zend_Media_Asf_Exception
146                ('No file given to write to');
147        } else if ($filename !== null && $this->_filename !== null &&
148                   realpath($filename) != realpath($this->_filename) &&
149                   !copy($this->_filename, $filename)) {
150            require_once 'Zend/Media/Asf/Exception.php';
151            throw new Zend_Media_Asf_Exception
152                ('Unable to copy source to destination: ' .
153                 realpath($this->_filename) . '->' . realpath($filename));
154        }
155
156        if (($fd = fopen
157             ($filename, file_exists($filename) ? 'r+b' : 'wb')) === false) {
158            require_once 'Zend/Media/Asf/Exception.php';
159            throw new Zend_Media_Asf_Exception
160                ('Unable to open file for writing: ' . $filename);
161        }
162
163        $header = $this->getHeader();
164        $headerLengthOld = $header->getSize();
165        $header->removeObjectsByIdentifier(Zend_Media_Asf_Object::PADDING);
166        $header->headerExtension->removeObjectsByIdentifier
167            (Zend_Media_Asf_Object::PADDING);
168
169        require_once 'Zend/Io/StringWriter.php';
170        $buffer = new Zend_Io_StringWriter();
171        $header->write($buffer);
172        $headerData = $buffer->toString();
173        $headerLengthNew = $header->getSize();
174
175        // Fits right in
176        if ($headerLengthOld == $headerLengthNew) {
177        }
178
179        // Fits with adjusted padding
180        else if ($headerLengthOld >= $headerLengthNew + 24 /* for header */) {
181            $header->headerExtension->padding->setSize
182                ($headerLengthOld - $headerLengthNew);
183            $buffer = new Zend_Io_StringWriter();
184            $header->write($buffer);
185            $headerData = $buffer->toString();
186            $headerLengthNew = $header->getSize();
187        }
188
189        // Must expand
190        else {
191            $header->headerExtension->padding->setSize(4096);
192            $buffer = new Zend_Io_StringWriter();
193            $header->write($buffer);
194            $headerData = $buffer->toString();
195            $headerLengthNew = $header->getSize();
196
197            fseek($fd, 0, SEEK_END);
198            $oldFileSize = ftell($fd);
199            ftruncate
200                ($fd, $newFileSize = $headerLengthNew - $headerLengthOld +
201                 $oldFileSize);
202             for ($i = 1, $cur = $oldFileSize; $cur > 0; $cur -= 1024, $i++) {
203                if ($cur >= 1024) {
204                    fseek($fd, -(($i * 1024) +
205                            ($newFileSize - $oldFileSize)), SEEK_END);
206                    $buffer = fread($fd, 1024);
207                    fseek($fd, -($i * 1024), SEEK_END);
208                    fwrite($fd, $buffer, 1024);
209                } else {
210                    fseek($fd, 0);
211                    $buffer = fread($fd, $cur);
212                    fseek($fd, $newFileSize - $oldFileSize);
213                    fwrite($fd, $buffer, $cur);
214                }
215            }
216        }
217
218        fseek($fd, 0);
219        fwrite($fd, $headerData, $headerLengthNew);
220        fclose($fd);
221    }
222}