Snippets code from my daily experience

March 25, 2009

Komodo maintenant parle Français (Komodo now speaks French)

Filed under: babelzilla,komodo,localization,openkomodo — dafi @ 6:25 pm

The Babelzilla Team is proud to present the (unofficial) Komodo French localization.

Komodo 5.1 has been released, it contains many cool features and the Babelzilla guys have completed the FIRST localization, the first one.

You can find further details at French Mozilla blog and the installation instructions at BabelWiki

A special thanks goes to Goofy that coordinated the L10N work.

Thanks guys, you made the world a better place without linguistic barrier.

December 22, 2008

Downloading protected resources using nsIChannel and friends

Filed under: babelzilla,extension,komodo,macro,nsIChannel,nsIStreamListener — dafi @ 2:35 pm

A couple of days ago I needed to automate file downloading from a service, a very trivial task in every programming language (or using wget).

The little complication was represented by the web based authentication mechanism (userid/password) needed to access to files.
Determining which files to download and their usage (unzipping and picking files) required some specific business logic, nothing really complicated but very annoying.

After a while I realized this job can be done using Javascript and XPCOM and here I would share the solution based on nsIChannel.

What is does

  • the service uses userid and password to login
  • login to the service using HTTP POST method, it simulates an HTML <form/> submission
  • store the cookies sent from server. They contains credentials login data, cookies usage is a prerequisite in our scenario
  • reuse login data to download protected resources

Example usage

Suppose you want to automate download of extensions stored on AMO‘s sandbox, you must login first so this use-case is perfect for us.
Someone can consider this approach ugly, web services or Remora API are better but here I only want to demonstrate how to use nsIChannel.

Let’s start…

You can write the Javascript code shown below to download my extension RichFeedButton (dropped on sandbox an year ago)

var amoUsername = "dafi@localhost";
var amoPassword = "my_secret_code";
downloadProtectedResource(
   "https://addons.mozilla.org/it/firefox/users/login",

   "data[Login][email]=" + amoUsername + "&data[Login][password]" + amoPassword,

   "https://addons.mozilla.org/en-US/firefox/downloads/file/33926/richfeedbutton-0.0.21-fx.xpi",

   "/tmp/richfeedbutton-0.0.21-fx.xpi");

where our downloadProtectedResource function signature is shown below

function downloadProtectedResource(loginUrl, postData, resourceUrl, destPathName) { ... }

Nothing special, simply we need to know the HTML input names used for userid and password (ie data[Login][email] and data[Login][password]) and pass them in postData argument.

The downloadProtectedResource interacts with nsIChannel (nsIHttpChannel) and other XPCOM object

function downloadProtectedResource(loginUrl, postData, resourceUrl, destPathName) {
   var httpChannel = makeHttpChannel(loginUrl); // create an object nsIHttpChannel
   var stream = makeStringStream(postData); // create an object nsIStringInputStream
   setChannelPostData(httpChannel, stream); // fill data using nsIUploadChannel

   // downloader saves data on disk
   var downloader = new Downloader(resourceUrl, destPathName);
   // make a login then passes cookies to downloader object
   var cookieListener = new CookieRetrieverListener(downloader);

   // start authentication and download
   httpChannel.asyncOpen(cookieListener, null);
}

The object Downloader and CookieRetrieverListener implement the nsIStreamListener interface.

The cookieListener after obtaining cookies aborts the operation because we don’t need all server output, then it calls the downloader.

function CookieRetrieverListener(downloader) {
   this.downloader = downloader;
   this.cookies = "";
}

CookieRetrieverListener.prototype = {
   onStartRequest: function(request, ctx) {
         var channel = request.QueryInterface(Components.interfaces.nsIHttpChannel);
         this.cookies = channel.getRequestHeader("Cookie");

         // no need more data
         throw Components.results.NS_ERROR_ABORT;
   },

   onDataAvailable : function(request, context, inputStream, offset, count) {
   },

   onStopRequest: function(request, ctx, status) {
      this.downloader.cookies = this.cookies;
      this.downloader.start();
   }
}

Another way to use this code consists to download localizations from BabelZilla as shown below.
BabelZilla requires many parameters on query string 😕


var bzUsername = "dafi_duck";
var bzPassword = "my_secret_code";
var bzItemId = "88";
var bzExtId = "4432";
downloadProtectedResource("http://www.babelzilla.org/index.php",
                 "op2=login&lang=english&message=0"
                        + "&option=ipblogin&task=login&0b14737c5ade1f7697a8f81b33b0bacf=1"
                        + "&option=com_frontpage&Itemid=1"
                        + "&username=" + bzUsername
                        + "&passwd=" + bzPassword,
                 "http://www.babelzilla.org/index.php?option=com_wts&type=downloadtar"
                        + "&Itemid=" + bzItemId
                        + "&extension=" + bzExtId,
                 "/tmp/vsw.tar.gz");

nsIChannel.asyncOpen

Accessing to cookies received from server requires to use nsIStreamListener available only in asynchronous open calls.

This needs to start the download only when cookies are surely retrieved, this is achieved using the nsIRequestObserver.onStopRequest, any better idea is very appreciated.

Complete code

The complete code contains a few of helper functions (reading binary stream, saving file) and is available on SVN, it’s ready to be executed as Komodo macro simply setting userid and password.

December 13, 2008

Komodo French Localization coming soon

Filed under: babelzilla,komodo,localization — dafi @ 10:56 am

This morning I’ve found a couple of emails coming from my BabelZilla forum subscriptions, after reading them I went to WTS homepage where I saw the image shown below.

komodo-locale

Fantastic! The French localization is completed, 2016 strings translated!

When I asked to BabelZilla guys to localize Komodo I could not imagine they did it so quickly.

Many activities must be coordinated with ActiveState team

  • Remove all hardcoded strings (amazingly new code continues to be written with hard-coded strings!!! 😯 😕 )
  • Establish a time deadline to froze new strings added to trunks (this can drastically simplify localization cycle)
  • Lang Pack release process and better integration with code development lifecycle

But be calm dafi 😛 … one step at a time

I want to say thanks to Goofy, the BabelZilla Super Mod, and Pedro the Italian localizer that helped me from the beginning, they helped me to “extract” hard-coded strings and prepare patches to submit.
A big “thank you” goes to all localizers (especially the French community) for dedicating time and passion to this work.

Technically speaking an installable French lang pack is already ready for KomodoEdit v5.0.2, French team are completing the quality test and everybody can help them.

Who want to see Komodo in French can register on Babelzilla and read more at Komodo Lang Pack forum thread…

… and Goofy has already localized in French my extension TabSwitcher

August 7, 2008

Alea iacta est: OpenKomodo localized

Filed under: babelzilla,komodo,localization,openkomodo — dafi @ 6:59 pm

Alea iacta est the first OpenKomodo lang pack has landed.

I’ve already spoken about KomodoEdit localization and now the french Babelzilla team has terminated the first version, the official announcement has posted at Mozilla Europe site.

I’m very happy, I’ve developed macros to simplify lang pack testing and created a simple webapp to convert babelzilla locale tarballs to installable xpi langpacks.

Maybe ActiveState guys hate me because the translation idea started from me, but I believe localized (and open) softwares are simpler to use in schools, poor information environments and any low profile educational eco-systems.

The italian lang pack is coming soon, I will be very proud to use KomodoEdit in my mother tongue.

I hope other localizations can arrive very soon

July 12, 2008

KomodoEdit localization

Filed under: babelzilla,localization,openkomodo — dafi @ 8:01 am

I’ve asked to babelzilla community if they are interested to translating KomodoEdit and immediately they reply to me that this is possible.

So I’ve posted into Komodo forum to understand if ActiveState is interested, too.

Well, all is ready and I’m glad to have started this process.

I don’t know what this experiment will produce but I’m happy to see collaborations between so different communities.

I hope to see very soon the first KomodoEdit in non english language 😛

Blog at WordPress.com.