Mosso Cloud Servers DNS records tip

April 17th, 2009

If it happens that you use Mosso Cloud Servers and its DNS management panel remember to always set different name for each record. Otherwise if you want to remove one of them, if there is another record with same name control panel with return an error. In such case the only way to fix your DNS records is to drop whole domain, add it again and recreate all records from scratch. Unfortunately.

GitHub gets an issue tracker

April 16th, 2009

This appeared on Twitter about an hour ago, GitHub has an issue tracker now. Follow the link http://github.com/blog/411-github-issue-tracker to watch the video and read more about it.

Local function variables and parameters in ColdFusion and Railo

April 16th, 2009

Today I was doing some heavy refactoring on a project I am working for quite a long time. Moving methods, changing arguments, removing unnecessary CFCs. We are using PDF and XML merging so the project utilizes Adobe ColdFusion. Now, I am using Adobe CF for like 7 years now, I thought I know it well. While testing changes I have been stopped by an error saying "local variable X declared twice&quot. Something wasn’t right there, I just moved few methods to different components and changed few argument names. It took me good 5 minutes to figure out (even though, what I found out later, the error message was explicitly saying it) that the problem was caused bu using the same function parameter and local variable names. This was very confusing, in any other programming language I used before such an issue doesn’t exist, that was probably why I did not notice I am doing something wrong. To make sure I am right I created this sample CFC.

[source language="cf"]
<cfcomponent>
  <cffunction name="testFunc">
    <cfargument name="arg1" type="numeric" />
    <cfset var arg1 = "" />
  </cffunction>
</cfcomponent>
[/source]

And I called it in the browser. ColdFusion confirmed my assumption. My first thought was "hang on, is this a general CFML issue or just another bit that isn’t working correctly just in Adobe ColdFusion"? I started Railo and created exactly the same CFC. It appears that in Railo it is working as expected, calling the CFC with ?wsdl option returns WSDL definition.

Definitely a hint to remember.

AIR HTTPService does not return response headers

April 16th, 2009

Using Mosso Cloud Servers and Cloud Files for few days now I thought it would be useful to have AS3 library that would let me accessing my Cloud Files account directly from AIR. Just after spending last 2 hours writing prototype I came to the point when I wanted to read response headers that Cloud Files REST API returns and it appears to be impossible (Cloud Files returns authentication data using headers). According to what other people say HTTPService has some major limitations.

It got more interesting when I looked at HTTPStatusEvent.responseHeaders and HTTPRequestMessage.recordHeaders properties. Flex is able to determine proxy server headers only and only when using NetworkMonitor. Otherwise responseHeaders is always null.

I can understand why this limitation exists for Flex applications running in the browser. Not all browsers have the ability to access response headers and Adobe wants to keep Flash Player consistent across browsers. But why this wasn’t fixed for AIR where Adobe has full control on where and how Flash Player is running? And why this isn’t left in competence of the developer as HTTPStatusEvent.status is? I have no idea.

This is really disappointing. Does it mean people have to craft there REST for AIR? I hope someone at Adobe is going to have a look at this issue.

Safely storing configuration with passwords in Adobe AIR applications

April 15th, 2009

Almost every application designed to manipulate users data requires storing custom settings, often with passwords. MySQL on AIR is no different. One of the major features is saving connections settings locally. The most obvious way is to use XML but quickly an issue pops out – how to store passwords? XML is saved as open text unless some kind of encryption/decryption mechanism is implemented. But is it worth implementing such a solution when in most cases it will require storing hash keys on the hard drive or compiled directly in the application? Fortunately Adobe AIR provides mechanism called Encrypted Locale Store. It allows for saving critical bits of information in completely isolated, safe place. I won’t go into details how it works, . I rather focus on how I solved the problem with XML for all noncritical settings and Encrypted Local Store for passwords without the need of compiling any hash into the application itself.

The key lays inside the uk.co.riait.controllers.ConnectionsController class. Basically the idea is to store some unique ID in connection nodes and use the same unique ID as an EncryptedLocalStore.setItem() name argument. Let’s see how it’s done.

[source lang='as3']
package uk.co.riait.controllers {
  import flash.data.EncryptedLocalStore;
  import flash.filesystem.File;
  import flash.filesystem.FileMode;
  import flash.filesystem.FileStream;
  import flash.utils.ByteArray;

  import org.swizframework.controller.AbstractController;

  public class ConnectionsController extends AbstractController {

    [Bindable] public var connections:XML = ;
    private var _initialized:Boolean = false;

    public function init():void {
      if (!_initialized) {
        var dir:File = File.userDirectory.resolvePath( ".mysqlonair" );
        if (!dir.exists) {
          dir.createDirectory();
          writeXml();
        } else {
          var file:File = File.userDirectory.resolvePath( ".mysqlonair/connections.xml" );
          if ( !file.exists ) {
            writeXml();
          }
          var stream:FileStream = new FileStream();
          stream.open( file, FileMode.READ );
          connections = new XML(stream.readMultiByte(stream.bytesAvailable, "utf-8"));
          stream.close();
        }
        _initialized = true;
      }
    }

    public function addConnection(
      type:String, host:String, port:Number, user:String, pass:String, schema:String, name:String, uid:String, existing:Object ):void {
      if ( existing != null ) {
        dropConnection(XML(existing).@uid.toString());
      }
      var node:String = "";
      var xml:XML = new XML(node);
      connections.appendChild(xml);
      var passwordBytes:ByteArray = new ByteArray();
      passwordBytes.writeUTFBytes( pass );
      EncryptedLocalStore.setItem(uid, passwordBytes);
      writeXml();
    }
  }
}
[/source]

Let’s scan through the code quickly, but focus on addConnection() method first. All connection parameters and uid are passed as arguments. First the method checks if connection with given uid exists. If it does it is going to delete it ensuring there is always just one instance of given connection. Next it createss new connection XML node, password is not saved there. Instead uid attribute is set on XML node. Right after appending newly created nodea ByteArray is used to save the password in the local store under uid key and XML is saved to the file.

It is time to focus on init() method. First the method checks it ConnectionsController is already initialized. If it is not it verifies existence of .mysqlonair directory in user’s home directory, creates it if necessary and writes an empty XML file with just a root node. Otherwise, if the directory was found it is going to check if the file is still there. If it is missing it is going to be created, again just root node is going to be saved, then all connections settings will be loaded. So the question now is how the password is accessed?

[source lang='as3']
    [Bindable("dataChange")] public function getConnectionPassword(uid:String):String {
      var passwordBytes:ByteArray = EncryptedLocalStore.getItem(uid);
      return passwordBytes.readUTFBytes(passwordBytes.length);
    }
[/source]

Above method is the answer. This method takes uid argument and reads the password from Encrypted Local Store. To see how it is executed let’s take a look at following test class (my wrapper class does not use events so I’m going to simulate time lapse using timers):

[source lang='as3']
package uk.co.riait.tests {
  import flash.events.TimerEvent;
  import flash.utils.Timer;

  import mx.utils.UIDUtil;

  import uk.co.riait.controllers.ConnectionsController;

  public class ConnectionsControllerTest {

    private var ctrl:ConnectionsController = new ConnectionsController();
    private var uid:String = UIDUtil.createUID();

    public function runTest():void {
      ctrl.init();
      var timer:Timer = new Timer(1000, 1);
      timer.addEventListener(TimerEvent.TIMER_COMPLETE, onInitializedTimer);
      timer.start();
    }

    private function onInitializedTimer(event:TimerEvent):void {
      ctrl.addConnection(
        "MySQL", "someHost", 1000, "username", "P4ssw0rd", "mysql", "Some connection",
        uid,
        null);
      var timer:Timer = new Timer(1000, 1);
      timer.addEventListener(TimerEvent.TIMER_COMPLETE, onSavedTimer);
      timer.start();
    }

    private function onSavedTimer(event:TimerEvent):void {
      trace(ctrl.getConnectionPassword(uid));
    }
  }
}
[/source]

Running the test class creates new ConnectionsController and initializes it. Next in onInitializedTimer() the connection is added and new timer is spawn. In onSavedTimer() method the string P4ssw0rd is displayed. And that was the password I used for new connection.

To delete a connection from XML file a dropConnection() method is used:

[source lang='as3']
    public function dropConnection(uid:String):void {
      delete connections.node.(@uid==uid)[0];
      EncryptedLocalStore.removeItem(uid);
      writeXml();
    }
[/source]

Thanks to this approach MySQL on AIR stores passwords safely without having any knowledge about IDs being used. The only place where IDs are stored is XML file.

What is MySQL on AIR?

April 12th, 2009

It is an Adobe AIR client for MySQL databases. About 3 months ago I moved to Ubuntu as my primary OS and the only thing I was missing was nice MySQL tool. I found few different projects, most obvious ones are MySQL Query Browser and phpMyAdmin, but there are always these small issues… MySQL Query Browser doesn’t allow resizing query area (really annoying when writing large queries) and phpMyAdmin, well… it is phpMyAdmin and it is to big for what I needed.

Remembering that someone created MySQL driver in ActionScript (asSQL) I decided to write an application that will be cross platform and is going to offer as much as any other desktop application would.

Now please remember, this is still work in progress, the code is not well structured and it is changing very often but some major functionality is already there.

MySQL on AIR interface

Following features are currently available:

  • query window with results data grid
  • new table window
  • edit table window
  • SQL editor with code coloring (please check notes on performance below), line numbering and selected query part execution (feature known from MSSQL Management Studio)
  • multiple windows
  • connections management, data stored in XML file, passwords in encrypted storage
  • number of context navigation options (for details please visit following URL http://wiki.github.com/radekg/mysqlonair/todo)

Here is a raw list of options I plan to implement in near feature:

  • query window progress bar and cancelling running query
  • wire all context navigation options
  • create and restore CSV, XML, SQL and YAML backups
  • handling binary files
  • query result data grid improvements, cell alignment and sort support depending on column data type
  • query editor improvement – code hints (similar to what can be found in MSSQL Management Studio 2008)
  • diagrams and foreign keys support

Notes on performance

While developing the application I discovered following performance issues. Code coloring works perfectly on Windows, there is no speed problems even for queries 500 lines long (I didn’t tested larger ones yet). Unfortunately on Linux with Flash Player 10 I could not get good TextRange performance (more information and sample code soon in separate post) so code coloring is by default disabled on Linux (you can enable it if you want). I had no chance to test it on OSX. Second performance issue is results data grid. I tried running large queries and it appears that asSQL driver handles them very well but ArrayCollection does not. I would not try running queries that return large result sets. Other than that everything seems to be working fine. I’m aware of some small driver issues that I’m going to track down and report to asSQL project owner.

License

MySQL on AIR project is available under MIT license, it is free software, you can download, use and modify it free of charge. But please bear in mind that there is no warranty at all and at this stage it is not ready for production environments.

Where is it

If you want give it a try you can check it out from github: git://github.com/radekg/mysqlonair.git. You will then need Flex SDK or Flex Builder to build it.

New server, new blog, new appearance

April 12th, 2009

Welcome to my new blog. After some time I decided to change my ISP from 1&1 to mosso cloudserver (thanks John!) and I totally love it.

It has been a long time since I blogged last, no archives left – I’m starting from scratch, no rants, no bitching, just constructive stuff. What I’m going to blog about? All sorts of RIA topics: Adobe Flex/AIR, Microsoft Silverlight/WPF, jQuery and as many server side technologies I can lay my hands on, who knows, maybe even some JavaFX stuff?

If you want to know more about me check about page.