开发者

Is it possible to remove actionScript from inside of SWF file using PHP?

The result should be clean SWF f开发者_JAVA百科ile.


Of course its possible, but you would have to read the file data and understand the structure of the file to know where the actionscript's are stored.

you can use PHP native functions such as

  • fopen
  • fseak
  • fread
  • flcose

Along with other binary tools such as

  • bin
  • dec
  • pack
  • <<, |, >>, & and other binary manipulation tools

To manipulate binary data, I suggest you start with the link below to understand the complexity of this:

http://wwwimages.adobe.com/www.adobe.com/content/dam/Adobe/en/devnet/swf/pdf/swf_file_format_spec_v10.pdf

Here's a pretty basic class that allows you to read data from a SWF or Compressed SWF File:

/**
* Base SWF class
*
* This class requires the File PEAR.
* Read the SWF header informations and return an
* associative array with the property of the SWF File, the result array
* will contain framerate, framecount, background color, compression, filetype
* version and movie size.
* <code>
* <?php
* require_once "File/File_SWF.php";
* $file = "any_file.swf";
*
* $swf = &new File_SWF($file);
* if($swf->isValid){
* $result = $swf->stat();
* print_r($result);
* }
* <?
* </code>
* @author Alessandro Crugnola <alessandro@sephiroth.it>
* @access public
* @version 0.2
* @package File_SWF
*/
class File_SWF
{
    /**
    * current unpacked binary string
    * @var mixed
    */
    var $current = "";
    /**
    * internal pointer
    * @var integer
    */
    var $position = 0;
    /**
    * use zlib compression
    * @var boolean
    */
    var $compression = 0;
    /**
    * current position
    * @var integer
    */
    var $point = 0;
    /**
    * is a valid swf
    * @var boolean
    * @access private
    */
    var $isValid = 0;
    /**
    * stirng file name to parse
    * @var string
    */
    var $file = "";
    /**
    * determine if file is protected
    * @var boolean
    */
    var $protected = false;
    /**
    * password for protected files
    * @var mixed
    */
    var $password;

    /**
    * Deconstructor
    * does anything right now
    * @access public
    */
    function _File_SWF()
    {
    }

    /**
    * Costructor
    * creates a new SWF object
    * reads the given file and parse it
    * @param string $file file to parse
    * @access public
    */
    function File_SWF($file="")
    {
        $this->compression = 0;
        $this->isValid = 0;
        $this->point = 0;
        $this->file = $file;
        $head = File::read($this->file, 3);
        if(PEAR::isError($head)){
            return $head;
        }
        File::rewind($this->file, "rb");
        if($head == "CWS"){
            $data = File::read($this->file, 8);
            $_data = gzuncompress(File::read($this->file, filesize($this->file)));
            $data = $data . $_data;
            $this->data = $data;
            $this->compression = 1;
            $this->isValid = 1;
        } else if ($head == "FWS"){
            $this->data = File::read($this->file, filesize($this->file));
            $this->isValid = 1;
        } else {
            /**
            * invalid SWF file, or invalid head tag found
            */
            $this->isValid = 0;
        }
        File::close($this->file, "rb");
    }

    /**
    * Is a valid SWF file
    * @return boolean
    * @access public
    */
    function is_valid()
    {
        return $this->isValid;
    }

    /**
    * Return if swf file is protected from import
    * @return boolean
    * @access public
    */
    function getProtected()
    {
        if($this->getVersion() >= 8){
            $this->_seek(31);
        } else {
            $this->_seek(26);
        }
        $data = $this->_readTag();
        $tag  = $data[0];
        $this->protected = $tag == 24;
        return $this->protected;
    }

    /**
    * Define import protection for the SWF
    * @param boolean $protect define is file must be protected
    * @access public
    */
    function setProtected($protect)
    {
        if($protect and !$this->protected){
            if($this->getVersion() >= 8){
                $pre = substr($this->data, 0, 31);
                $post = substr($this->data, 31);
            } else {
                $pre = substr($this->data, 0, 26);
                $post = substr($this->data, 26);
            }
            $middle = pack("v", 1536);
            $this->data = $pre . $middle . $post;
            $this->password = 0;
            $this->protected = true;
        } else if(!$protect and $this->protected){
            if($this->getVersion() >= 8){
                $pos = 31;
            } else {
                $pos = 26;
            }
            $this->_seek($pos);
            if($this->_readData()){
                $this->data = substr($this->data,0, $pos) . substr($this->data, $this->point - (is_string($this->password) == 1 ? 0 : 1));
            }
        }
    }

    /**
    * Return the current SWF frame rate
    * @return mixed integer frame rate in fps or Error if invalid file
    * @access public
    */
    function getFrameRate()
    {
        if(!$this->is_valid()){
            return PEAR::raiseError("Invalid SWF head TAG found in " . $this->file, PEAR_SWF_ID_ERR);
        }
        if($this->getVersion() >= 8){
            $this->_seek(16);
        } else {
            $this->_seek(17);
        }
        $fps = unpack('vrate',$this->_read(2));
        return $fps['rate']/256;
    }

    /**
    * Set the new Frame Rate
    * @access public
    */
    function setFrameRate($num)
    {
        if(!$this->is_valid()){
            return;
        }
        $num = intval($num);
        if($num > 0 and $num <= 120){
            $fps = pack('v', $num*256);
            if($this->getVersion() >= 8){
                $this->_seek(16);
                $this->data = substr($this->data, 0, 16) . $fps . substr($this->data, 18);
            } else {
                $this->_seek(17);
                $this->data = substr($this->data, 0, 17) . $fps . substr($this->data, 19);
            }
        }
    }

    /**
    * Return the current number of frames
    * @return mixed interger or error if invalid file format
    * @access public
    */
    function getFrameCount()
    {
        if(!$this->is_valid()){
            return PEAR::raiseError("Invalid SWF head TAG found in " . $this->file, PEAR_SWF_ID_ERR);
        }
        if($this->getVersion() >= 8){
            $this->_seek(18);
        } else {
            $this->_seek(19);
        }
        return $this->_readshort();
    }

    /**
    * Return the current movie size in pixel
    * @return mixed array or error if invalid file format
    * @access public
    */
    function getMovieSize()
    {
        if(!$this->is_valid()){
            return PEAR::raiseError("Invalid SWF head TAG found in " . $this->file, PEAR_SWF_ID_ERR);
        }
        $this->_seek(8);
        return $this->_readRect();
    }

    /**
    * Return the current file type (CWS, FWS)
    * @return mixed string or error if invalid file format
    * @access public
    */
    function getFileType()
    {
        if(!$this->is_valid()){
            return PEAR::raiseError("Invalid SWF head TAG found in " . $this->file, PEAR_SWF_ID_ERR);
        }
        $this->_seek(0);
        return $this->_read(3);
    }

    /**
    * Return the current compression used
    * @return mixed interger or error if invalid file format
    * @access public
    */
    function getCompression()
    {
        if(!$this->is_valid()){
            return PEAR::raiseError("Invalid SWF head TAG found in " . $this->file, PEAR_SWF_ID_ERR);
        }
        return $this->compression;
    }

    /**
    * Set the compression
    * @return string based on the compression used
    * @param integer $mode compression on/off
    * @access public
    */
    function setCompression($mode = 0)
    {
        if(!$this->is_valid()){
            return;
        }
        $data = "";
        $real_size = pack( "V", strlen($this->data));
        $this->data = substr($this->data, 0, 4) . $real_size . substr($this->data, 8, strlen($this->data));
        if($mode == 0){
            $this->compression = 0;
            $this->data = "FWS" . substr($this->data, 3);
            $_n1 = substr($this->data, 0, 8);
            $_n2 = substr($this->data, 8, strlen($this->data));
            $data = $_n1 . $_n2;
        } else if($mode == 1){
            $this->compression = 1;
            $this->data = "CWS" . substr($this->data, 3);
            $_n1 = substr($this->data, 0, 8);
            $_n2 = substr($this->data, 8, strlen($this->data));
            $_n3 = gzcompress($_n2);
            $data = $_n1 . $_n3;
        }
        return $data;
    }

    /**
    * Return the current version of player used
    * @return mixed interger or error if invalid file format
    * @access public
    */
    function getVersion()
    {
        if(!$this->is_valid()){
            return PEAR::raiseError("Invalid SWF head TAG found in " . $this->file, PEAR_SWF_ID_ERR);
        }
        $this->_seek(3);
        return $this->_readbyte();
    }

    /**
    * Return the current SWF file size
    * @return mixed interger or error if invalid file format
    * @access public
    */
    function filesize()
    {
        if(!$this->is_valid()){
            return PEAR::raiseError("Invalid SWF head TAG found in " . $this->file, PEAR_SWF_ID_ERR);
        }
        $this->_seek(4);
        $real_size = unpack( "Vnum", $this->_read(4) );
        if( $this->getCompression() ){
            $n = $this->data;
            $n = "CWS" . substr($n, 3, 8) . gzcompress(substr($n, 8, strlen($n)));
            $file_size = strlen( $n ) -3;
        } else {
            $file_size = strlen( $this->data )-3;
        }
        return array($file_size, $real_size['num'], "compressed" => $file_size, "real" => $real_size['num']);
    }

    /**
    * Return the current background color
    * @return mixed array or error if invalid file format
    * @access public
    */
    function getBackgroundColor()
    {
        if(!$this->is_valid()){
            return PEAR::raiseError("Invalid SWF head TAG found in " . $this->file, PEAR_SWF_ID_ERR);
        }
        if($this->getVersion() >= 8){
            $this->_seek(26);
        } else {
            $this->_seek(21);
        }
        return $this->_readData();
    }

    /**
    * Set the new background color
    * @param integer $r (0,255)
    * @param integer $g (0,255)
    * @param integer $b (0,255)
    * @access public
    */
    function setBackgroundColor($r=0, $g=0, $b=0)
    {
        if(!$this->is_valid()){
            return;
        }
        $color  = pack("C", $r);
        $color .= pack("C", $g);
        $color .= pack("C", $b);

        if($this->getVersion() >= 8){
            $data = substr($this->data, 0, 28);
            $data .= $color;
            $this->data = $data . substr($this->data, 31, strlen($this->data));
        } else {
            $data = substr($this->data, 0, 23);
            $data .= $color;
            $this->data = $data . substr($this->data, 26, strlen($this->data));
        }
    }

    /**
    * Save current swf as a new file
    * @param string $filename filename
    * @param boolean $overwrite overwrite existing file
    * @return boolean true if saved succesfully
    * @access public
    */
    function write($filename, $overwrite = 1)
    {
        if(!$this->is_valid()){
            return false;
        }
        if(is_writeable(dirname($filename))){
            if(is_file($filename)){
                if($overwrite == 0){
                    return false;
                }
            }
            $newdata = $this->setCompression($this->getCompression());
            File::write ($filename, $newdata, $mode = "wb");
            File::close($filename, "wb");
            return true;
        } else {
            return false;
        }
    }

    /**
    * reads the SWF header
    * @return mixed associative array or error on fault
    * @access private
    */
    function stat()
    {
        if(!$this->is_valid()){
            return PEAR::raiseError("Invalid SWF head TAG found in " . $this->file, PEAR_SWF_ID_ERR);
        }
        $filetype = $this->getFileType();
        $version = $this->getVersion();
        $filelength = $this->filesize();
        $rect = $this->getMovieSize();
        $framerate = $this->getFrameRate();
        $framecount = $this->getFrameCount();
        $background = $this->getBackgroundColor();
        $protection = $this->getProtected();
        return array(
            "zlib-compression" => $this->getCompression(),
            "fileType" => $filetype,
            "version" => $version,
            "fileSize" => $filelength,
            "frameRate" => $framerate,
            "frameCount" => $framecount,
            "movieSize" => $rect,
            "background" => $background,
            "protected" => $protection,
        );
    }

    /**
    * read tag type, tag length
    * @return array
    * @access private
    */
    function _readTag()
    {
        $n = $this->_readshort();
        if($n == 0)
        {
            return false;
        }
        $tagn = $n>>6;
        $length = $n&0x3F;
        if($length == 0x3F)
        {
            $length = $this->_readlong();
        }
        return array($tagn,$length);
    }

    /**
    * read long
    * @access private
    */
    function _readlong(){
        $ret = unpack("Nnum", $this->_read(4));
        return $ret['num'];
    }

    /**
    * read data of next tag
    * @return array
    * @access private
    */
    function _readData()
    {
        $tag = $this->_readTag();
        $tagn = $tag[0];
        $length = $tag[1];
        if($tagn == 9)
        {
            $r = $this->_readbyte();
            $g = $this->_readbyte();
            $b = $this->_readbyte();
            $data = array($r,$g,$b, "hex" => sprintf("#%X%X%X", $r, $g, $b));
            return $data;
        } else if($tagn == 24)
        {
            if($this->_readbyte() == 0x00){
                $this->_readbyte();
                $this->password = $this->_readstring();
            } else {
                $this->password = 0;
            }
            return true;
        }
        return array();
    }

    /**
    * read a string
    * @return string
    * @access private
    */
    function _readstring()
    {
        $s = "";
        while(true){
            $ch = $this->_read(1);
            if($this->point > strlen($this->data)){
                break;
            }
            if($ch == "\x00"){
                break;
            }
            $s .= $ch;
        }
        return $s;
    }


    /**
    * read internal data file
    * @param integer $n number of byte to read
    * @return array
    * @access private
    */
    function _read($n)
    {
        $ret = substr($this->data, $this->point, $n);
        $this->point += $n;
        return $ret;
    }

    /**
    * move the internal pointer
    * @param integer $num
    * @access private
    */
    function _seek($num){
        if($num < 0){
            $num = 0;
        } else if($num > strlen($this->data)){
            $num = strlen($this->data);
        }
        $this->point = $num;
    }

    /**
    * read short
    * @return string
    * @access private
    */
    function _readshort(){
        $pack = unpack('vshort',$this->_read(2));
        return $pack['short'];
    }

    /**
    * read single byte
    * @return string
    * @access private
    */
    function _readByte(){
        $ret = unpack("Cbyte",$this->_read(1));
        return $ret['byte'];
    }
    /**
    * read a rect type
    * @return rect
    * @access private
    */
    function _readRect(){
        $this->_begin();
        $l = $this->_readbits(5);
        $xmin = $this->_readbits($l)/20;
        $xmax = $this->_readbits($l)/20;
        $ymin = $this->_readbits($l)/20;
        $ymax = $this->_readbits($l)/20;
        $rect = array(
            $xmax,
            $ymax,
            "width" => $xmax,
            "height" => $ymax
        );
        return $rect;
    }

    /**
    * read position internal to rect
    * @access private
    */
    function _incpos(){
        $this->position += 1;
        if($this->position>8){
            $this->position = 1;
            $this->current = $this->_readbyte();
        }
    }
    /**
    * read bites
    * @param integer $nbits number of bits to read
    * @return string
    * @access private
    */
    function _readbits($nbits){
        $n = 0;
        $r = 0;
        while($n < $nbits){
            $r = ($r<<1) + $this->_getbits($this->position);
            $this->_incpos();
            $n += 1;
        }
        return $r;
    }

    /**
    * getbits
    * @param integer $n
    * @return long
    * @access private
    */
    function _getbits($n){
        return ($this->current>>(8-$n))&1;
    }

    /**
    * begin reading of rect object
    * @access private
    */
    function _begin(){
        $this->current = $this->_readbyte();
        $this->position = 1;
    }
}
?>

Source: http://www.sephiroth.it/swfreader.php

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜