Archive for category Flash
Flash cannot parse this document – Adobe Flash CS5
I found a fix for a single case of “Flash cannot parse this document” error when opening a file saved from Adobe Flash CS5. Here is how it happened.
A designer friend of mine upgraded to CS5 recently and sent me an email in a panic when she got this error “Flash cannot parse this document” after trying to open up a file she had just saved. While she tried to salvage some of her work from a decompiler I took a look at if we could fix the file.
Some quick Google searching came up with the right clue to figuring out what was wrong. The user wbfreek21 got me on the right path to figuring out just what happened. He talks about how he was able to fix his particular file by going into the new XML based FLA format and removing empty XML elements from the DOM here.
That’s it! Flash cannot parse this document, it’s an error in the XML! I quickly followed the instruction to open the FLA as a ZIP and started poking around in the XML files. They were large, this wasn’t a small project. Firefox has an XML parser as well but it lists out where the problem characters are, I tried opening all the files in the LIBRARY directory in Firefox and instantly found the issue. The empty character that wbfreek21 reported was this ETX (End of Text) character that had found it’s way into the document. I pulled out that character and successfully opening up the file in Flash CS5 again much to the designers joy.
Here is the step by step process I used to find and remove the problem:
- Make a copy of your corrupt FLA and put it in a fresh folder, in case you need to repeat steps
- Rename the extension on your FLA to ZIP and extract the contents to a folder
- There are several XML files in the extracted folder structure, I found my corrupt file in the LIBRARY folder but all XML files should be tested. Open each XML file in Firefox, when you reach a corrupted file you will get an error page that looks like this:

- Open that document in a text editor that can show hidden ASCII characters, I used Notepad++ but I wasn’t able to find an editor that worked for a Mac sorry, scroll to the line that Firefox reported your error on and take a look at the code in there to see what your problem area was, my XML document looked like this:

- Save your XML file with the character removed and repeat steps 3 and 4 on the same file you found an error in and the rest of the XML files in the folder structure.
- Now open up your XFL file in the root of your extracted folder structure, you shouldn’t get any errors, if you get a parse error again repeat steps 3 through 5. Use Save As to make a copy of your file as a FLA, you’re all set!
Sizing the buttons on the NumericStepper
So your working on a new RIA in Flash and you want to use the built in NumericStepper, or any other Flash component for that matter but you aren’t happy with the skin. You’ve already seen Customizing the NumericStepper component by Adobe and you’re ready to move past changing the color of the component and want to update the buttons. Every time I updated the component skin after it has been added to the Library in Flash and tested the Movie, the smaller button graphics I created get stretched and distorted. It was always 21 pixels wide and 12 pixels tall! The Adobe documentation on the NumericStepper didn’t provide any help in resizing these buttons that control the increase and decrease for the NumericStepper component.
What you need to do is open up the source and take a look to figure out what was going on. I found the source files here C:\Program Files (x86)\Adobe\Adobe Flash CS4\Common\Configuration\Component Source\ActionScript 3.0\User Interface\fl\controls\NumericStepper.as on my system. I found out what was going wrong by doing a quick search for that pesky 21 pixel width and found my answer starting on line 527.
527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 | override protected function configUI():void { super.configUI(); upArrow = new BaseButton(); copyStylesToChild(upArrow, UP_ARROW_STYLES); upArrow.autoRepeat = true; upArrow.setSize(21, 12); upArrow.focusEnabled = false; addChild(upArrow); downArrow = new BaseButton(); copyStylesToChild(downArrow, DOWN_ARROW_STYLES); downArrow.autoRepeat = true; downArrow.setSize(21, 12); downArrow.focusEnabled = false; addChild(downArrow); inputField = new TextInput(); copyStylesToChild(inputField, TEXT_INPUT_STYLES); inputField.restrict = "0-9\\-\\.\\,"; inputField.text = _value.toString(); inputField.setSize(21, 24); inputField.focusTarget = this as IFocusManagerComponent; inputField.focusEnabled = false; inputField.addEventListener(FocusEvent.FOCUS_IN, passEvent); inputField.addEventListener(FocusEvent.FOCUS_OUT, passEvent); addChild(inputField); inputField.addEventListener(Event.CHANGE, onTextChange, false, 0, true); upArrow.addEventListener(ComponentEvent.BUTTON_DOWN, stepperPressHandler, false, 0, true); downArrow.addEventListener(ComponentEvent.BUTTON_DOWN, stepperPressHandler, false, 0, true); } |
Ah ha! They set the size of the buttons when the component is initialized on the stage. You can’t edit this file to solve your problem though you’ll need to extend the fl.controls.NumericStepper class and override the configUI function to change the size of your buttons. I suspect there are several other instances of hard-coded component sizes in the Flash component library but you just need to look to the source they provided to extend the components to your liking.
Blocking IP addresses by country on IIS shared hosting
On a shared hosting environment you often won’t have access to ban IP addresses on the IIS level and my shared host didn’t offer the Firewall module for Plesk so I had to come up with a programmatic way of blocking large blocks of IPs. You can setup in your web.config file something called a HTTPModule that works before the page is delivered to the client computer. For this sample I added a key and value to my web.config file that holds my comma separated IP list that I want to block. Since I’m running a site that is focused on the United States there isn’t much overlap on the /24 block area 255.255.255.* so I am only checking the first 3 digit blocks for matches. When a request comes in IpTwentyFourBlockingModule will check the users IP address against the key value blockiptwentyfour to see if there is a match and if it is a match will return 403 forbidden to the client browser, banned!
Coming up with a IP list is another problem. I found IP Location Tools that gives out an API that generates a updated list of IPs for a given country. The problem is the list gets broken out into IP blocks other than /24, you’ll see all ranges of IP blocks that get very complicated very fast and more than I wanted to try and pull off in a days work. I wrote a Flash ActionScript 3 application to consume this data and give me a list of unique IPs 255.255.255 that I could then drop in as the value for blockiptwentyfour. I then added IP tracking for new users and have had to ban some rogue /24 blocks that escaped this list but its kept them at bay and more manageable for now. I’ve already had a colleague suggest that this is still only a stopgap at best and I should develop some kind of throttling system to help prevent spam when I’m not around to watch the site like a hawk.
web.config
1 2 3 4 5 6 7 8 9 10 | <configuration> <appSettings> <add key="blockiptwentyfour" value="41.210.29,41.210.28" /> </appSettings> <system.web> <httpModules> <add name="IpTwentyFourBlockingModule" type="IpTwentyFourBlockingModule" /> </httpModules> </system.web> </configuration> |
IpTwentyFourBlockingModule.cs – put this is in your App_Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | #region Using using System; using System.Web; using System.Configuration; using System.Collections.Specialized; #endregion /// <summary> /// Block the response to certain IP addresses /// </summary> public class IpTwentyFourBlockingModule : IHttpModule { #region IHttpModule Members void IHttpModule.Dispose() { // Nothing to dispose; } void IHttpModule.Init(HttpApplication context) { context.BeginRequest += new EventHandler(context_BeginRequest); } #endregion /// <summary> /// Checks the requesting IP address in the collection /// and block the response if it's on the list. /// </summary> private void context_BeginRequest(object sender, EventArgs e) { string ip = HttpContext.Current.Request.UserHostAddress; string[] tempIpArray = ip.Split('.'); string iptwentyfour = tempIpArray[0] + "." + tempIpArray[1] + "." + tempIpArray[2]; if (_IpAdresses.Contains(iptwentyfour)) { HttpContext.Current.Response.StatusCode = 403; HttpContext.Current.Response.End(); } } private static StringCollection _IpAdresses = FillBlockedIps(); /// <summary> /// Retrieves the IP addresses from the web.config /// and adds them to a StringCollection. /// </summary> /// <returns>A StringCollection of IP addresses.</returns> private static StringCollection FillBlockedIps() { StringCollection col = new StringCollection(); string raw = ConfigurationManager.AppSettings.Get("blockiptwentyfour"); foreach (string ip in raw.Split(',')) { col.Add(ip.Trim()); } return col; } } |
collectipaddresses.as
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | import flash.events.*; import flash.net.*; var myRequest:URLRequest = new URLRequest("http://iplocationtools.com/country_query.php?country=CI,SN,GH,NA,NG") var loader:URLLoader = new URLLoader(); loader.dataFormat = URLLoaderDataFormat.TEXT; loader.addEventListener(Event.COMPLETE, handleComplete); loader.load(myRequest); function handleComplete(event:Event):void { var loader:URLLoader = URLLoader(event.target); //trace(loader.data.replace(/\n/g, "|")); var ipArray:Array = loader.data.replace(/\n/g, "|").split("|"); trace(ipArray.length); setTwentyFourBlock(ipArray); } function setTwentyFourBlock(ipArray:Array) { var shortIpArray:Array = new Array(); var lastUniqueIp:String = ""; for each(var ip:String in ipArray) { var tempIpArray:Array = ip.split("."); var stringCurrentIp:String = tempIpArray[0]+"."+tempIpArray[1]+"."+tempIpArray[2]+".0"; if(stringCurrentIp != lastUniqueIp) { lastUniqueIp = stringCurrentIp; shortIpArray.push(stringCurrentIp); } } trace(shortIpArray.length); trace(shortIpArray.join(',')); } |
All of this work has really kept my free online dating site almost spam free for now but I’m adding IP blocks I’ve missed from time to time.