Skip to content

Instantly share code, notes, and snippets.

@claus
Created September 23, 2010 21:09
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save claus/594367 to your computer and use it in GitHub Desktop.
Save claus/594367 to your computer and use it in GitHub Desktop.
<?xml version="1.0" encoding="utf-8"?>
<!--
Show the compile date of a SWF.
See http://wahlers.com.br/claus/blog/undocumented-swf-tags-written-by-mxmlc/
-->
<s:Application
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
minWidth="600" minHeight="400"
creationComplete="creationCompleteHandler(event)">
<fx:Script>
<![CDATA[
import com.codeazur.as3swf.SWF;
import com.codeazur.as3swf.SWFData;
import com.codeazur.as3swf.data.SWFRawTag;
import com.codeazur.as3swf.data.SWFRecordHeader;
import com.codeazur.as3swf.tags.TagEnd;
import com.codeazur.as3swf.tags.TagProductInfo;
import mx.events.FlexEvent;
[Bindable]
protected var compileDate:Date;
protected function creationCompleteHandler(event:FlexEvent):void
{
compileDate = getCompileDateOptimized();
}
// if we're lazy and not concerned about performance/memory,
// we can just have as3swf parse the entire SWF
// and then loop over the tags to see if there's a ProductInfo tag
protected function getCompileDateSimple():Date
{
var swf:SWF = new SWF(systemManager.loaderInfo.bytes);
for(var i:uint = 0; i < swf.tags.length; i++) {
if(swf.tags[i] is TagProductInfo) {
var productInfo:TagProductInfo = swf.tags[i] as TagProductInfo;
return productInfo.compileDate;
}
}
return null;
}
// much better: do not parse the entire SWF, just the tag headers
// and bail out as soon as a ProductInfo tag is found
protected function getCompileDateOptimized():Date
{
var swfData:SWFData = new SWFData();
swfData.writeBytes(systemManager.loaderInfo.bytes);
swfData.position = 0;
// parse SWF header
var compressed:Boolean = false;
var signatureByte:uint = swfData.readUI8();
if (signatureByte == 0x43) {
compressed = true;
} else if (signatureByte != 0x46) {
throw(new Error("Not a SWF. First signature byte is 0x" + signatureByte.toString(16) + " (expected: 0x43 or 0x46)"));
}
signatureByte = swfData.readUI8();
if (signatureByte != 0x57) {
throw(new Error("Not a SWF. Second signature byte is 0x" + signatureByte.toString(16) + " (expected: 0x57)"));
}
signatureByte = swfData.readUI8();
if (signatureByte != 0x53) {
throw(new Error("Not a SWF. Third signature byte is 0x" + signatureByte.toString(16) + " (expected: 0x53)"));
}
swfData.readUI8(); // version
swfData.readUI32(); // fileLength
if (compressed) {
// the following data (up to end of file) is compressed
swfData.swfUncompress();
}
swfData.readRECT(); // frameSize
swfData.readFIXED8(); // frameRate
swfData.readUI16(); // frameCount
try {
// parse SWF tags
do {
// read the tag header
var tagRaw:SWFRawTag = swfData.readRawTag();
var tagHeader:SWFRecordHeader = tagRaw.header;
if(tagHeader.type == TagProductInfo.TYPE) {
// it's a ProductInfo tag: parse it
var productInfo:TagProductInfo = new TagProductInfo();
productInfo.parse(swfData, 0, 0);
// and return the compile date. we're done here.
return productInfo.compileDate;
} else {
// not a ProductInfo tag: just skip it
swfData.position += tagHeader.contentLength;
}
// loop until End tag is encountered
} while(tagHeader.type != TagEnd.TYPE);
} catch(error:Error) {
}
return null;
}
]]>
</fx:Script>
<s:layout>
<s:VerticalLayout paddingLeft="8" paddingTop="8" />
</s:layout>
<s:Label text="{compileDate}" />
</s:Application>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment