mirror of
https://github.com/billsonnn/nitro-converter.git
synced 2024-11-26 09:20:51 +01:00
optimize zlib inflate, the old code would get stuck on malformed swfs
This commit is contained in:
parent
32435a3c84
commit
7ce2438ea5
@ -1,450 +1,432 @@
|
|||||||
/**
|
/**
|
||||||
* Simple module for reading SWF properties
|
* Simple module for reading SWF properties
|
||||||
*
|
*
|
||||||
* (c) 2014 Rafael Leal Dias <rafaeldias.c at gmail dot com>
|
* (c) 2014 Rafael Leal Dias <rafaeldias.c at gmail dot com>
|
||||||
* MIT LICENCE
|
* MIT LICENCE
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var fs = require('fs')
|
var fs = require('fs')
|
||||||
, zlib = require('zlib')
|
, zlib = require('zlib')
|
||||||
, lzma = require('lzma-purejs')
|
, lzma = require('lzma-purejs')
|
||||||
, Stream = require('stream')
|
, Stream = require('stream')
|
||||||
, SWFBuffer = require('./lib/swf-buffer')
|
, SWFBuffer = require('./lib/swf-buffer')
|
||||||
, SWFTags = require('./lib/swf-tags')
|
, SWFTags = require('./lib/swf-tags')
|
||||||
, SWFReader = exports;
|
, SWFReader = exports;
|
||||||
|
|
||||||
function readSWFTags(buff, swf) {
|
function readSWFTags(buff, swf) {
|
||||||
var tags = []
|
var tags = []
|
||||||
, tag
|
, tag
|
||||||
, tagHeader
|
, tagHeader
|
||||||
, flag
|
, flag
|
||||||
, l
|
, l
|
||||||
, sc
|
, sc
|
||||||
, fc;
|
, fc;
|
||||||
|
|
||||||
/* Reads TagCodeAndLength from Tag's RECORDHEADER */
|
/* Reads TagCodeAndLength from Tag's RECORDHEADER */
|
||||||
while( (tagHeader = buff.readTagCodeAndLength()) ) {
|
while( (tagHeader = buff.readTagCodeAndLength()) ) {
|
||||||
tag = {
|
tag = {
|
||||||
header : tagHeader
|
header : tagHeader
|
||||||
};
|
};
|
||||||
switch( tagHeader.code ) {
|
switch( tagHeader.code ) {
|
||||||
case SWFTags.FileAttributes :
|
case SWFTags.FileAttributes :
|
||||||
flag = buff.readUIntLE(32);
|
flag = buff.readUIntLE(32);
|
||||||
fileAttrs = {}
|
fileAttrs = {}
|
||||||
|
|
||||||
fileAttrs.useNetwork = tag.useNetwork = !!(flag & 0x1);
|
fileAttrs.useNetwork = tag.useNetwork = !!(flag & 0x1);
|
||||||
fileAttrs.as3 = tag.as3 = !!(flag & 0x8);
|
fileAttrs.as3 = tag.as3 = !!(flag & 0x8);
|
||||||
fileAttrs.hasMetaData = tag.hasMetaData = !!(flag & 0x10);
|
fileAttrs.hasMetaData = tag.hasMetaData = !!(flag & 0x10);
|
||||||
fileAttrs.useGPU = tag.useGPU = !!(flag & 0x20);
|
fileAttrs.useGPU = tag.useGPU = !!(flag & 0x20);
|
||||||
fileAttrs.useDirectBit = tag.useDirectBlit = !!(flag & 0x40);
|
fileAttrs.useDirectBit = tag.useDirectBlit = !!(flag & 0x40);
|
||||||
|
|
||||||
swf.fileAttributes = fileAttrs;
|
swf.fileAttributes = fileAttrs;
|
||||||
break;
|
break;
|
||||||
case SWFTags.Metadata :
|
case SWFTags.Metadata :
|
||||||
swf.metadata = tag.metadata = buff.readString()
|
swf.metadata = tag.metadata = buff.readString()
|
||||||
break;
|
break;
|
||||||
case SWFTags.SetBackgroundColor :
|
case SWFTags.SetBackgroundColor :
|
||||||
tag.RGB = buff.readRGB();
|
tag.RGB = buff.readRGB();
|
||||||
swf.backgroundColor = '#' + (tag.RGB[0]*65536 + tag.RGB[1]*256 + tag.RGB[0]).toString(16);
|
swf.backgroundColor = '#' + (tag.RGB[0]*65536 + tag.RGB[1]*256 + tag.RGB[0]).toString(16);
|
||||||
break;
|
break;
|
||||||
case SWFTags.Protect :
|
case SWFTags.Protect :
|
||||||
swf.protect = tagHeader.length && buff.readString();
|
swf.protect = tagHeader.length && buff.readString();
|
||||||
break;
|
break;
|
||||||
case SWFTags.DefineSceneAndFrameLabelData :
|
case SWFTags.DefineSceneAndFrameLabelData :
|
||||||
sc = tag.sceneCount = buff.readEncodedU32();
|
sc = tag.sceneCount = buff.readEncodedU32();
|
||||||
tag.scenes = [];
|
tag.scenes = [];
|
||||||
|
|
||||||
while (sc--)
|
while (sc--)
|
||||||
tag.scenes.push({
|
tag.scenes.push({
|
||||||
offset : buff.readEncodedU32(),
|
offset : buff.readEncodedU32(),
|
||||||
name : buff.readString()
|
name : buff.readString()
|
||||||
});
|
});
|
||||||
|
|
||||||
fc = tag.frameLabelCount = buff.readEncodedU32();
|
fc = tag.frameLabelCount = buff.readEncodedU32();
|
||||||
tag.labels = [];
|
tag.labels = [];
|
||||||
|
|
||||||
while (fc--)
|
while (fc--)
|
||||||
tag.labels.push({
|
tag.labels.push({
|
||||||
frameNum : buff.readEncodedU32(),
|
frameNum : buff.readEncodedU32(),
|
||||||
frameLabel : buff.readString()
|
frameLabel : buff.readString()
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
/**
|
/**
|
||||||
* DefineShape4 extends the capabilities of
|
* DefineShape4 extends the capabilities of
|
||||||
* DefineShape3 by using a new line style
|
* DefineShape3 by using a new line style
|
||||||
* record in the shape
|
* record in the shape
|
||||||
*/
|
*/
|
||||||
//case SWFTags.DefineShape4 :
|
//case SWFTags.DefineShape4 :
|
||||||
// /* id for this character */
|
// /* id for this character */
|
||||||
// tag.ShapeId = buff.readUIntLE(16);
|
// tag.ShapeId = buff.readUIntLE(16);
|
||||||
// /* bounds of the shape */
|
// /* bounds of the shape */
|
||||||
// tag.ShapeBounds = buff.readRect();
|
// tag.ShapeBounds = buff.readRect();
|
||||||
// /* bounds of the shape, excluding the strokes */
|
// /* bounds of the shape, excluding the strokes */
|
||||||
// tag.EdgeBounds = buff.readRect();
|
// tag.EdgeBounds = buff.readRect();
|
||||||
// /* reserved, must be 0 */
|
// /* reserved, must be 0 */
|
||||||
// if (0 !== buff.readBits(5))
|
// if (0 !== buff.readBits(5))
|
||||||
// throw new Error('Reserved bit used.');
|
// throw new Error('Reserved bit used.');
|
||||||
// /* if 1, use fill winding. >= SWF 10 */
|
// /* if 1, use fill winding. >= SWF 10 */
|
||||||
// if (swf.version >= 10)
|
// if (swf.version >= 10)
|
||||||
// tag.UsesFillWindingRule = buff.readBits(1);
|
// tag.UsesFillWindingRule = buff.readBits(1);
|
||||||
// /**
|
// /**
|
||||||
// * if 1, shape contains at least one
|
// * if 1, shape contains at least one
|
||||||
// * non-scaling stroke.
|
// * non-scaling stroke.
|
||||||
// */
|
// */
|
||||||
// tag.UsesNonScallingStrokes = buff.readBits(1);
|
// tag.UsesNonScallingStrokes = buff.readBits(1);
|
||||||
// /**
|
// /**
|
||||||
// * if 1, shape contains at least one
|
// * if 1, shape contains at least one
|
||||||
// * scaling stroke
|
// * scaling stroke
|
||||||
// */
|
// */
|
||||||
// tag.UsesScalingStrokes = buff.readBits(1);
|
// tag.UsesScalingStrokes = buff.readBits(1);
|
||||||
// tag.shapes = buff.readShapeWithStyle();
|
// tag.shapes = buff.readShapeWithStyle();
|
||||||
// break;
|
// break;
|
||||||
case SWFTags.FrameLabel :
|
case SWFTags.FrameLabel :
|
||||||
tag.name = buff.readString()
|
tag.name = buff.readString()
|
||||||
l = Buffer.byteLength(tag.name);
|
l = Buffer.byteLength(tag.name);
|
||||||
/* check if it's an named anchor */
|
/* check if it's an named anchor */
|
||||||
if (l & (tagHeader.length - 1) != l)
|
if (l & (tagHeader.length - 1) != l)
|
||||||
tag.anchor = buff.readUInt8();
|
tag.anchor = buff.readUInt8();
|
||||||
break;
|
break;
|
||||||
case SWFTags.DefineSprite :
|
case SWFTags.DefineSprite :
|
||||||
tag.SpriteID = buff.readUIntLE(16);
|
tag.SpriteID = buff.readUIntLE(16);
|
||||||
tag.FrameCount = buff.readUIntLE(16);
|
tag.FrameCount = buff.readUIntLE(16);
|
||||||
tag.ControlTags = readSWFTags(buff, swf);
|
tag.ControlTags = readSWFTags(buff, swf);
|
||||||
break;
|
break;
|
||||||
case SWFTags.ExportAssets :
|
case SWFTags.ExportAssets :
|
||||||
tag.count = buff.readUIntLE(16);
|
tag.count = buff.readUIntLE(16);
|
||||||
tag.assets = [];
|
tag.assets = [];
|
||||||
|
|
||||||
l = 0;
|
l = 0;
|
||||||
|
|
||||||
while (l++ < tag.count)
|
while (l++ < tag.count)
|
||||||
tag.assets.push({
|
tag.assets.push({
|
||||||
id : buff.readUIntLE(16),
|
id : buff.readUIntLE(16),
|
||||||
name : buff.readString()
|
name : buff.readString()
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case SWFTags.ImportAssets :
|
case SWFTags.ImportAssets :
|
||||||
/**
|
/**
|
||||||
* URL where the source SWF file can be found
|
* URL where the source SWF file can be found
|
||||||
*/
|
*/
|
||||||
tag.url = buff.readString();
|
tag.url = buff.readString();
|
||||||
/**
|
/**
|
||||||
* Number of assets to import
|
* Number of assets to import
|
||||||
*/
|
*/
|
||||||
tag.count = buff.readUIntLE(16);
|
tag.count = buff.readUIntLE(16);
|
||||||
tag.assets = [];
|
tag.assets = [];
|
||||||
|
|
||||||
l = 0;
|
l = 0;
|
||||||
|
|
||||||
while (l++ < tag.count)
|
while (l++ < tag.count)
|
||||||
tag.assets.push({
|
tag.assets.push({
|
||||||
/**
|
/**
|
||||||
* Character ID for the l-th item
|
* Character ID for the l-th item
|
||||||
* in importing SWF file
|
* in importing SWF file
|
||||||
*/
|
*/
|
||||||
id : buff.readUIntLE(16),
|
id : buff.readUIntLE(16),
|
||||||
/**
|
/**
|
||||||
* Identifies for the l-th
|
* Identifies for the l-th
|
||||||
* imported character
|
* imported character
|
||||||
*/
|
*/
|
||||||
name : buff.readString()
|
name : buff.readString()
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case SWFTags.ImportAssets2 :
|
case SWFTags.ImportAssets2 :
|
||||||
tag.url = buff.readString();
|
tag.url = buff.readString();
|
||||||
|
|
||||||
if ( !(1 === buff.readUInt8() && 0 === buff.readUInt8()) ) {
|
if ( !(1 === buff.readUInt8() && 0 === buff.readUInt8()) ) {
|
||||||
throw new Error('Reserved bits for ImportAssets2 used');
|
throw new Error('Reserved bits for ImportAssets2 used');
|
||||||
}
|
}
|
||||||
|
|
||||||
tag.count = buff.readUIntLE(16);
|
tag.count = buff.readUIntLE(16);
|
||||||
tag.assets = [];
|
tag.assets = [];
|
||||||
|
|
||||||
l = 0;
|
l = 0;
|
||||||
|
|
||||||
while (l++ < tag.count)
|
while (l++ < tag.count)
|
||||||
tag.assets({
|
tag.assets({
|
||||||
id : buff.readUIntLE(16),
|
id : buff.readUIntLE(16),
|
||||||
name : buff.readString()
|
name : buff.readString()
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case SWFTags.EnableDebbuger :
|
case SWFTags.EnableDebbuger :
|
||||||
tag.password = buff.readString()
|
tag.password = buff.readString()
|
||||||
break;
|
break;
|
||||||
case SWFTags.EnableDebugger2 :
|
case SWFTags.EnableDebugger2 :
|
||||||
if (0 !== buff.readUIntLE(16)) {
|
if (0 !== buff.readUIntLE(16)) {
|
||||||
//throw new Error('Reserved bit for EnableDebugger2 used.');
|
//throw new Error('Reserved bit for EnableDebugger2 used.');
|
||||||
}
|
}
|
||||||
tag.password = buff.readString()
|
tag.password = buff.readString()
|
||||||
break;
|
break;
|
||||||
case SWFTags.ScriptLimits :
|
case SWFTags.ScriptLimits :
|
||||||
/**
|
/**
|
||||||
* Maximum recursion Depth
|
* Maximum recursion Depth
|
||||||
*/
|
*/
|
||||||
tag.maxRecursionDepth = buff.readUIntLE(16);
|
tag.maxRecursionDepth = buff.readUIntLE(16);
|
||||||
/**
|
/**
|
||||||
* Maximum ActionScript processing time before script
|
* Maximum ActionScript processing time before script
|
||||||
* stuck dialog box displays
|
* stuck dialog box displays
|
||||||
*/
|
*/
|
||||||
tag.scriptTimeoutSeconds = buff.readUIntLE(16);
|
tag.scriptTimeoutSeconds = buff.readUIntLE(16);
|
||||||
break;
|
break;
|
||||||
case SWFTags.SymbolClass :
|
case SWFTags.SymbolClass :
|
||||||
tag.numSymbols = buff.readUIntLE(16);
|
tag.numSymbols = buff.readUIntLE(16);
|
||||||
tag.symbols = [];
|
tag.symbols = [];
|
||||||
|
|
||||||
l = 0;
|
l = 0;
|
||||||
|
|
||||||
while (l++ < tag.numSymbols)
|
while (l++ < tag.numSymbols)
|
||||||
tag.symbols.push({
|
tag.symbols.push({
|
||||||
id : buff.readUIntLE(16),
|
id : buff.readUIntLE(16),
|
||||||
name : buff.readString()
|
name : buff.readString()
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case SWFTags.DefineScalingGrid :
|
case SWFTags.DefineScalingGrid :
|
||||||
tag.characterId = buff.readUIntLE(16);
|
tag.characterId = buff.readUIntLE(16);
|
||||||
tag.splitter = buff.readRect();
|
tag.splitter = buff.readRect();
|
||||||
break;
|
break;
|
||||||
case SWFTags.setTabIndex :
|
case SWFTags.setTabIndex :
|
||||||
tag.depth = buff.readUIntLE(16);
|
tag.depth = buff.readUIntLE(16);
|
||||||
tag.tabIndex = buff.readUIntLE(16);
|
tag.tabIndex = buff.readUIntLE(16);
|
||||||
break;
|
break;
|
||||||
case SWFTags.JPEGTables:
|
case SWFTags.JPEGTables:
|
||||||
tag.jpegData = buff.buffer.slice(buff.pointer, buff.pointer + tagHeader.length);
|
tag.jpegData = buff.buffer.slice(buff.pointer, buff.pointer + tagHeader.length);
|
||||||
buff.pointer += tagHeader.length;
|
buff.pointer += tagHeader.length;
|
||||||
break;
|
break;
|
||||||
case SWFTags.DefineBits:
|
case SWFTags.DefineBits:
|
||||||
tag.characterId = buff.readUIntLE(16);
|
tag.characterId = buff.readUIntLE(16);
|
||||||
tag.jpegData = buff.buffer.slice(buff.pointer, buff.pointer + tagHeader.length - 2);
|
tag.jpegData = buff.buffer.slice(buff.pointer, buff.pointer + tagHeader.length - 2);
|
||||||
buff.pointer += tagHeader.length - 2;
|
buff.pointer += tagHeader.length - 2;
|
||||||
break;
|
break;
|
||||||
case SWFTags.DefineBitsJPEG2:
|
case SWFTags.DefineBitsJPEG2:
|
||||||
tag.characterId = buff.readUIntLE(16);
|
tag.characterId = buff.readUIntLE(16);
|
||||||
tag.imageData = buff.buffer.slice(buff.pointer, buff.pointer + tagHeader.length - 2);
|
tag.imageData = buff.buffer.slice(buff.pointer, buff.pointer + tagHeader.length - 2);
|
||||||
buff.pointer += tagHeader.length - 2;
|
buff.pointer += tagHeader.length - 2;
|
||||||
break;
|
break;
|
||||||
case SWFTags.DefineBitsJPEG3:
|
case SWFTags.DefineBitsJPEG3:
|
||||||
tag.characterId = buff.readUIntLE(16);
|
tag.characterId = buff.readUIntLE(16);
|
||||||
var alphaDataOffset = buff.readUIntLE(32);
|
var alphaDataOffset = buff.readUIntLE(32);
|
||||||
tag.imageData = buff.buffer.slice(buff.pointer, buff.pointer + alphaDataOffset);
|
tag.imageData = buff.buffer.slice(buff.pointer, buff.pointer + alphaDataOffset);
|
||||||
buff.pointer += alphaDataOffset;
|
buff.pointer += alphaDataOffset;
|
||||||
var restLength = tagHeader.length - 6 - alphaDataOffset;
|
var restLength = tagHeader.length - 6 - alphaDataOffset;
|
||||||
tag.bitmapAlphaData = buff.buffer.slice(buff.pointer, buff.pointer + restLength);
|
tag.bitmapAlphaData = buff.buffer.slice(buff.pointer, buff.pointer + restLength);
|
||||||
buff.pointer += restLength;
|
buff.pointer += restLength;
|
||||||
break;
|
break;
|
||||||
case SWFTags.DefineBitsJPEG4:
|
case SWFTags.DefineBitsJPEG4:
|
||||||
tag.characterId = buff.readUIntLE(16);
|
tag.characterId = buff.readUIntLE(16);
|
||||||
var alphaDataOffset = buff.readUIntLE(32);
|
var alphaDataOffset = buff.readUIntLE(32);
|
||||||
tag.deblockParam = buff.readUIntLE(16);
|
tag.deblockParam = buff.readUIntLE(16);
|
||||||
tag.imageData = buff.buffer.slice(buff.pointer, buff.pointer + alphaDataOffset);
|
tag.imageData = buff.buffer.slice(buff.pointer, buff.pointer + alphaDataOffset);
|
||||||
buff.pointer += alphaDataOffset;
|
buff.pointer += alphaDataOffset;
|
||||||
var restLength = tagHeader.length - 8 - alphaDataOffset;
|
var restLength = tagHeader.length - 8 - alphaDataOffset;
|
||||||
tag.bitmapAlphaData = buff.buffer.slice(buff.pointer, buff.pointer + restLength);
|
tag.bitmapAlphaData = buff.buffer.slice(buff.pointer, buff.pointer + restLength);
|
||||||
buff.pointer += restLength;
|
buff.pointer += restLength;
|
||||||
break;
|
break;
|
||||||
case SWFTags.DefineBitsLossless:
|
case SWFTags.DefineBitsLossless:
|
||||||
case SWFTags.DefineBitsLossless2:
|
case SWFTags.DefineBitsLossless2:
|
||||||
tag.characterId = buff.readUIntLE(16);
|
tag.characterId = buff.readUIntLE(16);
|
||||||
tag.bitmapFormat = buff.readUInt8();
|
tag.bitmapFormat = buff.readUInt8();
|
||||||
tag.bitmapWidth = buff.readUIntLE(16);
|
tag.bitmapWidth = buff.readUIntLE(16);
|
||||||
tag.bitmapHeight = buff.readUIntLE(16);
|
tag.bitmapHeight = buff.readUIntLE(16);
|
||||||
var restLength = tagHeader.length - 7;
|
var restLength = tagHeader.length - 7;
|
||||||
if (tag.bitmapFormat == 3) {
|
if (tag.bitmapFormat == 3) {
|
||||||
tag.bitmapColorTableSize = buff.readUInt8();
|
tag.bitmapColorTableSize = buff.readUInt8();
|
||||||
restLength--;
|
restLength--;
|
||||||
}
|
}
|
||||||
tag.zlibBitmapData = buff.buffer.slice(buff.pointer, buff.pointer + restLength);
|
tag.zlibBitmapData = buff.buffer.slice(buff.pointer, buff.pointer + restLength);
|
||||||
buff.pointer += restLength;
|
buff.pointer += restLength;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
tag.data = buff.buffer.slice(buff.pointer, buff.pointer + tagHeader.length);
|
tag.data = buff.buffer.slice(buff.pointer, buff.pointer + tagHeader.length);
|
||||||
buff.pointer += tagHeader.length;
|
buff.pointer += tagHeader.length;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
tags.push(tag);
|
tags.push(tag);
|
||||||
}
|
}
|
||||||
return tags;
|
return tags;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads tags and their contents, passaing a SWF object to callback
|
* Reads tags and their contents, passaing a SWF object to callback
|
||||||
*
|
*
|
||||||
* @param {SWFBuffer} buff
|
* @param {SWFBuffer} buff
|
||||||
* @param {Buffer} compressed_buff
|
* @param {Buffer} compressed_buff
|
||||||
* @param {function} callback
|
* @param {function} callback
|
||||||
* @api private
|
* @api private
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
function readSWFBuff(buff, compressed_buff, next) {
|
function readSWFBuff(buff, compressed_buff, next) {
|
||||||
buff.seek(3);// start
|
buff.seek(3);// start
|
||||||
|
|
||||||
if (buff.length < 9) {
|
if (buff.length < 9) {
|
||||||
if (isSync) throw new Error("Buffer is to small, must be greater than 9 bytes.");
|
if (isSync) throw new Error("Buffer is to small, must be greater than 9 bytes.");
|
||||||
return next(new Error("Buffer is to small, must be greater than 9 bytes."));
|
return next(new Error("Buffer is to small, must be greater than 9 bytes."));
|
||||||
}
|
}
|
||||||
var swf = {
|
var swf = {
|
||||||
version : buff.readUInt8(),
|
version : buff.readUInt8(),
|
||||||
fileLength : {
|
fileLength : {
|
||||||
compressed : compressed_buff.length,
|
compressed : compressed_buff.length,
|
||||||
uncompressed : buff.readUIntLE(32)
|
uncompressed : buff.readUIntLE(32)
|
||||||
},
|
},
|
||||||
frameSize : buff.readRect(), // Returns a RECT object. i.e : { x : 0, y : 0, width : 200, height: 300 }
|
frameSize : buff.readRect(), // Returns a RECT object. i.e : { x : 0, y : 0, width : 200, height: 300 }
|
||||||
frameRate : buff.readUIntLE(16)/256,
|
frameRate : buff.readUIntLE(16)/256,
|
||||||
frameCount : buff.readUIntLE(16)
|
frameCount : buff.readUIntLE(16)
|
||||||
}
|
}
|
||||||
, isSync = 'function' !== typeof next;
|
, isSync = 'function' !== typeof next;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
swf.tags = readSWFTags(buff, swf);
|
swf.tags = readSWFTags(buff, swf);
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
if (isSync) throw e;
|
if (isSync) throw e;
|
||||||
return next(e);
|
return next(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
return isSync && swf || next( null, swf );
|
return isSync && swf || next( null, swf );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Concat SWF Header with uncompressed Buffer
|
* Concat SWF Header with uncompressed Buffer
|
||||||
*
|
*
|
||||||
* @param {Buffer|ArrayBuffer} buff
|
* @param {Buffer|ArrayBuffer} buff
|
||||||
* @param {Buffer|ArrayBuffer} swf
|
* @param {Buffer|ArrayBuffer} swf
|
||||||
*/
|
*/
|
||||||
function concatSWFHeader(buff, swf) {
|
function concatSWFHeader(buff, swf) {
|
||||||
return Buffer.concat([swf.slice(0, 8), buff]);
|
return Buffer.concat([swf.slice(0, 8), buff]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Uncompress SWF and start reading it
|
* Uncompress SWF and start reading it
|
||||||
*
|
*
|
||||||
* @param {Buffer|ArrayBuffer} swf
|
* @param {Buffer|ArrayBuffer} swf
|
||||||
* @param {function} callback
|
* @param {function} callback
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
function uncompress(swf, next) {
|
function uncompress(swf, next) {
|
||||||
var compressed_buff = swf.slice(8)
|
var compressed_buff = swf.slice(8)
|
||||||
, uncompressed_buff
|
, uncompressed_buff
|
||||||
, isSync = 'function' !== typeof next
|
, isSync = 'function' !== typeof next
|
||||||
, e;
|
, e;
|
||||||
|
|
||||||
// uncompress buffer
|
// uncompress buffer
|
||||||
switch( swf[0] ) {
|
switch( swf[0] ) {
|
||||||
case 0x43 : // zlib compressed
|
case 0x43 : // zlib compressed
|
||||||
if (isSync) {
|
if (isSync) {
|
||||||
uncompressed_buff = concatSWFHeader(zlib.unzipSync(compressed_buff), swf);
|
uncompressed_buff = concatSWFHeader(zlib.unzipSync(compressed_buff), swf);
|
||||||
return readSWFBuff(new SWFBuffer(uncompressed_buff), swf);
|
return readSWFBuff(new SWFBuffer(uncompressed_buff), swf);
|
||||||
}
|
}
|
||||||
|
|
||||||
const newBuffer = swf.slice(4);
|
zlib.inflate(compressed_buff, function(err, buf) {
|
||||||
const uncompressedLength = newBuffer.readUInt32LE();
|
readSWFBuff(new SWFBuffer(buf), swf, next);
|
||||||
const chunks = [];
|
});
|
||||||
|
break;
|
||||||
let readLength = 0;
|
case 0x46 : // uncompressed
|
||||||
var decompressStream = zlib.createInflate()
|
return readSWFBuff(new SWFBuffer( swf ), swf, next);
|
||||||
.on('data', function (chunk) {
|
break;
|
||||||
readLength += chunk.length;
|
case 0x5a : // LZMA compressed
|
||||||
chunks.push(chunk);
|
var lzmaProperties = compressed_buff.slice(4, 9);
|
||||||
|
compressed_buff = compressed_buff.slice(9);
|
||||||
if (uncompressedLength - 8 === readLength) {
|
|
||||||
decompressStream.close();
|
var input_stream = new Stream();
|
||||||
}
|
input_stream.pos = 0;
|
||||||
//decompressStream.pause();
|
input_stream.readByte = function() {
|
||||||
}).on('error', function(err) {
|
return this.pos >= compressed_buff.length ? -1 : compressed_buff[this.pos++];
|
||||||
console.log(err);
|
};
|
||||||
//next(err);
|
|
||||||
}).on('close', function() {
|
var output_stream = new Stream();
|
||||||
readSWFBuff(new SWFBuffer( Buffer.concat(chunks) ), swf, next);
|
output_stream.buffer = new Buffer(16384);
|
||||||
});
|
output_stream.pos = 0;
|
||||||
decompressStream.write(compressed_buff);
|
output_stream.writeByte = function(_byte) {
|
||||||
break;
|
if (this.pos >= this.buffer.length) {
|
||||||
case 0x46 : // uncompressed
|
var newBuffer = new Buffer(this.buffer.length * 2);
|
||||||
return readSWFBuff(new SWFBuffer( swf ), swf, next);
|
this.buffer.copy(newBuffer);
|
||||||
break;
|
this.buffer = newBuffer;
|
||||||
case 0x5a : // LZMA compressed
|
}
|
||||||
var lzmaProperties = compressed_buff.slice(4, 9);
|
this.buffer[this.pos++] = _byte;
|
||||||
compressed_buff = compressed_buff.slice(9);
|
};
|
||||||
|
output_stream.getBuffer = function() {
|
||||||
var input_stream = new Stream();
|
// trim buffer
|
||||||
input_stream.pos = 0;
|
if (this.pos !== this.buffer.length) {
|
||||||
input_stream.readByte = function() {
|
var newBuffer = new Buffer(this.pos);
|
||||||
return this.pos >= compressed_buff.length ? -1 : compressed_buff[this.pos++];
|
this.buffer.copy(newBuffer, 0, 0, this.pos);
|
||||||
};
|
this.buffer = newBuffer;
|
||||||
|
}
|
||||||
var output_stream = new Stream();
|
return this.buffer;
|
||||||
output_stream.buffer = new Buffer(16384);
|
};
|
||||||
output_stream.pos = 0;
|
|
||||||
output_stream.writeByte = function(_byte) {
|
lzma.decompress(lzmaProperties, input_stream, output_stream, -1);
|
||||||
if (this.pos >= this.buffer.length) {
|
uncompressed_buff = Buffer.concat([swf.slice(0, 8), output_stream.getBuffer()]);
|
||||||
var newBuffer = new Buffer(this.buffer.length * 2);
|
|
||||||
this.buffer.copy(newBuffer);
|
return readSWFBuff(new SWFBuffer(uncompressed_buff), swf, next);
|
||||||
this.buffer = newBuffer;
|
break;
|
||||||
}
|
default :
|
||||||
this.buffer[this.pos++] = _byte;
|
e = new Error('Unknown SWF compressions');
|
||||||
};
|
|
||||||
output_stream.getBuffer = function() {
|
if (isSync) {
|
||||||
// trim buffer
|
throw e;
|
||||||
if (this.pos !== this.buffer.length) {
|
} else {
|
||||||
var newBuffer = new Buffer(this.pos);
|
next(e);
|
||||||
this.buffer.copy(newBuffer, 0, 0, this.pos);
|
}
|
||||||
this.buffer = newBuffer;
|
};
|
||||||
}
|
};
|
||||||
return this.buffer;
|
|
||||||
};
|
/**
|
||||||
|
* Check if file is Buffer or ArrayBuffer
|
||||||
lzma.decompress(lzmaProperties, input_stream, output_stream, -1);
|
*
|
||||||
uncompressed_buff = Buffer.concat([swf.slice(0, 8), output_stream.getBuffer()]);
|
* @param {Buffer|ArrayBuffer) b
|
||||||
|
* @api private
|
||||||
return readSWFBuff(new SWFBuffer(uncompressed_buff), swf, next);
|
*
|
||||||
break;
|
*/
|
||||||
default :
|
function isBuffer(b) {
|
||||||
e = new Error('Unknown SWF compressions');
|
return typeof Buffer !== "undefined" && Buffer.isBuffer(b) || b instanceof ArrayBuffer;
|
||||||
|
}
|
||||||
if (isSync) {
|
|
||||||
throw e;
|
/* Exposes Tags constants */
|
||||||
} else {
|
SWFReader.TAGS = SWFTags;
|
||||||
next(e);
|
|
||||||
}
|
/**
|
||||||
};
|
* Reads SWF file
|
||||||
};
|
*
|
||||||
|
* @param {String|Buffer}} file
|
||||||
/**
|
* @param {function} next - if not a function, uses synchronous algorithm
|
||||||
* Check if file is Buffer or ArrayBuffer
|
* @api public
|
||||||
*
|
*
|
||||||
* @param {Buffer|ArrayBuffer) b
|
*/
|
||||||
* @api private
|
SWFReader.read = SWFReader.readSync = function(file, next) {
|
||||||
*
|
if (isBuffer(file)) {
|
||||||
*/
|
/* File is already a buffer */
|
||||||
function isBuffer(b) {
|
return uncompress(file, next);
|
||||||
return typeof Buffer !== "undefined" && Buffer.isBuffer(b) || b instanceof ArrayBuffer;
|
} else {
|
||||||
}
|
/* Get the buffer */
|
||||||
|
if ('function' === typeof next) {
|
||||||
/* Exposes Tags constants */
|
fs.readFile(file, function(err, swf) {
|
||||||
SWFReader.TAGS = SWFTags;
|
if ( err ) {
|
||||||
|
next(err);
|
||||||
/**
|
return;
|
||||||
* Reads SWF file
|
}
|
||||||
*
|
uncompress(swf, next);
|
||||||
* @param {String|Buffer}} file
|
});
|
||||||
* @param {function} next - if not a function, uses synchronous algorithm
|
} else {
|
||||||
* @api public
|
return uncompress(fs.readFileSync(file));
|
||||||
*
|
}
|
||||||
*/
|
}
|
||||||
SWFReader.read = SWFReader.readSync = function(file, next) {
|
};
|
||||||
if (isBuffer(file)) {
|
|
||||||
/* File is already a buffer */
|
|
||||||
return uncompress(file, next);
|
|
||||||
} else {
|
|
||||||
/* Get the buffer */
|
|
||||||
if ('function' === typeof next) {
|
|
||||||
fs.readFile(file, function(err, swf) {
|
|
||||||
if ( err ) {
|
|
||||||
next(err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
uncompress(swf, next);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
return uncompress(fs.readFileSync(file));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
Loading…
Reference in New Issue
Block a user