newspaint

Documenting Problems That Were Difficult To Find The Answer To

Monthly Archives: October 2012

Have Desktop GUIs Matured?

After watching a review of Windows 8 – and thinking about my personal experiences with Windows 7, Vista, XP, NT 4.0, Windows 2000, and Windows 95 – it occurred to me that the desktop GUI has probably reached a point where radical changes are probably inappropriate for this day and age.

Unusual Aircraft Design

Unusual Aircraft Design

When you think about other products and their development – such as the car and aeroplane – you can see that the historical development included some wild and fanciful ideas – some horribly inefficient designs – but a lot of variety. There were biplanes and triplanes, 3-wheel vehicles, thin tyres and wide tyres. Nowadays cars are pretty much the same design – 4 wheels, very similar engine types, generally similar window layout, etc. Planes are very similar to each other, too.

Isn’t this the order of discoveries? Wild experimentation until a few essentially-agreed optimisations are made – and then the process becomes more an evolution than revolution – with refinements being made.

And this is a story of the evolution of the desktop user interface on computers, too, hasn’t it! Windows 3.1 (and the Windows before it) was something radical – multiple windows giving the illusion of being able to do several things at the same time on a single computer!

Remember Windows 95 and the endless repetition of “Start Me Up” (by the Rolling Stones) adverts? Yet Windows 95 was a leap forward in usability on the desktop. Having a start button was a great idea and emulated in other desktops (such as GNOME for Linux).

Windows NT 4.0 was an advance on Windows 95 with more process protection and serious API support. But in most ways very similar to Windows 95 in terms of user interface.

Windows XP seemed to be the pinnacle of Windows desktop design. It was the most functional Windows ever released.

Then came Windows Vista. I remember just wanting to scream and curse at my laptop computer that came bundled with Vista. So many things just “didn’t work” any more. It seemed that a generation of Microsoft developers had died out and a fresh wave of kids with no idea what advances had been made in desktop design had taken control. My pet hate was the User Access Control bringing up a modal window that was hidden – and I had to learn to alt-tab to find that modal window – before I could do anything else on the computer.

Windows 7 fixed a bunch of usability problems in Windows Vista. However what happened to the Start button? When you click on “All Programs” you no longer get a large window showing all your program folders! You just get a narrow short window with a scroll bar – requiring a bunch of extra clicks and gestures to get to that program you wanted. And there’s no option to restore that useful functionality that we came to expect in 3 generations of Microsoft desktop.

Windows 8 threatens to remove a lot of existing functionality in an effort to offer a vastly different user interface. But this is like throwing away everything we’ve learned about aircraft design in an effort to appeal to travellers. Why!?

We’re in a commercial age where no profit can come out of improving desktop design. Instead the only commercial option companies have is to throw out outlandish revolutionary ideas that discard the best of what we’ve come accustomed to. It’s wrong to imply that consumers who want the old are dinosaurs – far from it. They were often early adopters who went through the pain of the past to learn what worked and what didn’t. And now they are being forced into a radical experimental phase again?!

The solution must be something like XFCE for Linux. It is a stable desktop design. With multiple desktops! Even Windows 8 still cannot offer that.

Sure; the mobile and tablet space is new. Radical experimentation is required because we don’t yet know what really works and what doesn’t. Hence we have Android, Apple, and Microsoft Mobile Windows 8 all competing in that space. Which is necessary for this early stage of such a product’s life. Because we don’t know, yet, what will win out in terms of superior design. Unfortunately design and software patents threaten to permanently hobble the mobile space from ever achieving the best in ideas as commercial giants and greedy judiciaries squabble over who has the rights to what ideas.

But Microsoft: stop retarding Windows for the desktop. I know you’re desperate for piles of more cash. I know you’re desperate for a slice of lucky Apple’s pie. And by all means go seeking the stupid consumer that needs to be a slave to fashion. But appreciate and celebrate the stability of the Windows desktop. It’s a good thing that companies want to stay on Windows XP forever. Treating it as otherwise will set us all back until we learn to adopt Linux as our desktop.

Putty Can’t Connect To X11 Display Via Socks Proxy

I spent hours trying to figure out this problem. The short story is that version 0.60 and the latest release version (beta 0.62) of Putty on Windows 7 64-bit cannot forward X11 on a connection using a SOCKS proxy.

The fix is simple – download the latest development snapshot of Putty – which on build 2012-10-26:r9690 appeared to fix my issue.

Set-Up

I had a ssh tunnel to my target machine with a local SOCKS proxy – using ssh on a Linux server at home and with the -D command-line switch.

I was running Xming on my Windows 7 64-bit desktop.

I was using Putty version 0.60:

Putty About Screen for Version 0.60

Putty About Screen for Version 0.60

I set up a Putty connection to my target server via my SOCKS proxy port:

Putty Configuration Window for Using SOCKS Proxy

Putty Configuration Window for Using SOCKS Proxy

Then I configured my connection to use X11 forwarding (no need to fill out the DISPLAY variable part):

Putty Configuration for X11 Forwarding

Putty Configuration for X11 Forwarding

Now – if I had set my proxy up to use SOCKS5 then I’d get the following response after connecting to the server:

user@server:~$ echo $DISPLAY
localhost:13.0
user@server:~$ xhost
xhost:  unable to open display "localhost:13.0"
user@server:~$ xclock
Error: Can't open display: localhost:13.0

Strange – the DISPLAY environment variable was being set correctly but a display couldn’t be opened.

I tried changing my proxy type to SOCKS4. Then when I typed the command “xhost” I got the following crash:

Putty Crashing When X Command Sent Over SOCKS4 Proxy

Putty Crashing When X Command Sent Over SOCKS4 Proxy

Trying Using 0.62-beta

I tried using the latest release version (0.62-beta).

Putty About Box for Latest Release 0.62-Beta

Putty About Box for Latest Release 0.62-Beta

But this version also crashed using SOCKS4 proxy type.

Using Latest Development Snapshot of Putty

I downloaded the latest development snapshot of putty (which happened to be 2012-10-26:r9690 at the time):

Putty About Screen for Latest Development Snapshot

Putty About Screen for Latest Development Snapshot

Now when I logged into my server I got the following (and xclock worked):

user@server:~$ echo $DISPLAY
localhost:16.0
user@server:~$ xhost
access control enabled, only authorized clients can connect
INET:192.168.10.147    (no nameserver response within 5 seconds)
LOCAL:
INET:localhost

Great! It is working with Xming.

Post Script

There are a lot of articles on the Internet about how X11 forwarding won’t authenticate when using a different user to the one you first connect as (e.g. if you sudo to root after connecting). This was not my problem here. However I did initially get Putty authentication problems at first – which may or may not have been related to the SOCKS problems with the older Putty clients. The message was:

PuTTY X11 proxy: wrong authentication protocol attemptedPuTTY X11 proxy: wrong authentication protocol attemptedPuTTY X11 proxy: wrong authentication protocol attemptedPuTTY X11 proxy: wrong authentication protocol attemptedxhost: unable to open display “localhost:10.0”

… or in other words:

PuTTY X11 proxy: wrong authentication protocol attempted

Deleting the ~/.Xauthority file may be a very good start if you haven’t sudo’d into another user account.

USA And UK Keyboard Differences That Affect Perl Developers

Main Differences

Mistakes made by British and Irish using USA (ANSI layout) keyboards:

  • The UK # key is located where the USA [enter] key would be
  • The UK ~ key is located where the USA [enter] key would be
  • The UK @ key is located where the USA ” key would be
  • The UK ” key is located where the USA @ key would be
  • The UK \ key is located where the USA [left shift] key would be
  • The UK [enter] key extends over where the USA \ key would be

Mistakes made by Indians, Australians, Canadians, Hong Kong residents, New Zealanders, South Africans, Malaysians, Singaporians and Philippinos using UK (ISO layout) keyboards:

  • The USA # key is located where the UK £ key would be
  • The USA ~ key is located where the UK ¬ key would be
  • The USA @ key is located where the UK ” key would be
  • The USA ” key is located where the UK @ key would be
  • The USA \ key is located where the UK [enter] key would be
  • The USA left shift key extends over where the UK \ key would be
  • The USA [enter] key extends over where the UK # key would be

Why Is This A Big Deal?

For most modern-day computer users the special characters on the keyboard are not important. After all the numbers and letters are in the same place. But for programmers the differences are major because special characters are used frequently throughout programs – particularly in Perl.

In Perl:

  • The # symbol is used for commenting out all or part of a line
  • The ~ symbol is used in regular expression syntax, e.g. $text =~ m/\d+/
  • The @ symbol is used for naming arrays
  • The ” symbol is used for delimiting interpolated strings
  • The \ symbol is used for escaping characters and character classes in regular expressions

How Do I Get Java Working On Firefox 16 With Windows 7 64-Bit

This was driving me crazy. I upgraded to Firefox 16 (from 15) and all of a sudden Firefox wouldn’t run Java-based websites.

Mozilla explain that this is because the previous version of Java installed on my computer was deemed “insecure”.

So: here’s what to do.

STEP ONE

Make sure all browsers on your desktop are closed.

Download and install Java 32-bit (even if you’re on a 64-bit Windows 7 machine) from the manual download page on www.java.com.

STEP TWO

Start Firefox. Then select from the menu (you might have to press the Alt key to make the menu appear):

  Tools -> Add-Ons (also ctrl-shift-A will do the same thing)

Next find the Java plug-in (not the Java Deployment Tool which is completely unrelated) from the list of plug-ins. It might be at the bottom of the list.

Press the Enable button. Yes: you have to tell Firefox that you want to run Java again because it (unhelpfully) disabled the plug-in!

JavaScript Regular Expressions for Perl Developers

Too many of the regular expression tutorials for JavaScript focus on the basics of regular expression syntax – not how regular expressions can be actually used.

Test String For Match

Some basic examples:

if ( /abc/.test( "abcdefg" ) ) { console.log( "Match" ) } // MATCH
if ( /^abc/.test( "abcdefg" ) ) { console.log( "Match" ) } // MATCH
if ( /bcd/.test( "abcdefg" ) ) { console.log( "Match" ) } // MATCH
if ( /^bcd/.test( "abcdefg" ) ) { console.log( "Match" ) } // NO MATCH
if ( /^ABC/.test( "abcdefg" ) ) { console.log( "Match" ) } // NO MATCH
if ( /^ABC/i.test( "abcdefg" ) ) { console.log( "Match" ) } // MATCH

Some more examples:

var tests = [
  [ 'abc', '', 'abcdefg' ],
  [ '^abc', '', 'abcdefg' ],
  [ 'bcd', '', 'abcdefg' ],
  [ '^bcd', '', 'abcdefg' ],
  [ '^ABC', '', 'abcdefg' ],
  [ '^ABC', 'i', 'abcdefg' ]
];

for ( var i = 0; i < tests.length; i++ ) {
  var regString = tests[i][0];
  var regFlags = tests[i][1];
  var testString = tests[i][2];

  var regexp = new RegExp( regString, regFlags );
  if ( regexp.test( testString ) ) {
    console.log( '  \'' + testString + '\' =~ /' + regString + '/' + regFlags );
  } else {
    console.log( '  \'' + testString + '\' !~ /' + regString + '/' + regFlags );
  }
}

// OUTPUTS:
//  'abcdefg' =~ /abc/
//  'abcdefg' =~ /^abc/
//  'abcdefg' =~ /bcd/
//  'abcdefg' !~ /^bcd/
//  'abcdefg' !~ /^ABC/
//  'abcdefg' =~ /^ABC/i

Test And Capture

var result = /^(.+?)=(\S+)$/.exec( 'name=Jim' );
if ( result != null ) {
  console.log( '  key=' + result[1] + ', value=' + result[2] );
} else {
  console.log( 'NO MATCH' );
}

Global Search

In this example the regKeyPair variable is created with a global search and each “exec()” on this variable will return a subsequent match.

var regKeyPair = new RegExp( '(\\S+?)=(\\S+)', 'g' );
do {
  var result = regKeyPair.exec( 'name=Jim age=21' );
  if ( result != null ) {
    console.log( '  key=' + result[1] + ', value=' + result[2] );
  } else {
    console.log( 'NO MATCH' );
    break;
  }
} while ( 1 );

Note that matching over multiple lines requires the “m” flag. E.g.:

var multiLine = 'line1\nline2\nline3\n';
var getLine = new RegExp( '^(.+)$', 'mg' );

do {
  var result = getLine.exec( multiLine );
  if ( result == null )
    break;

  console.log( '  found line: "' + result[1] + '"' );
} while ( 1 );

Resetting the search can be done as follows:

var regGetLine = new RegExp( '^(.+)$', 'mg' );
// .. do multiple exec()s on regGetLine

regGetLine.lastIndex = 0; // similar to pos() function in Perl

// .. do another set of multiple exec()s on regGetLine

Simple Replace

Note that replace operates on a string – but it returns a new string with the replacements; the original string is never modified by the replace() call.

var source = 'abcdefg';
var replacement = source.replace(/abc/, 'ABC'); // 'ABCdefg'
var source = 'key=value';
var replacement = source.replace(/(.+?)=(.+)/, '$2=$1'); // 'value=key'

This next example demonstrates the use of a (synchronous) callback function that is passed the entire match and then the sub-matches as parameters.

function replaceFn( all, first, second ) {
  return( second.toUpperCase() + '=' + first.toUpperCase() );
}

var source = 'key=value';
var replacement = source.replace(/(.+?)=(.+)/, replaceFn); // 'VALUE=KEY'

Simple Global Replace

var source = 'key = value; key2 = value2';
var replacement = source.replace(/([^;=\s]+?)=([^;\s]+)/g, "$2=$1"); // 'VALUE=KEY'

Process a Buffer of Text One Line at a Time

function processLines( text, callback_fn ) {
  var regexpLine = new RegExp( "([^\r\n]+)[\r\n]+" );
  while ( 1 ) {
    var mymatch = regexpLine.exec( text );
    if ( mymatch == null )
      break;

    var start = mymatch.index;
    var end = start + mymatch[0].length;

    var line = mymatch[1];

    // remove the line and everything before it from the buffer
    text = text.substring( end );

    // process the line of text
    callback_fn( line );
  }

  // return the remaining text
  return( text );
}

This is useful when you are receiving chunks of text. The last part of the chunk may be half a line so you want to store that and add the next chunk to the unprocessed half-line next time. E.g.:

var buffer = "";
process.stdin.on('data', function (chunk) {
  buffer += chunk;
  buffer = processLines(
    buffer,
    function(line) { console.log( ' Line was "%s"', line ); }
  );
} );

Creating a Reverse Proxy For National Rail’s Mobile Website

The Nation Rail mobile website, http://m.nationalrail.co.uk/, thinks it is smarter than you. If you try and access this link from your desktop browser you will be redirected to the full website: http://www.nationalrail.co.uk/.

I wanted to create an iframe on a personal webpage so that I could keep up-to-date with the next departing train times. Let’s say you want to know what trains are departing London Waterloo and stopping at Surbiton. You could visit the full website live departures page (http://ojp.nationalrail.co.uk/service/ldbboard/dep/WAT/SUR/To) but the page has more than you might want in a smaller iframe. The mobile site view is what you’d prefer at http://m.nationalrail.co.uk/pj/ldbboard/dep/WAT/SUR/To using the following embedded code:

<style type="text/css">
iframe.infoframe {
  float: right;
}
</style>



<script type="text/javascript">
function updatetrainframe() {
  var myFrame = document.getElementById("idtrainframe");
  myFrame.src = "http://m.nationalrail.co.uk/pj/ldbboard/dep/PAD/RDG/To";
}

function startrepeat( callback, interval ) {
  callback();
  setInterval( callback, interval );
}

startrepeat( updatetrainframe, 1000 * 60 * 5 ); // update every 5 minutes starting now
</script>

Of course the problem is that the National Rail website hijacks your request to the mobile website and plonks you on the full desktop version of the website – which is not what you wanted (this is incredibly bad practice and somebody at National Rail should be fired for this: if someone goes to the effort to deliberately type “m.” instead of “www.” then it is clear they want the mobile version of the site).

Creating a Reverse Proxy Using Apache

Creating a reverse proxy is easy using the Apache web server. Create a new virtual site and add the following to the configuration:

ProxyPass / http://m.nationalrail.co.uk/
ProxyPassReverse / http://m.nationalrail.co.uk/
RequestHeader set User-Agent "Mozilla/5.0 (Linux; U; Android 2.2; nl-nl; Desire_A8181 Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1"

This will proxy-pass requests to your virtual site to the National Rail mobile website and substitute the user-agent for a mobile phone’s – fooling the National Rail website into serving the content you wanted all along.

Creating a Reverse Proxy Using Node.JS

Maybe you don’t have the convenience of running an Apache webserver – or perhaps you do but want to use a different method.

If you use node.js then the following script will proxy-pass requests to the National Rail mobile website:

var http = require('http');

var debugging = 0;

function deleteAnyCase( associativeArray, keyString ) {
    for ( var key in associativeArray ) {
        if ( key.toLowerCase() === keyString.toLowerCase() ) {
            delete associativeArray[ key ];
        }
    }
}

function httpUserRequest( userRequest, userResponse ) {
    if ( debugging )
        console.log( '  > request: ' + userRequest.url );

    // create options object required for proxy request we will make
    var options = {
        host: 'm.nationalrail.co.uk',
        port: 80,
    };
    options.path = userRequest.url;
    options.headers = userRequest.headers;
    options.method = userRequest.method;
    deleteAnyCase( options.headers, "user-agent" );

    // we must fool National Rail into thinking we are mobile device
    options.headers['user-agent'] = 'Mozilla/5.0 (Linux; U; Android 2.2; nl-nl; Desire_A8181 Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1'
    options.headers.host = options.host; // important: site name but no port
    delete options.headers.cookie; // stop National Rail tracking us

    if ( debugging )
        console.log( '  >   options = %j', options );

    // make request to national rail, and route data between user and target
    var proxyRequest = http.request(
        options,
        function (proxyResponse) {
            if ( debugging )
                console.log( '  < response' );

            if ( debugging )
                console.log( '      headers = %j', proxyResponse.headers );

            // protect again National Rail trying to redirect to new host
            var newHeaders = proxyResponse.headers;
            if ( "location" in newHeaders ) {
                newHeaders["location"] = newHeaders["location"].replace(
                    "http://m.nationalrail.co.uk", ""
                );
            }

            userResponse.writeHead(
                proxyResponse.statusCode,
                newHeaders
            );

            // route incoming data from National Rail to user response
            proxyResponse.on(
                'data',
                function (chunk) {
                    if ( debugging )
                        console.log( '  < response data' );

                    userResponse.write( chunk );
                }
            );

            proxyResponse.on(
                'end',
                function() {
                    if ( debugging )
                        console.log( '  < response end' );

                    userResponse.end();
                }
            );
        }
    );

    proxyRequest.on( 'error', function(error) {
        console.error( '  problem with request: ' + error.message );
    } );

    // route outgoing user request to National Rail
    userRequest.on( 'data', function(chunk) {
        if ( debugging )
            console.log( '  > request data' );

        proxyRequest.write( chunk );
    } );
    userRequest.on( 'end', function() {
        if ( debugging )
            console.log( '  > request end' );

        proxyRequest.end();
    } );
}

function main() {
    var port = 5555; // default port if none on command line

    // check for any command line arguments
    for ( var argn = 2; argn < process.argv.length; argn++ ) {
        if ( process.argv[argn] === '-p' ) {
            port = parseInt( process.argv[argn + 1] );
            argn++;
            continue;
        }

        if ( process.argv[argn] === '-d' ) {
            debugging = 1;
            continue;
        }
    }

    if ( debugging ) {
        console.log( 'server listening on port ' + port );
    }

    // start HTTP server with custom request handler callback function
    http.createServer( httpUserRequest ).listen(port);
}

main();

This script checks the command line for a port argument (and optionally a debugging flag) and will listen on that port and proxy any requests to the National Rail mobile website. By default it attaches to locahost:5555 – so you can run this script and fetch the departures from London Waterloo to Surbiton using the URL http://localhost:5555/pj/ldbboard/dep/WAT/SUR/To.