Archive for March, 2009

as3Crypto and php, what a fun ride!

Actually not so fun, but I did manage (I should say we because I wasn’t alone in this). Cryptography is not my thing, eh, not everything can be your thing so I accept it. There is just too much to learn: hash functions, public keys, symmetric ciphers, etc. Want we wanted to do was to encrypt data on the As3 side and decrypt it on the php side. I was aware that there was some cryptographic algorythms in the as3corelib, but none of them (MD5, SHA-1) fitted our needs. There is another great cryptography library out there and it is as3Crypto; the problem is that it is a bit hard to get around, there is a lot to choose from. We settled on AES (Advanced Encryption Standard). After 2 hours of trying to get it to work, we found this great post on Google groups (about middle of the page). I am copying the content here to make it easier for people to find. I have to give all the credit for this post to Jason Foglia who posted his code.

Here is the As3 Class:

 
package
{
        import flash.display.Sprite;
        import flash.utils.ByteArray;
 
        import com.hurlant.crypto.symmetric.ICipher;
        import com.hurlant.crypto.symmetric.IVMode;
        import com.hurlant.crypto.symmetric.IMode;
        import com.hurlant.crypto.symmetric.NullPad;
        import com.hurlant.crypto.symmetric.PKCS5;
        import com.hurlant.crypto.symmetric.IPad;
        import com.hurlant.util.Base64;
        import com.hurlant.util.Hex;
        import com.hurlant.crypto.Crypto;
 
        public class CryptoCode extends Sprite
        {
                private var type:String='simple-des-ecb';
                private var key:ByteArray;
 
                public function CryptoCode()
                {
                        init();
                }
 
                private function init():void
                {
                        key = Hex.toArray(Hex.fromString('TESTTEST'));// can only be 8 characters long
 
                        trace(encrypt('TEST TEST'));
                        trace(decrypt(encrypt('TEST TEST'));
                }
 
                private function encrypt(txt:String = ''):String
                {
                        var data:ByteArray = Hex.toArray(Hex.fromString(txt));
 
                        var pad:IPad = new PKCS5;
                        var mode:ICipher = Crypto.getCipher(type, key, pad);
                        pad.setBlockSize(mode.getBlockSize());
                        mode.encrypt(data);
                        return Base64.encodeByteArray(data);
                }
                private function decrypt(txt:String = ''):String
                {
                        var data:ByteArray = Base64.decodeToByteArray(txt);
                        var pad:IPad = new PKCS5;
                        var mode:ICipher = Crypto.getCipher(type, key, pad);
                        pad.setBlockSize(mode.getBlockSize());
                        mode.decrypt(data);
                        return Hex.toString(Hex.fromArray(data));
                }
        }
 
}

Here is the php class:

 
<?
class Crypt
{
        var $key = NULL;
        var $iv = NULL;
        var $iv_size = NULL;
 
        function Crypt()
        {
                $this->init();
        }
 
        function init($key = "")
        {
                $this->key = ($key != "") ? $key : "";
 
                $this->algorithm = MCRYPT_DES;
                $this->mode = MCRYPT_MODE_ECB;
 
                $this->iv_size = mcrypt_get_iv_size($this->algorithm, $this->mode);
                $this->iv = mcrypt_create_iv($this->iv_size, MCRYPT_RAND);
        }
 
        function encrypt($data)
        {
                $size = mcrypt_get_block_size($this->algorithm, $this->mode);
                $data = $this->pkcs5_pad($data, $size);
                return base64_encode(mcrypt_encrypt($this->algorithm, $this->key, $data, $this->mode, $this->iv));
        }
 
        function decrypt($data)
        {
                return $this->pkcs5_unpad(rtrim(mcrypt_decrypt($this->algorithm, $this->key, base64_decode($data), $this->mode, $this->iv)));
        }
 
        function pkcs5_pad($text, $blocksize)
        {
                $pad = $blocksize - (strlen($text) % $blocksize);
                return $text . str_repeat(chr($pad), $pad);
        }
 
        function pkcs5_unpad($text)
        {
                $pad = ord($text{strlen($text)-1});
                if ($pad > strlen($text)) return false;
                if (strspn($text, chr($pad), strlen($text) - $pad) != $pad) return false;
                return substr($text, 0, -1 * $pad);
        }
}
 
?>

Now if you use the encrypt method of one you can send the data to the other one and decrypt it in the other language if you use the same key. Works like a charm. There is a mention that the key can only be 8 characters long but I haven’t tested it out.

, , , , , , , , ,

24 Comments


Show Your Pride: Just Moo

I’m happy to announce that we just lanched today a campaign for the Dairy Farmers of Canada. My part in this was to do develop the microsite, but their was an entire team working on the facebook application, the banners, the widget. We worked really hard on this and I think this is going to be a sucessfull campaign. I went on again using PureMVC even if this was more a website than an application and I can say that I really don’t regret it. Even if we kept adding features, the project grew correctly and I could go back in the code in a month and I would still be a happy developper and understand where everything is. Here is a list of the features / libraries used in the project:

  • PureMVC
  • SWFObject from Google hosted libraries API
  • TubeLoc (I had a few problems using it at first, but I could do it way faster now)
  • The microsite resizes to fit smaller resolutions
  • TweenMax (I am going to use the colorMatrixFilters everywhere now)

One of the goal of the campaign is to get the most people clicking on a button on June 3rd to make a world record. You can click on the button from facebook, banners, the microsite and a widget like this one:

Congrats to the entire team at Twist Image who worked on this. So check it out: The Great Canadian Moo.

And I forgot on June 3rd, go back to the microsite and go beserk on the moo button!

, , , , , , ,

3 Comments


How to handle Stage resizes with PureMVC

I am starting to like the Proxies a lot in PureMVC because I am always creating new ones (Google Analytics Proxy, SWFAddress Proxy, etc) and they are reusable from project to project.

The latest one is a Proxy that keeps track of the resizing of the stage. I found it was a nice way to handle the problem where you set the stage to NOSCALE and you want to handle the resizing yourself. In those situation you would have multiple views/elements reacting differently + you would have to manage adding and removing listener to the stage. Now with one Proxy setting one listener to the stage and sending notifications whenever it resizes, I found it was simpler. Here is the code for my Proxy:

package com.zedia.model{
  import com.zedia.ApplicationFacade;
  import flash.display.Stage;
  import flash.events.Event;
  import flash.events.MouseEvent;
  import org.puremvc.as3.interfaces.IProxy;
  import org.puremvc.as3.patterns.proxy.Proxy;
/**
* Model for the everything that is related to Resizing.
*
*/
  public class ResizeProxy extends Proxy implements IProxy{
    public static const NAME:String = "ResizeProxy";
    private var _stage:Stage;
    public function ResizeProxy(newStage:Stage){
      super(NAME);
      _stage = newStage;
      _stage.addEventListener(Event.RESIZE, _onStageResize, false, 0, true);
    }
 
    public function get stageWidth():Number {
      return _stage.stageWidth;
    }
 
    public function get stageHeight():Number {
      return _stage.stageHeight;
    }
 
    private function _onStageResize(event:Event):void {
      facade.sendNotification(ApplicationFacade.STAGE_RESIZE);
    }
  }
}

Now in the StartupCommand of your application you register the Proxy and pass it an instance of the stage. It is easy to do so because you already have to pass one instance of the stage to the ApplicationMediator. Once that is done, your Proxy is running and sending the notifications. All that is left is to listen and to handle the notifications in the Mediators of the views that needs to react to the resizing; as simple as that.

, ,

10 Comments


Introduction to Adobe AIR

I know this isn’t the usual content, it being introductory level, but I got to write this piece in order to try to raise the general awareness about Adobe AIR where I work. My true goal being that project managers and account directors get a better feel of AIR and push it more to the clients, resulting,  in the end, that I would get to do more AIR apps (i got plenty of these little machinations). I am not sure it got the attention it deserves, so I am putting it here, where, with a little Google love it might get a bigger audience.

I’ve been playing lately with Adobe AIR and I was thinking that it might be a good idea to give you an overview of what it is to help us all grasp its full potential.

AIR is made by Adobe and is based on the Flash Player. What this means is that it can do almost all of the things that you would expect from a Flash file (.swf). The particularity of AIR comes from the fact that it doesn’t need to be embedded into an HTML page to work. An AIR application is made to runs on your desktop, just like any other application.

Let’s take a look at how an AIR application differentiates itself from a regular Flash file.

Installation

In order to run an AIR application, you must first download the AIR runtime; this is similar to how Flash files require the Flash Player. Once the AIR runtime is installed, you can begin downloading and installing AIR packages (.air files).

When offering AIR applications for download, you can use what’s known as a badge. A badge is a little piece of Flash that you put on your website that will do two things:

  1. First, the badge will check if the user has the AIR runtime installed. If not, it will install the runtime first.
  2. Then, the badge will proceed to download and install the desired AIR application.

This makes the installation process remarkably painless. For an example of a badge in action check out Agile Agenda. You will see the badge roughly in the middle of the page.

Automatic Updates

Another nice feature of Air is the fact that an application can keep itself up to day by automatically checking for new versions on a central server. If a newer version is found, the application will download the updated version of itself and install it. This is a great way to manage code enhancements and bug fixes after the initial application release or while the client is reviewing the final product prior to launch.

Cross-platform functionality

Just like Flash, AIR applications should function precisely the same way on all systems, regardless of operating system. This means we should see the same results on Macs as we do on PCs and other platforms.

Database interactions

AIR can create and interact with a local database (SQLite), as well as write and read files from the user’s hard drive. This allows developers to create applications that can function even without the need of an internet connection.

Additional features

On top of the remarkable features noted above, AIR also features:

  • To open a file, simply drag and drop a file over the AIR application;
  • AIR applications can run in the background;
  • Applications can send tray notifications, much like when a user connects to MSN Messenger;
  • Applications can be included within the start menu in the same way as other common applications;
  • AIR can detect whether the system is connected to the internet or not;
  • …and many more.

But what is it made of?

AIR applications are built using ActionScript 3. This means applications can be developed in Flex, Flash, or even by using javascript. The latter means that AIR applications can be developed by Integrators as well, not only Flash developers. Common libraries that I have seen used for this purpose include jQuery and Dojo.

A few notable drawbacks

While AIR has many wonderful qualities, it is not without its faults. It is not yet suited for just any type of desktop application. The current version is 1.5, which means it is still in its infancy. AIR applications can on occasion take up a lot of memory, and it can sometimes run rather slow. Accordingly, its use should be limited to building widgets and small sized applications.

However, even with these limitations, AIR is a great tool to have in your toolbox. I hope you now have a better understanding of this emerging technology.

I also have to give some love to StrategicText, because he did some editing to the text and made it even better.

, ,

3 Comments


Shaving some kb when using TweenLite (or TweenMax)

Introduction

I was working on some banners lately and with banners, every kilobytes counts. So I downloaded the new version of  TweenLite for AS2 (because I can’t do shit without TweenLite) and noticed so weird behavior (not so weird once you understand about the file size. I mostly has to do with the new plugin architecture, which I wasn’t acustumed to.

When you unpack the downloaded file from TweenLite, there is in there, a very usefull Plugin Explorer to help you understand how plugins work and to generate the code you need to activate only the plugins you want which looks something like:

import gs.plugins.*;
TweenPlugin.activate([ColorMatrixFilterPlugin, BlurFilterPlugin]);

With that code you would activate the ColorMatrixFilter plugin and the BlurFilter Plugin. I tought at first that that would be the only plugins activated and so the Plugin Explorer was telling me that if you activate only these plugin TweenLite should only add 5.5kb to my file.But that wasn’t what I was seeing it was more around 8kb (I know that isn’t much different but when you do banners, you fight for every kb).

Here is the solution

It turns out that when call the TweenPlugin.activate method, even if you say to activate only 2 plugins, it doesn’t deactivate the plugins that are activated by default. In order to do so, you have to go in the file TweenLite.as and comments the lines where these are activated like this:

...
//this starts on line 257 of the TweenLite.as file VERSION: 10.09
 
public function TweenLite($target:Object, $duration:Number, $vars:Object) {
if (TweenLite.timerClip._visible != false || !_tlInitted) {
 
TweenPlugin.activate([
 
//ACTIVATE (OR DEACTIVATE) PLUGINS HERE...
 
//TintPlugin,
// RemoveTintPlugin,
//   FramePlugin,
//   AutoAlphaPlugin,
//    VisiblePlugin,
//     VolumePlugin,
//   EndArrayPlugin
 
//So by commenting these previous lines, these plugins won't be activated thus saving you some kb
]);

You have to get your hands dirty, but in the end you gain a lot of flexibility plus you have only what you need activated.

More stuff on TweenLite

Well I’m always playing with TweenLite, so the other day I was using the ColorMatrixFilterPlugin on some really big MovieClips (9000px large). Well it turns out that Flash isn’t able to do bitmap manipulations (Matrices or Filters) on MovieClip bigger than 2800px.  So my Tweens on them would just not work (not TweenLite’s fault). What you have to do is segment your big MovieClip in chunks of 2800px and do a Tween on each of them at the same time.

Lastly, on the TweenLite website today you could read that Jack Doyle (TweenLite creator) and Grant Skinner (creator of gTween) will be working together on the next version of TweenLite/TweenMax. This can only mean great things for the future of this Tweening library! I look forward to the next version.

, , , , , ,

2 Comments


Date range query using SQLite and AIR

I decided I would investigate more on Dates and SQLite. As you know I had some trouble when trying to extract a date range from my SQLite database because Flash and SQLite don’t save dates in the same format.  Flash saves it in UTC format and SQLite as a Julian day.

Looking around a bit I found on the php website some information about how to do the conversion from Julian day to UTC.  All I had to do was to turn the formula around. But that didn’t work because the Date in Flash is also offested to account for the timezone of where the computer is. Once that was solved, everything worked fine. Here is a function that will do the conversion:

function UTCToJulianDay(newDate:Date):Number{
  return ( newDate.time - (newDate.getTimezoneOffset()*60000))  / 86400000) + 2440587.5)
}

The time method of Date object return milliseconds so we have to change everything in milliseconds. The getTimezoneOffset  method returns minutes so by multiplying by 60000 you get its millisecond equivalent. 86400000 is the number of milliseconds in a day and 2440587.5 is the julian day at 1/1/1970 0:00 UTC.

So using this function will enable you to use the greater than, lesser than and BETWEEN operator in SQLite when you want to search for date ranges. Here are some example of SQL query you might do:

sqlStmt.text = "SELECT * FROM main.Entry WHERE dateF >; " + UTCToJulianDay(new Date());
//this will return all entries where dateF is bigger than now
 
var date1:Date = new Date(2009, 2, 3) ; //March 3rd 2009
var date2:Date = new Date(2009, 3, 3); //April 3rd 2009
 
sqlStmt.text = "SELECT * FROM main.Entry WHERE dateF BETWEEN " + UTCToJulianDay(date1) + " AND " + UTCToJulianDay(date2) ;
//this will return all entries  Between March 3rd and April 3rd

It is that easy to do date range comparison; you just have to know how.

, , , , , ,

8 Comments