what am I up to?

My wife is in hospital with an absess on her eye, so I’m stuck at home minding Jareth, my 3yo son.

I don’t have time to work on KFM at the moment, but work is progressing anyway – Benjamin Ter Kuile has been hacking away at it feverishly – he’s currently working on the Image code. We plan to have all thumbnails contained within the sqlite database for version 0.7. I received an Italian language file from Stefano Luchetta, which, together with Hannu Nemi’s Finnish translation, makes a total of ten languages!

I’m busy with a rather large project which I can’t reveal details about, but can say that it involves Perl and a few different DB versions. Perl is a bit of a bugger, after you’ve been used to PHP, and PostgreSQL is just a pain in the behind…

I translated my Kaejax framework from PHP into Perl last night, after much hardship, and am currently strugging with JavaScript – a previous developer on this project made a decision to use the Prototype JS library. That’s not a bad decision, but it is interfering with my own scripts such that some simple things are not working as expected.

All in all, I’m incredibly busy. Thank $DEITY monday is a bank holiday, as I think I’ll need it, in order to catch up with everything!

ie vs regexps as hash array indexes

Cryptic, right?

I have a small piece of javascript which looks a bit like this:

	var kaejax_replaces={'([89A-F][A-Z0-9])':'%u00$1','22':'"','2C':',','3A':':','5B':'[','5D':']','7B':'{','7D':'}'};
	if(!browser.isIE){
		for(var a in kaejax_replaces){
			kaejax_replaces[kaejax_replaces[a]]=eval('/%'+a+'/g');
			delete kaejax_replaces[a];
		}
	}

What that does is to build up an array (or Object, to be precise) called kaejax_replaces. A context for this is that you should escape() post_data before you send it via AJAX, but for some characters, the escape() is not necessary, so to save bandwidth (and thereby speed up the application), we convert those characters back by looping through the kaejax_replaces array before sending off the post_data:

function kfm_sanitise_ajax(d){
	var r=kaejax_replaces;
	for(var a in r)d=d.replace(r[a],a);
	return d;
}

In the above, d is the data to be sanitised of extraneous conversion.

Now, the problem arises that an object such as the following is actually illegal in IE (who knows why…):

	kaejax_replaces={
		/%([89A-F][A-Z0-9])/g:	'%u00$1',
		/%22/g:			'"',
		/%2C/g:			',',
		/%3A/g:			':',
		/%5B/g:			'[',
		/%5D/g:			']',
		/%7B/g:			'{',
		/%7D/g:			'}'
	};

Now, I /like/ that code. it’s short, neat, and does the job efficiently.

Unfortunately, IE is a bugger, so we need to do it the old primitive way…

	var kaejax_replaces_regexps=[],kaejax_replaces_replacements=[];
	for(var i in kaejax_replaces){
		kaejax_replaces_regexps.push(eval('/%'+i+'/g'));
		kaejax_replaces_replacements.push(kaejax_replaces[i]);
	}
	function kfm_sanitise_ajax(d){
		for(var a in window.kaejax_replaces_regexps)d=d.replace(kaejax_replaces_regexps[a],kaejax_replaces_replacements[a]);
		return d;
	}

That is all.

ps: IE sucks – the above article is also true of IE7

abominable

This article is full of spoilers.

The acting at the beginning was pretty terrible – I thought “good lord, this is living up to its name!”. Lance Henrikson made an appearance, and got chomped within minutes.

Basically, the film (imdb, amazon) is about a creature, supposedly an abominable snowman (although it’s brown, 3000 miles from the Himalayas, and in Sasquatch country) who kills ten or so people, all while watched by a guy in a wheelchair who is helpless to do anything about it.

The whole thing reminded me of Alfred Hitchcock’s Rear View Mirror (imdb, amazon), combined with the Twilight Zone, episode 123, Nightmare At 20,000 Feet (tv.com, amazon). You have a guy who’s confined to a wheelchair and sees a load of murders happening through his binoculars (RW), but every time he tries to get someone to believe that the monster is there, they either don’t believe him, or the creature has inexplicably vanished (TZ).

All in all, a disappointing monster flick. Don’t bother with it if you’re a serious horror fan. Instead, get the Hitchcock and Twilight Zone DVDs.

kfm 0.6 released

New Features

  • New Languages
    • Irish
    • Russian (thanks to Vse Do FeNi)
  • Syntax highlighting (thanks to Benjamin Ter Kuile)
  • Search Engine (11)
  • Ajax library totally rewritten to improve responsiveness (74)

Improvements

  • Drag&Drop directory moving (79)
  • Rename Directory (78)
  • Recursive deletion of directories (96)
  • Improve key navigation (up/down arrows, f2 key) (106, 40)
  • and others (94)

demo | website

pdo::sqlite gotcha

This one caught me a few days ago, but I didn’t have to time to concentrate on it (I was being harassed by screaming kids at the time). I came across the same problem today, and managed to figure it out with the help of some useful prompts from the ILUGgers.

The problem manifests as a query failing to run for no apparent reason.

An example of some code that exhibits the bug (taken from the KFM project:

function _moveDirectory($from,$to){
	global $db;
	$q=$db->query('select * from directories where id="'.$from.'"');
	$from=$q->fetch();
	$q=$db->query('select * from directories where id="'.$to.'"');
	$to=$q->fetch();
	if(strpos($to['physical_address'],$from['physical_address'])===0)return 'error: cannot move a directory into its own sub-directory'; # TODO: new string
	if(file_exists($to['physical_address'].'/'.$from['name']))return 'error: "'.$to['physical_address'].'/'.$from['name'].'" already exists'; # TODO: new string
	rename($from['physical_address'],$to['physical_address'].'/'.$from['name']);
	if(!file_exists($to['physical_address'].'/'.$from['name']))return 'error: could not move directory'; # TODO: new string
	$len=strlen(preg_replace('#/[^/]*$#','',$from['physical_address']));
	$fugly='update directories set physical_address=("'.addslashes($to['physical_address']).'"||substr(physical_address,'.($len+1).',length(physical_address)-'.($len).')) where physical_address like "'.addslashes($from['physical_address']).'/%" or id="'.$from['id'].'"';
	$db->exec($fugly) or die('error: '.print_r($db->errorInfo(),true));
	$db->exec('update directories set parent="'.$to['id'].'" where id="'.$from['id'].'"') or die('error: '.print_r($db->errorInfo(),true));
	return _loadDirectories(1);
}

The problem is that the SQL statement $fugly (so named because it’s fucking ugly) and the following one do not run, and return an error saying the database is locked. This is despite the fact that earlier in the same function, we’ve read from the database with no problems.

After much banging of heads, I found the problem – the variable $q holds a lock on the database, but it’s a read lock. In order to change to ‘write’ mode, you need to free up that variable before you attempt the write.

function _moveDirectory($from,$to){
	global $db;
	$q=$db->query('select * from directories where id="'.$from.'"');
	$from=$q->fetch();
	$q=$db->query('select * from directories where id="'.$to.'"');
	$to=$q->fetch();
	$q=null;
	if(strpos($to['physical_address'],$from['physical_address'])===0)return 'error: cannot move a directory into its own sub-directory'; # TODO: new string
	if(file_exists($to['physical_address'].'/'.$from['name']))return 'error: "'.$to['physical_address'].'/'.$from['name'].'" already exists'; # TODO: new string
	rename($from['physical_address'],$to['physical_address'].'/'.$from['name']);
	if(!file_exists($to['physical_address'].'/'.$from['name']))return 'error: could not move directory'; # TODO: new string
	$len=strlen(preg_replace('#/[^/]*$#','',$from['physical_address']));
	$fugly='update directories set physical_address=("'.addslashes($to['physical_address']).'"||substr(physical_address,'.($len+1).',length(physical_address)-'.($len).')) where physical_address like "'.addslashes($from['physical_address']).'/%" or id="'.$from['id'].'"';
	$db->exec($fugly) or die('error: '.print_r($db->errorInfo(),true));
	$db->exec('update directories set parent="'.$to['id'].'" where id="'.$from['id'].'"') or die('error: '.print_r($db->errorInfo(),true));
	return _loadDirectories(1);
}

The conclusion is that you can make a load of read requests in a row, or a load of write requests in a row, but if you are mixing the query types, you need to free the result each time.

almost a millionaire

Based on a small discussion in #linux.

  1. I have 0 money
  2. 0 == 000,000
  3. 000,000 is 6/7ths of 1,000,000
  4. 6/7ths of 1,000,000 is 857,142
  5. therefore, I am worth €857,142

I don’t think banks would honour that logic when applying for a loan, though

syntax highlighting in KFM

Benjamin Ter Kuile has been hacking away at KFM, and has integrated a syntax highlighter.

syntax highlighting screenshot

You can try it yourself: go to the dev site (Firefox only – I’ll fix IE support when it’s closer to release), upload a text file such as a .html, .js, etc, right-click on the icon and choose “view”.

daily wtf

I saw this snippet on the daily wtf:

if b = b then
  b = true
end if

…and thought – how would I write that in JavaScript, if I wanted to keep the spirit of the thing, and add a little more “wtf” to it. Here y’are:

b=b==b?b==b:b;

It has a strange symmetry, dont you think?

kfm acquires a search engine

Over the last few weeks, I’ve gradually been shifting the KFM project over to using sqlite for its file meta-data organisation, a database engine which keeps everything in one file and doesn’t require any pesky authentication.

The logical next step was a search engine, so I wrote that today – and wrote some workarounds for SQLite – my home version is 3.3, and work server runs 3.1.3. 3.1.3 doesn’t support auto_increment, which bloody annoyed me.

demo
kfm screenshot

At the bottom left, open up Search, and type “jpg”. No need to press “enter” – it’s a live search – it will ask for the results 500ms after your last keypress. You’ll get a result set of all files with “jpg” in the name.

That’s one of the major new things for KFM 0.6, which I hope to push out the door by next weekend.

Thanks to Benjamin ter Kuile for his help in getting the system to work on servers that don’t have PDO-SQLite built in – he supplied a different flat-file database. I haven’t seen it in action, but it works on his server (which is running MacOSX!)

Also, thanks to Vse Do Feni, who supplied a Russian translation! It looks strange to see KFM with Cyrrilic characters.

The next few weeks should be interesting. I’ll be implementing tagging very soon. KFM will be the most advanced ajax filemanager in existance!

number formatting in javascript

demo

The thing to note is that the answer shown on the right is formatted with two digits on the right of the decimal point, and commas every third digit on the left.

The code that does that:

formatNumber=function(v,f){
	v=parseFloat(v);
	var l=Math.floor(f),a=v,c='',r=0;
	v=v.toFixed?v.toFixed((f-l)*10):v;
	while(a>=1){
		++r;
		a/=10;
	}
	for(;l>r;++r)c+='0';
	r=/(\d+)(\d{3})/;
	while(r.test(v))v=v.replace(r,'$1,$2');
	return v+c;
}

In the function, v is the value to format, and f is floating point digits – eg: .2 (10.23, 76.35), .3 (1.234, 8.200).