Blackberry Custom Button Field

March 31, 2008

The Blackberry’s ButtonField doesn’t allow much customisation of how it looks. It is grey when not selected, and when selected it is highlighted. The highlight colour depends on the current theme. The image below shows a ButtonField in the unselected state, and in the selected state with different themes.

Blackberry ButtonFields

Because the ButtonField doesn’t allow you to customise its appearance you must create your own custom field if you wish to do so. My CustomButtonField class below is almost identical to the standard ButtonField, only it allows you to specify the the highlight colour. It also displays the text in white even when the button isn’t selected

import net.rim.device.api.ui.Color;
import net.rim.device.api.ui.Field;
import net.rim.device.api.ui.Font;
import net.rim.device.api.ui.Graphics;

public class CustomButtonField extends Field
{

	private int backgroundColour = Color.GRAY;
	private int highlightColour;
	private int fieldWidth;
	private int fieldHeight;
	private String text;
	private int padding = 8;

	public CustomButtonField(String text, int highlightColour)
	{
		super(Field.FOCUSABLE);
		this.text = text;
		this.highlightColour = highlightColour;
		Font defaultFont = Font.getDefault();
		fieldHeight = defaultFont.getHeight() + padding;
		fieldWidth = defaultFont.getAdvance(text) + (padding * 2);
		this.setPadding(2, 2, 2, 2);
	}

	protected boolean navigationClick(int status, int time)
	{
		fieldChangeNotify(1);
		return true;
	}

	protected void onFocus(int direction)
	{
		backgroundColour = highlightColour;
		invalidate();
	}

	protected void onUnfocus()
	{
		backgroundColour = Color.GRAY;
		invalidate();
	}

	public int getPreferredWidth()
	{
		return fieldWidth;
	}

	public int getPreferredHeight()
	{
		return fieldHeight;
	}

	protected void layout(int arg0, int arg1)
	{
		setExtent(getPreferredWidth(), getPreferredHeight());
	}

	protected void drawFocus(Graphics graphics, boolean on)
	{

	}

	protected void fieldChangeNotify(int context)
	{
		try
		{
			this.getChangeListener().fieldChanged(this, context);
		}
		catch (Exception e)
		{}
	}

	protected void paint(Graphics graphics)
	{
		graphics.setColor(backgroundColour);
		graphics.fillRoundRect(0, 0, fieldWidth, fieldHeight, 8, 8);
		graphics.setColor(Color.GRAY);
		graphics.drawRoundRect(0, 0, fieldWidth, fieldHeight, 8, 8);
		graphics.setColor(Color.WHITE);
		graphics.drawText(text, padding - 1, padding / 2 + 1);
	}
}

You can see the CustomButtonFieldin the image below, which shows it unselected and also selected with a highlight colour of 0×990099.

Blackberry CustomButtonField

If you want to go beyond changing the colours of your buttons then Jonathan Fisher has written up details of a custom BigButtonField that  uses images, allowing you to create some really great looking buttons.

Python Port Scanner

March 29, 2008

Like the whois shell script I posted recently the Python port scanner below is another script I’ve had lying around on my computer for  while. I wrote it when I was first learning Python and its socket API.

#!/usr/bin/env python
from socket import * 

if __name__ == '__main__':
	target = raw_input('Enter host to scan: ')
	targetIP = gethostbyname(target)
	print 'Starting scan on host ', targetIP

	#scan reserved ports
	for i in range(20, 1025):
		s = socket(AF_INET, SOCK_STREAM)

		result = s.connect_ex((targetIP, i))

		if(result == 0) :
			print 'Port %d: OPEN' % (i,)
		s.close()

Example usage:

~$ ./scanner.py
Enter host to scan: localhost
Starting scan on host  127.0.0.1
Port 22: OPEN
Port 80: OPEN
Port 139: OPEN
Port 445: OPEN
Port 631: OPEN

The code could easily be extended to allow the user to specify what ports to scan, or to take the hostname as a command line argument.

Missing locale problems in Linux

March 27, 2008

I’ve recently been doing some work on a Debian server and was running into some errors when using Subversion

 ~$ svn
svn: warning: cannot set LC_CTYPE locale
svn: warning: environment variable LC_CTYPE is en_US.UTF-8
svn: warning: please check that your locale name is correct
Type ‘svn help’ for usage.

The error message tells me that the problem is a missing en_US.UTF-8 locale. I didn’t have root access on this server, so I wasn’t able to install any new locales. Luckily there is a command that prints out all available locales

 ~$ locale -a
locale: Cannot set LC_CTYPE to default locale: No such file or directory
locale: Cannot set LC_MESSAGES to default locale: No such file or directory
locale: Cannot set LC_COLLATE to default locale: No such file or directory
C
POSIX
en_US
en_US.iso88591

Switching my environment variables to en_US.iso88591 fixed the issue.

~$ LC_CTYPE=”en_US.iso88591″
~$ LC_MESSAGE=”en_US.iso88591″
~$ LC_ALL=”en_US.iso88591″

I also added those three lines to my bash_profile so I won’t need to do it again next time I log in.

Blackberry WebBitmapField

March 13, 2008

The standard Blackberry API provides lots of useful UI components, known as fields. The BitmapField can be used to display an image. Recently I’ve needed to display images from the web, so I created the WebBitmapField class.

Anyone who’s done any Blackberry programming knows that getting data off the web can be a bit of a pain. It must be done in a background thread, which must then pass the result back to the UI thread. I’ve created a simple method called getWebData that handles all of this for me. The result is passed back to a WebDataCallback interface:

public interface WebDataCallback
{
	public void callback(String data);
}

getWebData is a static method in my Utils class:

public static void getWebData(final String url, final WebDataCallback callback) throws IOException
{
	Thread t = new Thread(new Runnable()
	{
		public void run()
		{
			HttpConnection connection = null;
			InputStream inputStream = null;

			try
			{
				connection = (HttpConnection) Connector.open(url, Connector.READ, true);
				inputStream = connection.openInputStream();
				byte[] responseData = new byte[10000];
				int length = 0;
				StringBuffer rawResponse = new StringBuffer();
				while (-1 != (length = inputStream.read(responseData)))
				{
					rawResponse.append(new String(responseData, 0, length));
				}
				int responseCode = connection.getResponseCode();
				if (responseCode != HttpConnection.HTTP_OK)
				{
					throw new IOException("HTTP response code: "
							+ responseCode);
				}

				final String result = rawResponse.toString();
				UiApplication.getUiApplication().invokeLater(new Runnable()
				{
					public void run()
					{
						callback.callback(result);
					}
				});
			}
			catch (final Exception ex)
			{
				UiApplication.getUiApplication().invokeLater(new Runnable()
				{
					public void run()
					{
						callback.callback("Exception (" + ex.getClass() + "): " + ex.getMessage());
					}
				});
			}
			finally
			{
				try
				{
					inputStream.close();
					inputStream = null;
					connection.close();
					connection = null;
				}
				catch(Exception e){}
			}
		}
	});
	t.start();
}

The WebBitmapField that makes use of the getWebData method is below. All you need to do is pass a URL to the constructor and it’ll load the image:

public class WebBitmapField extends BitmapField implements WebDataCallback
{
	private EncodedImage bitmap = null;

	public WebBitmapField(String url)
	{
		try
		{
			Util.getWebData(url, this);
		}
		catch (Exception e) {}
	}

	public Bitmap getBitmap()
	{
		if (bitmap == null) return null;
		return bitmap.getBitmap();
	}

	public void callback(final String data)
	{
		if (data.startsWith("Exception")) return;

		try
		{
			byte[] dataArray = data.getBytes();
			bitmap = EncodedImage.createEncodedImage(dataArray, 0,
					dataArray.length);
			setImage(bitmap);
		}
		catch (final Exception e){}
	}
}

Hopefully the WebBitmapField class will be of use to some Blackberry developers. Feel free to use it in your applications.

Whois Shell Script

March 8, 2008

I’ve got loads of little scripts that I’ve written lying around my hard drive. Some I’ve probably only used once and never looked at again, and others I use regularly. I thought I would post some of them here.

Here is a simple shell script that I wrote that performs a whois lookup of every domain name in a given file and outputs the registrant details:

#!/bin/bash
# usage: $0 <domains file>
domains=`cat $1`
for domain in $domains
do
	stripped_domain=${domain#www.} # strip a leading www.
	reg=`whois $stripped_domain | grep -i -A 1 registrant: | tail -n 1`
	echo "[$domain] $reg"
done

Given an input file containing the following domains

www.dowling.me.uk
www.google.com
www.wordpress.com
www.facebook.com

The script will output

[www.dowling.me.uk]     B. Dowling
[www.google.com]        Google Inc. (DOM-258879)
[www.wordpress.com]    	Matt Mullenweg
[www.facebook.com]  	Facebook, Inc

Obviously this is one of those scripts that I used once and never looked at again! :)