Can ActionScript tell when a SWF was published? - actionscript-3

I'd like to write a little class that adds a Day/Month box showing the date a SWF was published from Flash.
The company I work for regularly produces many, many SWFs and many versions of each, iterating over the course of months. A version-tracking system we've been using to communicate with our clients is a Day/Month date-box that gives the date the SWF was published. Up until now, we've been filling in the publish date by hand. If there's any way I can do this programatically with ActionScript that'd be fantastic.
Any insight? Basically, all I need is the call that gives me the publish date, or even.. anything about the circumstances under which a SWF was published that I could use to roll into some form of.. automated version identification, unique to this SWF.
So, can ActionScript tell when a SWF was published?

George is correct. Adobe sneaks an undocumented ProductInfo tag that contains the compilation date in to every compiled swf. The DisplayObject.loaderInfo.bytes contains the the complete uncompressed swf that loaded the Display Object.
http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/display/DisplayObject.html#loaderInfo
So the quickest way to get the swf's compilation date without external libraries (from a Display Object):
import flash.utils.Endian;
import flash.display.LoaderInfo;
import flash.utils.ByteArray;
...
private function getCompilationDate():Date{
if(!stage) throw new Error("No stage");
var swf:ByteArray = stage.loaderInfo.bytes;
swf.endian = Endian.LITTLE_ENDIAN;
// Signature + Version + FileLength + FrameSize + FrameRate + FrameCount
swf.position = 3 + 1 + 4 + (Math.ceil(((swf[8] >> 3) * 4 - 3) / 8) + 1) + 2 + 2;
while(swf.position != swf.length){
var tagHeader:uint = swf.readUnsignedShort();
if(tagHeader >> 6 == 41){
// ProductID + Edition + MajorVersion + MinorVersion + BuildLow + BuildHigh
swf.position += 4 + 4 + 1 + 1 + 4 + 4;
var milli:Number = swf.readUnsignedInt();
var date:Date = new Date();
date.setTime(milli + swf.readUnsignedInt() * 4294967296);
return date; // Sun Oct 31 02:56:28 GMT+0100 2010
}else
swf.position += (tagHeader & 63) != 63 ? (tagHeader & 63) : swf.readUnsignedInt() + 4;
}
throw new Error("No ProductInfo tag exists");
}
The SWF Specification: http://www.adobe.com/content/dam/Adobe/en/devnet/swf/pdf/swf_file_format_spec_v10.pdf

Also you can read the date from the SWF bytecode with the awesome as3swf library.
Check this out.

I'm afraid you can't do it in Actionscript. Depending on how you build the swfs, there might be a couple of options. For instance, if you use the Flash IDE, you could use a JSFL script to publish the swf. This jsfl could replace a placeholder variable where you will store the publication date, and the publish the swf (haven't write a JSFL script in a long time but it shouldn't be too hard to get this working).
So, let's say you have a Version class:
public class Version {
public var publicationDate:Date = new Date();
}
Your script should read the file where this class lives, find that line and replace it with the current date:
Something like this:
var curDate = new Date();
var dateLine = "public var publication:Date = new Date(" + curDate.getFullYear() + "," + curDate.getMonth() + "," + curDate.getDate() +");";

In case you're using FlashDevelop (which is very nice lightweight, free AS3 IDE) you can do this:
public static function GetBuildDate() : String
{
return CONFIG::timeStamp;
}
It returns date in format YYYY-MM-DD
More info: http://www.flashdevelop.org/wikidocs/index.php?title=AS3_Conditional_Compilation

Not sure if this would work, but could you use an 'include' statement which calls in an externally generated .as file at compile time which has the (then) current date hard-coded into it? You'd need to have a script of some kind running on your server to update this file once a day to keep it current.

Related

Actionscript While loop & addChild problems

Hi I'm trying to make a powers calculator that displays every line calculated by the while loop in my actionscript3 code. When I run the program, the flash file only displays the last loop, can anyone help to make it work without using trace? I need it to display in the flash program. Here is my code:
private function evalue(event:MouseEvent = null):void
{
maMiseEnForme.font="Arial";
maMiseEnForme.size=14;
maMiseEnForme.bold=true;
maMiseEnForme.color=0x000000;
monMessage.x=270;
monMessage.y=375;
monMessage.autoSize=TextFieldAutoSiz...
monMessage.border=true;
monMessage.defaultTextFormat=maMiseE...
var base:uint;
var reponse:uint;
var puissanceCount:int=1;
var puissance:uint;
var reponseText:String;
base = uint(boiteBase.text);
puissance = uint(boitePuissance.text);
while (puissanceCount <= puissance)
{
reponse = Math.pow(base,puissanceCount);
reponseText=(base + "^" + puissanceCount + "=" + reponse + "\n");
monMessage.text=reponseText;
addChild(monMessage);
puissanceCount++
}
}
}
}
I have attached a picture of what appears in the .swf window:
P.S: I'm a newbie to flash.
Thanks in advance.
You can use "+=" parameter instead of "=" parameter to update a string variable by "adding string to it" instead of "refreshing it everytime", then you can show text after your while loop finished. You don't need to addChild(nonMessage) in everyloop, just move it after your while{} loop. SO: You just need "monMessage.text+=reponseText;" instead of "monMessage.text=reponseText;" and move your "addChild()" to next to your while loop.

Simple Obfuscation Of String Constants in Flash

I am not a F
lash expert.
I have a FLA file of a game coded in ActionScript 3.
The game has a string inside, "www.mywebsite.com".
I want that when someone opens this FLA and searches for ".com" or "mywebsite.com" to find nothing. So I have decided to encode that string somehow. But I never coded in Flash, so I have no idea what to start with and Google isn't helping.
Basically all I want to do is replace this line:
var url1 = 'www.mywebsite.com';
With something like this and be functional.
var url1 = base64_decode('asdahwiyadwaeawr==');
Even a XOR or other simple string manipulation algorithm would be good.
What options do I have without importing any non-standard libraries into Flash?
Anyone looking through your code at something like var url = BlaBla_decode("cvxcvxc"); can simply replace it with var url = "www.HisWebsite.com...
So I guess you're supposing no one will be going through your script line by line but instead search for ".com" (Which would make him a really lazy jerk)!
A simple solution is to come up with a function that would return "www.MyWebsite.com" without writing it;
Something like:
var url:String = youAreStupid();
function youAreStupid():String
{
return String(f(22) + f(22) + f(22) + "extra.extra" + f(12) + f(24) + f(22) + f(4) + f(1) + f(18) + f(8) + f(19) + f(4) + "extra.extra" + f(2) + f(14) + f(12)).replace(/extra/g, "");
}
function f(n:Number):String
{
return String.fromCharCode("a".charCodeAt(0) + n);
}
I can't but say this would be lame way to protect your document, and I suggest you keep a comment at the top of your Script (something clearly visible) : // You won't find it YOU ARE STUPID
Now if he's smart enough to search for youAreStupid, that means he's entitled to change it :p
Of course there's also the simpler:
String("-Ow-Mw-Gw-!.-Ym-Oy-Uw-Ae-Rb-Es-Si-Ot-Se-T.-Uc-Po-Im-D").replace(/-./g, "");
but that's no fun!!!

Oldest archive files not removed when using SizeAndTimeBasedFNATP when rolling over and there are multiple archive files for the oldest interval

There seems to be a problem with how the maxHistory argument is implemented.
I roll over multiple times withing the time interval (every minute
here), creating the following files : (maxHistory = 3)
trace.log (active file)
trace-2013-03-13-16.14.0.log.zip
trace-2013-03-13-16.13.0.log.zip
trace-2013-03-13-16.12.2.log.zip
trace-2013-03-13-16.12.1.log.zip
trace-2013-03-13-16.12.0.log.zip
The nex time rollover occurs, the 16.13.0.log.zip file is removed, and
not the oldest ones (12.{0,1,2} as I would have expected. Is this
intended behaviour ?
public static Logger createTimeAndSizeRollingLogger(String fileBase, String maxSize, int maxHistory, String resolutionPattern) {
LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
RollingFileAppender<ILoggingEvent> appender = new RollingFileAppender<ILoggingEvent>();
appender.setContext(loggerContext);
appender.setFile(fileBase + ".log");
TimeBasedRollingPolicy<ILoggingEvent> timePolicy = new TimeBasedRollingPolicy<ILoggingEvent>();
timePolicy.setFileNamePattern(fileBase + "_%d{" + resolutionPattern + "}-%i.log.zip");
timePolicy.setContext(loggerContext);
timePolicy.setMaxHistory(maxHistory);
timePolicy.setParent(appender);
appender.setRollingPolicy(timePolicy);
SizeAndTimeBasedFNATP<ILoggingEvent> rollingPolicy = new SizeAndTimeBasedFNATP<ILoggingEvent>();
rollingPolicy.setMaxFileSize(maxSize);
rollingPolicy.setTimeBasedRollingPolicy(timePolicy);
rollingPolicy.setContext(loggerContext);
timePolicy.setTimeBasedFileNamingAndTriggeringPolicy(rollingPolicy);
timePolicy.start();
rollingPolicy.start();
PatternLayoutEncoder encoder = new PatternLayoutEncoder();
encoder.setContext(loggerContext);
encoder.setPattern("%msg%n");
encoder.start();
appender.setEncoder(encoder);
appender.start();
Logger logger = loggerContext.getLogger(fileBase);
logger.setLevel(Level.TRACE);
logger.addAppender(appender);
StatusPrinter.print(loggerContext);
return logger;
}
THis seems to be fixed in the lastest 1.1.0 SNAPSHOT
http://jira.qos.ch/browse/LOGBACK-162
This is a known issue. MaxHistory will not work with SizeAndTimeBasedFNATP.
You can check it here
You will find many people saying that it is solved, but it is not. If you want to fix it you can edit SizeAndTimeBasedFNATP.java which is located inside logback-core. You can see it here . Inside isTriggeringEvent is the place to add the code in my opinion.

How to translate multiple labeled movieclip of Actionscript to Starling?

I'm new to starling and this may sound like a noob question but here goes nothing.
Imagine the following scenario (in Flash):
A movieclip named test
Test has 80 frames
Test has 4 labels at 20 frames each
When I script test in my project. I make it loop from label 0-1 (frames 1-19). Then I tell it to loop on label 2 on a certain event.
This way, I do not add or remove a movieclip or instantiate things just one.
Now, if I think about implementing it in starling. I'm thinking make 4 movieclips in flash. Export them as sprite sheets and then make four movieclips in the script. Add whichever moviclip needs to play in the juggler and similarly removechild it at that time.
This way, I'm adding the overhead cost of 'addchild' and 'removechild' everytime I want to switch between those animations. Is that a more cost effective way?
I presume you want to export a single clip, but control multipe(4 animations) rather than a single one. If this is the case, I wrote a few JSFL scripts a couple of years ago (when CS6 wasn't around to export spritesheets) which exported the main timeline of an .fla document as an image sequence, but used the frame labels in the filenames. This made it easy to integrate with TexturePacker. You can see video of it here.
Here's a JSFL snippet which will export a frame sequence with names generated based frame labels which should make it easy to manage in TexturePacker:
var d = (FLfile.getPlatform() == 'macos') ? '/' : '\\'; //delimiter
var doc = fl.getDocumentDOM(); //document
var tl = doc.getTimeline();tl.setSelectedLayers(0,true); //timeline
var cl = tl.layers[0]; //current layer
var numFrames = cl.frameCount;
var className = prompt("Name for your sequence", toClassName(doc.name.substr(0,doc.name.length-4)));
className = className.split('.')[0];//just in case the user adds .as
className = toClassName(className);//remove non alphabet chars
var docPath = doc.pathURI.substr(0,doc.pathURI.length - doc.name.length);
var exportPath = docPath+className+'_export'+d;
if(!FLfile.exists(exportPath)) FLfile.createFolder(exportPath);
fl.outputPanel.clear();
for(i = 0 ; i < numFrames; i++) {
if(cl.frames[i].name != ''){//if frame is labelled
tl.setSelectedFrames(i,i,true);
doc.exportPNG(exportPath+cl.frames[i].name+lpad(''+i,4)+'.png',true,true);
}
}
fl.trace("export complete!");
function lpad(number, length){
var result = '' + number;
while (result.length < length) result = '0' + result;
return result;
}
function toClassName(input){
return input.replace(/[^a-zA-Z]/g, "");
}
Also, I suggest having a look at generator tools like Dynamic-Texture-Atlas-Generator, Fruitfly, etc.

Flex requests by URLLoader not being well received on server side

today's question involves URLLoader requests using encrypted strings.
when I encrypt a string I get the following result:
1Kx4dfp5OC7ox0zb0lWzzzlnoPLcoPGE1MrAKOtl3h6SPcFmEdpLnUROSKpPrCl70VHRxrKzhsxHHlb1MRp3++JkvYZ++ghBEG2zbVhyaqQ/0+NDrJ+0cLt3g9THe9POohN6Ufcq9TcnmZVvIFXllg4HrjVNfQrhQCNwxuBgWBf2DRc4eq6hKzEgyLdlllQFc9ssUFlPD3wOBqoI22r+7N82sI3pqsQYBq5VlKHHreqD8Cq0gictnTFS3IqepASGARKyuCIPDCa4zE76VeQV5zgvkFfjDww+C1uZ8PUgjH67DKYqUP9a6euf2v1jUpBrREnm4ZbLAXScDjvrJ11rWYyVXOLZy9nhy9qRBQRvdw+tnBThPTmvxaq+LAusF8IbvDpZgMrZ3buvThnXuSBGXZxaja7fk/FIlm4RSliDTSGySiizFHy7dJePXuV0c9MI6ciOYxmEIg64NnhBZtB8wipUDJWOpoytOD2/sNQBenjZbYN8291msYnbBG+alAOQmEBH5Mn4KyW1VQWE2lBGk9ML+SflND8UXfdHz5Q3psOcMZJxSAURKGq5tjA8KlPPOAdQuVPIcysg2/4lV25QGIdDttQVGrkP+ZHZcHIPTLLD+Vml+PJU/OAJGNPGlf3wawUo+bID0FKur8N6tNyu7Pnoocn7plDi6WSJgUAaYjI4=
I send it in, everything seems fine on Flex's end. But when I go to the serverside (logfiles, not allowed to change server-side code) to check what I'm getting, I end up with this:
1Kx4dfp5OC7ox0zb0lWzzzlnoPLcoPGE1MrAKOtl3h6SPcFmEdpLnUROSKpPrCl70VHRxrKzhsxHHlb1MRp3 JkvYZ ghBEG2zbVhyaqQ/0 NDrJ 0cLt3g9THe9POohN6Ufcq9TcnmZVvIFXllg4HrjVNfQrhQCNwxuBgWBf2DRc4eq6hKzEgyLdlllQFc9ssUFlPD3wOBqoI22r 7N82sI3pqsQYBq5VlKHHreqD8Cq0gictnTFS3IqepASGARKyuCIPDCa4zE76VeQV5zgvkFfjDww C1uZ8PUgjH67DKYqUP9a6euf2v1jUpBrREnm4ZbLAXScDjvrJ11rWYyVXOLZy9nhy9qRBQRvdw tnBThPTmvxaq LAusF8IbvDpZgMrZ3buvThnXuSBGXZxaja7fk/FIlm4RSliDTSGySiizFHy7dJePXuV0c9MI6ciOYxmEIg64NnhBZtB8wipUDJWOpoytOD2/sNQBenjZbYN8291msYnbBG alAOQmEBH5Mn4KyW1VQWE2lBGk9ML SflND8UXfdHz5Q3psOcMZJxSAURKGq5tjA8KlPPOAdQuVPIcysg2/4lV25QGIdDttQVGrkP ZHZcHIPTLLD Vml PJU/OAJGNPGlf3wawUo bID0FKur8N6tNyu7Pnoocn7plDi6WSJgUAaYjI4=
at first glance they're the same, but if you check closely, the + gets replaced by a whitespace...
I've even tried switching the + for %2B but on the server-side it gets read as %2B, it isn't converted to a + (flex doesn't seem to function as a browser in this case).
Any kind of insight and help on this matter would be very appreciated.
The requests are being done as follows:
public function callService(callback:String, request:String):void{
var url:URLRequest = new URLRequest(server);
var requestedString:String = handlePluses(request);
url.useCache = false;
url.contentType = contentType;
url.method = method;
trace("sending: " + requestedString);
url.data += requestedString);
serverURL.addEventListener(IOErrorEvent.IO_ERROR, treatIO);
serverURL.dataFormat = URLLoaderDataFormat.TEXT;
serverURL.addEventListener(Event.COMPLETE, loadData);
serverURL.addEventListener(Event.CONNECT, function():void{trace("connected");});
try{
serverURL.load(url);
}catch(e:ArgumentError){trace("ArgError: " + e.message);}
catch(e:SecurityError){trace("SecError: " + e.message);}
catch(e:TimeoutEvent){trace("===========<Timeout>===========");}
}
we fixed this problem by switching the + character with a subset of escaped characters like \&\#.
this might be a problem to others attempting the same thing and trying to keep to a minimum size.