<?php //-----------------------------------------------------------------------------
// SWF HEADER - version 1.0
// Small utility class to determine basic data from a SWF file header
// Does not need any php-flash extension, based on raw binary data reading
//-----------------------------------------------------------------------------
//	SWFHEADER CLASS - PHP SWF header parser
//	Copyright (C) 2004  Carlos Falo Herv�s
//
//	This library is free software; you can redistribute it and/or
//	modify it under the terms of the GNU Lesser General Public
//	License as published by the Free Software Foundation; either
//	version 2.1 of the License, or (at your option) any later version.
//
//	This library 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
//	Lesser General Public License for more details.
//
//	You should have received a copy of the GNU Lesser General Public
//	License along with this library; if not, write to the Free Software
//	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//-----------------------------------------------------------------------------

class swfheader
{
    public $debug;				// Output DEBUG info
    public $fname;				// SWF file analyzed
    public $magic;				// Magic in a SWF file (FWS or CWS)
    public $compressed;		// Flag to indicate a compressed file (CWS)
    public $version;			// Flash version
    public $size;					// Uncompressed file size (in bytes)
    public $width;				// Flash movie native width
    public $height;				// Flash movie native height
    public $valid;				// Valid SWF file
    public $fps;					// Flash movie native frame-rate
    public $frames;				// Flash movie total frames

    //---------------------------------------------------------------------------
    // swfheader($debug) : 	Constructor, basically does nothing but initilize
    //											debug and data fields
    //---------------------------------------------------------------------------
    public function __construct($debug = false)
    {
        $this->debug = $debug;
        $this->init();
    }

    //---------------------------------------------------------------------------
    // init() : initialize the data fields to "empty" values
    //---------------------------------------------------------------------------
    public function init()
    {
        $this->valid = false;
        $this->fname = '';
        $this->magic = '';
        $this->compressed = false;
        $this->version = 0;
        $this->width = 0;
        $this->height = 0;
        $this->size = 0;
        $this->frames = 0;
        $this->fps[] = [];
        if ($this->debug) {
            echo 'DEBUG: Data values initialized<br>';
        }
    }

    //---------------------------------------------------------------------------
    // loadswf($filename) : loads $filename and stores data from it's header
    //---------------------------------------------------------------------------
    public function loadswf($filename)
    {
        $this->fname = $filename;
        $fp = @fopen($filename, 'rb');
        if ($fp) {
            if ($this->debug) {
                echo 'DEBUG: Opened ' . $this->fname . '<br>';
            }
            // Read MAGIC FIELD
            $this->magic = fread($fp, 3);
            if ($this->magic != 'FWS' && $this->magic != 'CWS') {
                if ($this->debug) {
                    echo 'DEBUG: ' . $this->fname . ' is not a valid/supported SWF file<br>';
                }
                $this->valid = 0;
            } else {
                // Compression
                if (substr($this->magic, 0, 1) == 'C') {
                    $this->compressed = true;
                } else {
                    $this->compressed = false;
                }
                if ($this->debug) {
                    echo 'DEBUG: Read MAGIC signature: ' . $this->magic . '<br>';
                }
                // Version
                $this->version = ord(fread($fp, 1));
                if ($this->debug) {
                    echo 'DEBUG: Read VERSION: ' . $this->version . '<br>';
                }
                // Size
                $lg = 0;
                // 4 LSB-MSB
                for ($i = 0; $i < 4; ++$i) {
                    $t = ord(fread($fp, 1));
                    if ($this->debug) {
                        echo 'DEBUG: Partial SIZE read: ' . ($t << (8 * $i)) . '<br>';
                    }
                    $lg += ($t << (8 * $i));
                }
                $this->size = $lg;
                if ($this->debug) {
                    echo 'DEBUG: Total SIZE: ' . $this->size . '<br>';
                }
                // RECT... we will "simulate" a stream from now on... read remaining file
                $buffer = fread($fp, $this->size);
                if ($this->compressed) {
                    // First decompress GZ stream
                    $buffer = gzuncompress($buffer, $this->size);
                }
                $b = ord(substr($buffer, 0, 1));
                $buffer = substr($buffer, 1);
                $cbyte = $b;
                $bits = $b >> 3;
                if ($this->debug) {
                    echo 'DEBUG: RECT field size: ' . $bits . ' bits<br>';
                }
                $cval = '';
                // Current byte
                $cbyte &= 7;
                $cbyte <<= 5;
                // Current bit (first byte starts off already shifted)
                $cbit = 2;
                // Must get all 4 values in the RECT
                for ($vals = 0; $vals < 4; ++$vals) {
                    $bitcount = 0;
                    while ($bitcount < $bits) {
                        if ($cbyte & 128) {
                            $cval .= '1';
                        } else {
                            $cval .= '0';
                        }
                        $cbyte <<= 1;
                        $cbyte &= 255;
                        --$cbit;
                        ++$bitcount;
                        // We will be needing a new byte if we run out of bits
                        if ($cbit < 0) {
                            $cbyte = ord(substr($buffer, 0, 1));
                            $buffer = substr($buffer, 1);
                            $cbit = 7;
                        }
                    }
                    // O.k. full value stored... calculate
                    $c = 1;
                    $val = 0;
                    // Reverse string to allow for SUM(2^n*$atom)
                    if ($this->debug) {
                        echo 'DEBUG: RECT binary value: ' . $cval;
                    }
                    $tval = strrev($cval);
                    for ($n = 0; $n < strlen($tval); ++$n) {
                        $atom = substr($tval, $n, 1);
                        if ($atom == '1') {
                            $val += $c;
                        }
                        // 2^n
                        $c *= 2;
                    }
                    // TWIPS to PIXELS
                    $val /= 20;
                    if ($this->debug) {
                        echo ' (' . $val . ')<br>';
                    }
                    switch ($vals) {
                        case 0:
                            // tmp value
                            $this->width = $val;
                        break;
                        case 1:
                            $this->width = $val - $this->width;
                        break;
                        case 2:
                            // tmp value
                            $this->height = $val;
                        break;
                        case 3:
                            $this->height = $val - $this->height;
                        break;
                      }
                    $cval = '';
                }
                // Frame rate
                $this->fps = [];
                for ($i = 0; $i < 2; ++$i) {
                    $t = ord(substr($buffer, 0, 1));
                    $buffer = substr($buffer, 1);
                    $this->fps[] = $t;
                }
                if ($this->debug) {
                    echo 'DEBUG: Frame rate: ' . $this->fps[1] . '.' . $this->fps[0] . '<br>';
                }
                // Frames
                $this->frames = 0;
                for ($i = 0; $i < 2; ++$i) {
                    $t = ord(substr($buffer, 0, 1));
                    $buffer = substr($buffer, 1);
                    $this->frames += ($t << (8 * $i));
                }
                if ($this->debug) {
                    echo 'DEBUG: Frames: ' . $this->frames . '<br>';
                }
                fclose($fp);
                if ($this->debug) {
                    echo 'DEBUG: Finished processing ' . $this->fname . '<br>';
                }
                $this->valid = 1;
            }
        } else {
            $this->valid = 0;
            if ($this->debug) {
                echo 'DEBUG: Failed to open ' . $this->fname . '<br>';
            }
        }

        return $this->valid;
    }

    //---------------------------------------------------------------------------
    // show() : report to screen all the header info
    //---------------------------------------------------------------------------
    public function show()
    {
        if ($this->valid) {
            // FNAME
            echo '<b>FILE: ' . $this->fname . '</b><br>';
            // Magic
            echo '<b>MAGIC:</b> ' . $this->magic;
            if ($this->compressed) {
                echo ' (COMPRESSED)';
            }
            echo '<br>';
            // Version
            echo '<b>VERSION:</b> ' . $this->version . '<br>';
            // Size
            echo '<b>SIZE:</b> ' . $this->size . ' bytes <br>';
            // FRAMESIZE
            echo '<b>WIDHT:</B> ' . $this->width . '<br>';
            echo '<b>HEIGHT:</B> ' . $this->height . '<br>';
            // FPS
            echo '<b>FPS:</b> ' . $this->fps[1] . '.' . $this->fps[0] . ' Frames/s <br>';
            // FRAMES
            echo '<b>FRAMES:</b> ' . $this->frames . ' FRAME <br>';
        } else {
            if (file_exists($this->fname)) {
                echo $this->fname . 'is not a valid SWF file<br>';
            } elseif ($this->fname == '') {
                echo 'SWFHEADER->SHOW : No file loaded<br>';
            } else {
                echo 'SWFHEDAR->SHOW : ' . $this->fname . 'was not found<br>';
            }
        }
    }

    //---------------------------------------------------------------------------
    // display($trans) : just echo <OBJECT>/<EMBED> tags for the parsed file, if
    //									 trans is set, WMODE is set to transparent
    //---------------------------------------------------------------------------
    public function display($trans = false, $qlty = 'high', $bgcolor = '#ffffff', $name = '')
    {
        $endl = chr(13);

        if ($this->valid) {
            if ($name == '') {
                $name = substr($this->fname, 0, strrpos($this->fname, '.'));
            }
            echo '<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=' . $this->version . ',0,0,0" width="' . $this->width . '" height="' . $this->height . '" id="' . $name . '" align="middle">' . $endl;
            echo '<param name="allowScriptAccess" value="sameDomain" />' . $endl;
            if ($trans) {
                echo '<param name="wmode" value="transparent" />' . $endl;
            }
            echo '<param name="movie" value="' . $this->fname . '" />' . $endl;
            echo '<param name="quality" value="' . $qlty . '" />' . $endl;
            echo '<param name="bgcolor" value="' . $bgcolor . '" />' . $endl;
            echo '<embed src="' . $this->fname . '" ';
            if ($trans) {
                echo 'wmode="transparent" ';
            }
            echo 'quality="' . $qlty . '" bgcolor="' . $bgcolor . '" width="' . $this->width . '" height="' . $this->height . '" name="' . $name . '" align="middle" allowScriptAccess="sameDomain" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" />' . $endl;
            echo '</object>' . $endl;
        } else {
            if ($this->debug) {
                if ($this->fname == '') {
                    echo 'SWFHEADER->DISPLAY : No loaded file in the object<br>';
                } else {
                    if (file_exists($this->fname)) {
                        echo 'SWFHEADER->DISPLAY : ' . $this->fname . ' is not a valid SWF file<br>';
                    } else {
                        echo 'SWFHEADER->DISPLAY : ' . $this->fname . ' was not found<br>';
                    }
                }
            }
        }
    }
}
?>

