0
結果應該是clean SWF文件。是否可以使用PHP從SWF文件中刪除actionScript?
結果應該是clean SWF文件。是否可以使用PHP從SWF文件中刪除actionScript?
當然可能,但您必須閱讀文件數據並瞭解文件的結構才能知道動作的存儲位置。
你可以使用PHP自身的功能,如
隨着其他二進制工具,如
要處理的二進制數據,我建議你先從下面的鏈接瞭解複雜這個:
這裏是一個非常基本的T類帽子可以讓你從一個SWF文件或壓縮的SWF文件中讀取數據:
/**
* 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 <[email protected]>
* @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;
}
}
?>
非常感謝!我會看看它。 – Zap 2011-05-06 12:31:20