Thursday, 8 May 2008

Blog moved...

Just a quick note: I've moved my blog to a Drupal-based site at http://colby.id.au... so go go there for my new blog site :)

Paul.

Friday, 9 March 2007

Internet Explorer's window title

Ok, so I found the registry key responsible for Telstra Bigpond's irritating branding of Internet Explorer's window title:

HKEY_USERS\S-1-5-21-682003330-789336058-839522115-1004\Software\Microsoft\Internet Explorer\Main\Window Title -> "Telstra BigPond Home Internet Explorer"

So I just used the registry editor to change it back to "Microsoft Internet Explorer". Actually, I then experimented a little... I removed the value entirely, and in response, IE's title became "Windows Internet Explorer" - interesting.

Ah well, anyway, I've produced this really simple registry patch to fix the problem in case anyone else wants to get rid of Telstra's (or some other company's) annoying branding:

Windows Registry Editor Version 5.00
[HKEY_USERS\S-1-5-21-682003330-789336058-839522115-1004\Software\Microsoft\Internet Explorer\Main]
"Window Title"="Microsoft Internet Explorer"

Just save it as a .reg file, and "merge" it (the default when you double-click). Of course, you can change the title to anything you want. If you leave it blank, (ie "") it looks a little funny... the title will be (for example) "PC Thoughts -". So I've decided to set mine to "ie" - nice and simple ;)

Paul.

Labels: ,

I hate Telstra software

Completely typical! I've just installed Telstra's BigPond Wireless Broadband client (unavoidable I'm afraid), and the installer has violated my PC in two ways (so far):

  1. the installer changed my browser's home page to some useless BigPond page; and

  2. the installer changed my browers's title from "Internet Explorer" to "Telstra BigPond Home Intenet Explorer"... that's right, viewing this site, my browser's window title actually reads "PC Thoughts - Telstra BigPond Home Internet Explorer"... arghh!!


Now I can understand that the weasels, opps, I mean "managers" at Telstra want to maximise Telstra's branding, but at the very least they should have provided an opt-out tickbox during the install process!! Obviously the first violation is easy to fix (though no less offensive), but now I'm going to have to search the registry / internet to fix the second one! :(

I do not want my PC to be branded "Telstra BigPond" in any way! Especially considering that BigPond is, by far, the least of three ISPs that I use. And while I'm on that... what if my homepage had been set to Optus, or some other ISP? Surely then, I, or someone else, could claim that Telstra's installer is abusing its position in an anti-competitive manner?

In case you haven't noticed yet, this has really pi$$ed me off!! And the worst thing is this: I knew the stupid installer would do such things before I even inserted the CD! :(

There's really only one solution - change ISPs... but what's this you're saying about a monopoly? :(

Paul.

Labels: ,

Thursday, 18 January 2007

Stealing from the (Steel)Vine

First some background: The Asus P5W-DH Deluxe includes an Silicon Image SiI4723 hardware RAID controller. Yes, that's hardware RAID - not fakeraid. And since the controller presents the OS with just one logical disk (as it should), Silicon Image provide a utilty called SteelVine Configuration Manager (SVCM) that can be used to view the current state of the controller and attached disks / arrays.

Now, since we use an Asus P5W-DH Deluxe for a server at work, it would be good to be able to get email (or SMS) notifications if the array becomes degraded. The obvious play to start is with the SVCM.

The bad news: SVCM is a graphical application - and scraping status information from the SVCM GUI is not that easy :(

The good news: SVCM has been implemented with a server / client architecture, using TCP to communicate between the two. So, it should be possible to create our own clone of the SVCM client. It turns out that SVCM uses a simple XML protocol, and that the server is stateless (so far as I can tell), so that should make getting the info we want pretty easy. However, there was one little hurdle that needed to be overcome first.

The SVCM client / server protocol seems to be:
1. Client connects the server on port 51115.
2. Client sends XML request.
3. Server sends XML response.
4. Client goes back to step 2, or closed the connection.

To get the info we need, we only needed to send the "SVConfigCmd" request. And since my language of choice for such a simple task is BASH, I tried to use netcat to submit the request for me:

$ echo "<SVConfigCmd/>" | nc localhost 51115

This gets the correct response, just as I wanted, but it crashes the SVCM server :(

$ ./start_server.sh
Starting SteelVine daemon
FOUND A RIGEL DEVICE!!
(performed request via netcat here)
Mutex destroy failure: Device or resource busy
pure virtual method called
./start_server.sh: line 12: 12304 Aborted SteelVine -e

Some quick playing revealed that the problem only occurs when the client disconnects immediately after it reads the response. If there is any noticable delay at all, then the server will not die. Presumably, the offical SVCM client would crash the server too if you managed to run it, and exit it very quickly.

So anyway, the solution is simply to add a small delay before disconnecting... but how to do that? It would be easy if we were using a programming langugae with TCP/IP sockets such as perl or C/C++, but this is BASH...

Well, the solution was pretty obvious - I just needed to create something that would output the XML request to stdout and then pause for some amout of time before closing stdout. This would, of course, cause netcat to do something very similar, which is exactly what we want. I suppose this could be done in a number of ways, but I chose to do it like this:

$ bash -c 'echo "<SVConfigCmd/>" ; sleep 1' | nc -w3 localhost 51115

There! A simple 1 second sleep, and the SVCM server now keeps running :)

From there, it was trivial to write a BASH script that parses the XML result, and fires off an email if the RAID array and/or disks are reported as degraded in any way.

Paul.

Friday, 1 December 2006

Seeding db2's RAND function

Most computers cannot generate truly random numbers. For this reason, many computer programming languages include pseudo-random number generators. These pseudo-random generators usually need to be seeded so that they don't always reproduce the same sequence of numbers.

The most common approach to seeding the generator, is to do so once per execution / session - ether manually (eg C/C++), via a constructor (eg Java), or automatically (eg JavaScript/ECMAScript). However, IBM's db2 allows the programmer to optionally seed the generator each time the RAND function is called, and not in any other way.

So, given that the common approach mentioned above is a good ballance between efficiency and randomness, I have written a really simple RANDOMIZE stored procedure for db2 that can be called once per session to increase the probability that each session will receive a unique sequence of psuedo-random numbers. And here it is:

CREATE PROCEDURE randomize ( )
  DYNAMIC RESULT SETS 0
  READS SQL DATA
  NOT DETERMINISTIC
  LANGUAGE SQL
  NO EXTERNAL ACTION
BEGIN
  DECLARE time TIMESTAMP;
  DECLARE seed BIGINT;
  DECLARE ignored DOUBLE;

  SET time = CURRENT_TIMESTAMP;
  SET seed = ( BIGINT(MINUTE(time) ) * 60 + SECOND(time) ) * 1000000 + MICROSECOND(time);

  SET ignored = RAND(INTEGER(MOD(seed,2147483648)));
END

There's really nothing fancy about this stored procedure... it simply uses the current time (with microsecond accuracy) to seed db2's psuedo-random number generator. So a typical use might look something like this:

...
CALL RANDOMIZE();
...
SET random_number_1 = RAND();
SET random_number_2 = RAND();
...
SET random_number_n = RAND();
...

Very simple :)

Paul.

Labels:

Sunday, 26 November 2006

textRollOverColor in Flex DataGrid part 2

In my last post I presented a simple way to customise the DataGridItemRenderer class so the Flex DataGrid control would use the textRollOverColor and textSelectedColor styles correctly. But I also noted that the solution would not fix the DataGrid header items... well, here's my solution to that problem.

First of all, it's worth noting that there are two main reasons why a custom DataGridItemRender is not adequate for the DataGrid header items. The first reason is that the renderer's validateNow() method is almost never called for header items, even though it also called correctly, and often, for the data items. And the second reason is this: the validateNow() method (both the original version, and my custom version) depends on two DataGrid methods in order to determine which text style to use. Those methods are isItemHighlighted() and isItemSelected(). However, neither of those methods work for header items - they both always return false, making them of no use in determining text color for header items.

So, to correctly use the textRollOverColor and textSelectedColor styles, I created a custom DataGrid control that overrides three mouse handlers: mouseDownHandler(), mouseOverHandler(), and mouseOutHandler(). The overrides are as follows:

override protected function mouseDownHandler(event:MouseEvent):void {
  super.mouseDownHandler(event);
  if (enabled && sortableColumns && isHeaderItem(event.target)) {
    var col:int = listItems[0].indexOf(event.target);
    if (columns[col].sortable && event.target.hasOwnProperty("textColor"))
      event.target.textColor = event.target.getStyle("textSelectedColor");
    }
  }

override protected function mouseOverHandler(event:MouseEvent):void {
  super.mouseOverHandler(event);
  if (enabled && sortableColumns && !event.buttonDown && isHeaderItem(event.target)) {
    var col:int = listItems[0].indexOf(event.target);
    if (columns[col].sortable && event.target.hasOwnProperty("textColor"))
      event.target.textColor = event.target.getStyle("textRollOverColor");
  }
}

override protected function mouseOutHandler(event:MouseEvent):void {
  super.mouseOutHandler(event);
  if (isHeaderItem(event.target) && event.target.hasOwnProperty("textColor"))
    event.target.textColor = event.target.getStyle("color");
}

protected function isHeaderItem(item:Object):Boolean {
  return ( showHeaders && (listItems[0].indexOf(item)>=0) );
}

So now if we put together the custom DataGridItemRenderer from the last post, and a custom DataGrid control with the above overrides, then we have a DataGrid control that uses the textRollOverColor and textSelectedColor styles almost perfectly. I say "almost" because the DataGrid control will still use the base text color when re-ordering columns by dragging, but other than that, it all works as I'd expect it to :)

I've put together a really simple demo app, which you can play with here, and/or view the source.

Paul.

Labels:

Saturday, 25 November 2006

textRollOverColor in Flex DataGrid

According to Adobe's documentation, the Flex DataGrid control supports the textRollOverColor CSS property. But this past week I discovered that that this is not the case :( A quick search revealed that I'm not alone in this discovery, but it seems that no one has proposed a useful solution yet... so I went about creating my own :)

So, why doesn't it work as documented? Well, a quick check revealed that the relevant text colors are supposed to be set in the DataGridItemRenderer's validateNow() method. That method sets the item's explicitColor property, and then calls the super.validateNow() method to update the display. However, the super (UITextField) class' validateNow() method does not update the text format unless the styleChangedFlag property is set - but that flag is not being set. Since the styleChangedFlag property is marked as private, I can only assume that it is meant to be set by the relevant setter functions, but as there is no setter function for the explicitColor property, the styleChangedFlag is not set.

So, what to do about it? Well, I found easiest solution was to write a custom DataGridItemRender that overrides the super class' validateNow() method. The new validateNow() method looks like this:

override public function validateNow():void {
  super.validateNow();
  if (data && parent && !(data as DataGridColumn)) {
    var dg:DataGrid = DataGrid(listData.owner);
    if (dg.isItemHighlighted(listData.uid))
      textColor = getStyle("textRollOverColor");
    else if (dg.isItemSelected(listData.uid))
      textColor = getStyle("textSelectedColor");
    else textColor = getStyle("color");
  }
}

It's pretty straight-forward - based very closely on the DataGridItemRenderer's validateNow() method, but instead of setting the item's explicitColor property, it goes straight ahead and sets the underlying text field's color directly. You might also notice the reference to the textSelectedColor style - it turns out that one was also broken, but this override fixes it too.

Something you won't find in the DataGridItemRenderer's validateNow() method is the reference to the "data as DataGridColumn" clause at the end of the first if statement... I won't go into the details now, but this custom renderer won't help for DataGrid header items, and so that clause prevents this override from doing anything to header items. In short, validateNow() is almost never called for DataGrid header items, so they have to be treated specially.

Well, that's it for now... in my next post I will show how to fix the DataGrid header items (need a custom DataGrid control), and link to a demo app that you can test, and view the source of :)

Paul.

Labels:

Wednesday, 22 November 2006

In the beginning...

Hello! :)

This is just a quick test to see how it all works... I will post some real content soon.

Paul.