In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

Google guitar doodle

I consider this code just a stub. Somebody please pick it up and make it perfect :)
/**
 * Copyright makc3d ( http://wonderfl.net/user/makc3d )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/rYLV
 */

// forked from wh0's Using proxies without crossdomain.xml
package {
	import com.bit101.components.Label;
    import flash.display.Loader;
	import flash.display.LoaderInfo;
    import flash.display.Sprite;
    import flash.events.Event;
	import flash.events.KeyboardEvent;
	import flash.system.ApplicationDomain;
	import flash.system.LoaderContext;
	import flash.ui.Keyboard;
//import flash.net.FileReference;
    import flash.net.URLLoader;
    import flash.net.URLRequest;
    import flash.system.Security;
	import flash.utils.ByteArray;
	import flash.utils.setTimeout;
    public class FlashTest extends Sprite {
        
        // Wrap url in proxy parameter.
        private function proxy(url:String):String {
            return 'http://www.gmodules.com/ig/proxy?url=' + encodeURIComponent(url);
        }
        
        public function FlashTest () {
//init (null); return;
            // Only the top level movie starts off with stage populated.
            if (stage) {
                // The top level movie is likely included from wonderfl.net and therefore unproxied.
                // All we do in this case is load the proxied version.
                // Allow the proxy domain so wee can access stage on lines 45-46.
                Security.allowDomain('www.gmodules.com');
                var l:Loader = new Loader();
                l.load(new URLRequest(proxy(loaderInfo.url)));
                addChild(l);
                return;
            } else {
                // Allow Wonderfl to take a screen cap.
                Security.allowDomain('swf.wonderfl.net');
                addEventListener(Event.ADDED_TO_STAGE, init);
            }
        }
        
        private function init(e:Event):void {
            removeEventListener(Event.ADDED_TO_STAGE, init);
            
            // Now you write your own code.
            // Since the inner proxied movie is in the proxy's domain, we can request anything.
            var ul:URLLoader = new URLLoader;
			ul.dataFormat = 'binary';
            ul.addEventListener(Event.COMPLETE, complete);
			ul.load (new URLRequest (proxy (
				'http://static.googleusercontent.com/external_content/untrusted_dlcp/www.google.com.ua/uk/ua/logos/swf/guitar11.swf'
			)));
        }
        
        private function complete(e:Event):void {
			var ul:URLLoader = URLLoader (e.target);
			// unfortunately doodle's playTrack() method is private
			// and only exposed through ExternalInterface :((
			// therefore we need to patch its bytecode before loading it
			var uncompressed:ByteArray = decompress (ul.data);
//new FileReference().save (uncompressed);
			if (uncompressed [0x1A361] == 5) {
				uncompressed [0x1A361] = 22; // change relevant namespace to public
				uncompressed [0x1A362] = 1;
				uncompressed [0x1A7AA] = 71; // prevent SecurityError (exit constructor early)

				// ok to load it
				var loader:Loader = new Loader;
				loader.contentLoaderInfo.addEventListener (Event.COMPLETE, gotDoodle);
				loader.loadBytes (uncompressed,
					new LoaderContext (false, ApplicationDomain.currentDomain)
				);
			} else {
				new Label (this, 10, 10, "sorry, doodle swf was updated, this code was not :(");
			}
        }

		private var doodle:*;
		private function gotDoodle (e:Event):void {
			doodle = LoaderInfo (e.target).content;
			stage.addEventListener (KeyboardEvent.KEY_DOWN, onKeyDown);

			// now some presets from twitter
			new Label (this, 10, 10, "use same keys as in doodle, or pick one of presets");
			new PresetButton (this, 10, 40, "Imperial march", "3,,3,,3,,1,,5,3,,1,,5,3,,,,,,7,,7,,7,,8,,5,3,,1,,5,3", playPreset);
			new PresetButton (this, 10, 70, "Godfather theme", convertPreset1 ("dhkjhkhjhfgd"), playPreset);
			new PresetButton (this, 10, 100, "Moon river", convertPreset1 ("toiuytrtquytrtqw"), playPreset);
		}

		private var keyCodes:Object = {
			1: Keyboard.NUMBER_1,
			2: Keyboard.NUMBER_2,
			3: Keyboard.NUMBER_3,
			4: Keyboard.NUMBER_4,
			5: Keyboard.NUMBER_5,
			6: Keyboard.NUMBER_6,
			7: Keyboard.NUMBER_7,
			8: Keyboard.NUMBER_8,
			9: Keyboard.NUMBER_9,
			0: Keyboard.NUMBER_0,
			q: Keyboard.Q,
			w: Keyboard.W,
			e: Keyboard.E,
			r: Keyboard.R,
			t: Keyboard.T,
			y: Keyboard.Y,
			u: Keyboard.U,
			i: Keyboard.I,
			o: Keyboard.O,
			p: Keyboard.P,
			a: Keyboard.A,
			s: Keyboard.S,
			d: Keyboard.D,
			f: Keyboard.F,
			g: Keyboard.G,
			h: Keyboard.H,
			j: Keyboard.J,
			k: Keyboard.K,
			l: Keyboard.L,
			z: Keyboard.Z,
			x: Keyboard.X,
			c: Keyboard.C,
			v: Keyboard.V,
			b: Keyboard.B,
			n: Keyboard.N,
			m: Keyboard.M
		}

		private function playPreset (event:Event):void {
			var preset:String = PresetButton (event.target).preset;
			var keys:Array = preset.split (",");
			for (var i:int = 0; i < keys.length; i++) {
				if (String (keys [i]).length == 1) {
					trace ("key", keys [i], "code", keyCodes [keys [i]])
					setTimeout (onKeyDown, 250 * (i + 1), { keyCode: keyCodes [keys [i]] });
				}
			}
		}

		private function convertPreset1 (str:String):String {
			return str.split ("").join (",,");
		}

		// was exposed via ExternalInterface.addCallback
		public function playTrack (trackName:String, channelName:String, volume:Number = 1, pan:Number = 0):void {
			doodle.playTrack (trackName, channelName, volume, pan);
		}

		// was exposed via ExternalInterface.addCallback
		public function stopChannel (channelName:String):void {
			doodle.stopSound (channelName);
		}

		// keydown handler ("ra" from js)
		public function onKeyDown (e:Object):void {
			// it's hard to tell what a hell is going on there as
			// the code is obfuscated; this is all just a guess
			var Y:Number = fixMap [trackIds [e.keyCode]];
			if (Y >= 0 && Y < 12) {
				playTrack ("guitar-" + (Y < 10 ? "0" : "") + Y, "" + /*Y*/Math.random ());
			}
		}

		// key mappings ("xa" from js)
		public var trackIds:Object = {
			49: 2,
			50: 6,
			51: 3,
			52: 0,
			53: 7,
			54: 1,
			55: 8,
			56: 4,
			57: 9,
			48: 5,
			81: 2,
			87: 6,
			69: 3,
			82: 0,
			84: 7,
			89: 1,
			85: 8,
			73: 4,
			79: 9,
			80: 5,
			65: 2,
			83: 6,
			68: 3,
			70: 0,
			71: 7,
			72: 1,
			74: 8,
			75: 4,
			76: 9,
			186: 5,
			90: 2,
			88: 6,
			67: 3,
			86: 0,
			66: 7,
			78: 1,
			77: 8,
			188: 4,
			190: 9,
			191: 5
		}

		// apparently xa variable values do not correspond to track id directly
		public var fixMap:Object = {
			2: 0,
			6: 1,
			3: 2,
			0: 3,
			7: 4,
			1: 5,
			8: 6,
			4: 7,
			9: 8,
			5: 9
			// 2 more notes?
		}

		/**
		 * @author Nikita Leshenko
		 * @see http://active.tutsplus.com/tutorials/workflow/protect-your-flash-files-from-decompilers-by-using-encryption/
		 */
		private function decompress (data:ByteArray):ByteArray {
			var header:ByteArray = new ByteArray;
			var compressed:ByteArray = new ByteArray;
			var decompressed:ByteArray = new ByteArray;

			header.writeBytes (data, 3, 5); // read the uncompressed header, excluding the signature
			compressed.writeBytes (data, 8); // read the rest, compressed

			compressed.uncompress ();

			decompressed.writeMultiByte ("FWS", "us-ascii"); // mark as uncompressed
			decompressed.writeBytes (header); // write the header back
			decompressed.writeBytes (compressed); // write the now uncompressed content

			return decompressed;
		}
    }
}

import com.bit101.components.PushButton;
import flash.display.DisplayObjectContainer;
class PresetButton extends PushButton {
	public var preset:String;
	public function PresetButton (parent:DisplayObjectContainer, xpos:Number, ypos:Number, label:String, preset:String, defaultHandler:Function) {
		super (parent, xpos, ypos, label, defaultHandler); this.preset = preset;
	}
}