一共有 24 篇文章,分页:2 / 5

swfread——从swf中提取图片的小工具

闪客精灵和asv都可以从swf中提取图片,但是图片和导出as类链接的对应关系没有导出,最近看了一下swf文件格式,除了doabc代码比较复杂,其他tag导出还是比较简单的,swf中和图片关联的tag有:DefineBitsLossless,DefineBitsJPEG2,DefineBitsLossless2,DefineBitsJPEG3,参照了网上其他开源项目的代码,用C写了一个工具:swfread.exe,可以把swf里面的png、jpg等图片素材全部提取出来。

11月15日更新:支持中文类名

12月25日更新:支持zws为标识的lzma压缩算法

工具名称:提取swf中的图片 使用说明:swfread.exe a.swf b.swf c.swf (或可直接拖动多个swf到图标上)

附件下载:swfread.zip(133KB)

(注意:本程序并没有病毒或其他破坏性的代码,请注意chrome浏览器中下载时会提示:不是常见的下载类型,可能存在危险。如不放心,请勿使用)

顺带推荐一下我写的另一个小工具,可以从任意进程里提取swf出来:swfdump

AS3从未知编码的二进制流中自适应编码读取文本

给你一个文件或者二进制,不知道编码是gb2312还是utf8的情况下怎么正确读取出文本呢?

以下代码是as3的,其他编程语言只要稍微改动一下即可。

上代码,请直接用!

感谢C++ BLOG提供的判断utf8的方法:http://hi.baidu.com/xingyan126/item/4abec1c1c2143755bcef6956

/** 
 * 从未知编码的二进制流中读取文本 
 * @param   ba 
 * @param   len 读取长度,默认为-1,则读取至文件尾 
 * @return 
 */ 
public static function readString(ba:ByteArray,len:int = -1):String 
{ 
    if ((len != -1 && len > ba.bytesAvailable) || (len == -1)) len = ba.bytesAvailable; 
    var encode:String = 'gb2312'; 
    //先判断头三个字节是不是utf bom 
    if (ba.bytesAvailable >= 3) 
    { 
        //0xEF 0xBB 0xBF 
        var chkarr:Array = []; 
        var a:int = 0xffffffEF; 
        var b:int = 0xffffffBB; 
        var c:int = 0xffffffBF; 
        chkarr.push(ba.readByte()); 
        chkarr.push(ba.readByte()); 
        chkarr.push(ba.readByte()); 
        if ((chkarr[0] == a && chkarr[1] == b && chkarr[2] == c)) 
        { 
            //utf-8 bom 
            encode = 'utf-8'; 
            return ba.readMultiByte(len - 3, encode); 
        } 
        else 
        { 
            ba.position -= 3; 
        } 
    } 

    //逐个字节判断是否有UTF8的编码 
    if (isUTF8(ba, len)) 
    { 
        encode = 'utf-8'; 
    } 

    return ba.readMultiByte(len - 3, encode); 
} 

/** 
 * 判断文本是否是UTF8编码 
 * @param   ba 
 * @param   len 读取长度,默认为-1,则读取至文件尾 
 * @return 
 */ 
public static function isUTF8(ba:ByteArray,len:int = -1):Boolean 
{ 
    if ((len != -1 && len > ba.bytesAvailable) || (len == -1)) len = ba.bytesAvailable; 
    var score:int = 0; 
    var i:int; 
    var goodbytes:int = 0, asciibytes:int = 0; 
    // Maybe also use UTF8 Byte Order Mark: EF BB BF 
    // Check to see if characters fit into acceptable ranges 
    var oldpos:int = ba.position; 
    var byte:int, byte1:int, byte2:int; 
    var curlen:int = len; 
    while(curlen>0) 
    { 
        ba.position = oldpos + (len - curlen); 
        byte = ba.readByte(); 
        curlen -= 1; 
        if (curlen >= 1) byte1 = ba.readByte(); 
        if (curlen >= 2) byte2 = ba.readByte(); 

        //0x7f = 127 = 01111111 
        if ((byte & 0x7F) == byte)  
        {  
             // 最高位是0的ASCII字符 
             asciibytes++; 
             // Ignore ASCII, can throw off count 
        }  
        else if (-64 <= byte && byte <= -33 
             //-0x40~-0x21 
             && // Two bytes 
             curlen >= 1 && -128 <= byte1 
             &&  
             byte1<= -65)  
        { 
             goodbytes += 2; 
             curlen -= 1; 
        }  
        else if (-32 <= byte 
            && byte <= -17 
            && // Three bytes 
            curlen >= 2 && -128 <= byte1 
            && byte1 <= -65 && -128 <= byte2 
            && byte2 <= -65)  
        { 
            goodbytes += 3; 
            curlen -= 2; 
        } 
    } 

    ba.position = oldpos; 

    if (asciibytes == len)  
    { 
        return false; 
    } 
    score = 100 * goodbytes / (len - asciibytes); 
    // If not above 98, reduce to zero to prevent coincidental matches 
    // Allows for some (few) bad formed sequences 
    if (score > 98) { 
        return true; 
    } else if (score > 95 && goodbytes > 30) { 
        return true; 
    } else { 
        return false; 
    } 
}

wmode为opaque或transparent不支持鼠标滚轮的解决

在chrome等浏览器会有这个问题, 需要在html页面用js捕捉滚轮事件,然后传入到flash里面,难点是到flash之后该怎么办,我这里采用类类似冒泡的方式来触发事件。

js代码,参考自:http://www.denisdeng.com/?p=685

function wheel(obj, fn ,useCapture){ 
  var mousewheelevt=(/Firefox/i.test(navigator.userAgent))? "DOMMouseScroll" : "mousewheel" 
  //FF doesn't recognize mousewheel as of FF3.x 
  if (obj.attachEvent) 
  //if IE (and Opera depending on user setting) 
  obj.attachEvent("on"+mousewheelevt, handler, useCapture); 
  else if (obj.addEventListener) 
  //WC3 browsers 
  obj.addEventListener(mousewheelevt, handler, useCapture); 
  function handler(event) { 
    var delta = 0; 
    var event = window.event || event ; 
    var delta =  event.detail ?  -event.detail/3 : event.wheelDelta/120; 
    if (event.preventDefault) 
    event.preventDefault(); 
    event.returnValue = false; 
    return fn.apply(obj, [event, delta]); 
  } 
} 

function addMouseWheelListener(){ 
  var target = document.getElementById('flashobjID'); 
  wheel(target,callWheel); 
} 

function callWheel(e,delta) { 
  var target = document.getElementById('flashobjID'); 
   if(target!=undefined && target && target.fireWheel) 
     { 
                 //调用flash的方法 
         target.fireWheel(delta);   
     } 
} 

//页面加载完,附近鼠标事件侦听 
window.onload = addMouseWheelListener;

flash代码:

ExternalInterface.addCallback('fireWheel', function(delta:int):void{ 

  //获取当前鼠标下面的所有对象 
  var arr:Array = stage.getObjectsUnderPoint(new Point(stage.mouseX, stage.mouseY)); 
  if (arr.length == 0) return; 
  //只找最接近鼠标的那一层来触发就好了,底下的挡住了不管 
  var obj:DisplayObject = arr[arr.length-1]; 
  //从叶子节点,一层一层往根上找 
  while (true) 
  { 
    if (obj is InteractiveObject) 
    { 
      var intobj:InteractiveObject = obj as InteractiveObject; 

      if (intobj is TextField) 
      { 
        //TextField似乎不接受外部触发的滚轮事件,只能暴力 
        if ((intobj as TextField).mouseEnabled) 
        { 
          (intobj as TextField).scrollV -= delta; 
        } 
      } 
      else if (obj.hasEventListener(MouseEvent.MOUSE_WHEEL)) 
      { 
        var me:MouseEvent = new MouseEvent(MouseEvent.MOUSE_WHEEL, false, false, 0, 0, intobj); 
        me.delta = delta; 
        obj.dispatchEvent(me); 
      } 
    } 
    if (obj == stage || (!obj.parent)) 
    { 
      break; 
    } 
    obj = obj.parent; 
  } 

});

nodejs请求HTTPS报错:UNABLE_TO_VERIFY_LEAF_SIGNATURE的解决

出现这个错误是因为对方网站的证书不正确导致的。

在请求的时候指定忽略证书验证,即options的rejectUnauthorized参数设置为false

var https = require('https'); 

var options = { 
  hostname: 'encrypted.google.com', 
  port: 443, 
  path: '/', 
  method: 'GET', 
  rejectUnauthorized:false 
}; 

var req = https.request(options, function(res) { 
  console.log("statusCode: ", res.statusCode); 
  console.log("headers: ", res.headers); 

  res.on('data', function(d) { 
    process.stdout.write(d); 
  }); 
}); 
req.end(); 

req.on('error', function(e) { 
  console.error(e); 
});

nodejs官方SDK关于该参数的说明:

rejectUnauthorized: If true, the server certificate is verified against the list of supplied CAs. An 'error'event is emitted if verification fails. Verification happens at the connection level, before the HTTP request is sent. Default true.

flash全屏模式不支持键盘输入的解决方案

在flash里面如果设置stage的displayState为StageDisplayState.FULL_SCREEN的话,会不支持键盘输入。只能按esc退出全屏模式。

其实在flashplayer 11.3版本以上支持全屏键盘输入了,只要设置displayState属性为StageDisplayState.FULL_SCREEN_INTERACTIVE就可以了。

前提是在html里面镶嵌swf之前需要对swf的params增加一个allowFullScreenInteractives属性为true

flash代码如下:

stage.displayState = StageDisplayState.FULL_SCREEN_INTERACTIVE;

html代码片段:

<param name="allowScriptAccess" value="sameDomain" /> 
< param name="allowFullScreenInteractive" value="true" />

如果是使用swfobject则js代码片段:

params.quality = "high"; 
params.bgcolor = "#000000"; 
params.allowscriptaccess = "always"; 
params.allowfullscreen = "true"; 
params.allowFullScreenInteractive = "true"; 
params.wmode = "direct";

注意 还要设置需求flash版本为11.3以上,