geansai gorm

Archive for the 'programming' Category

I received an email this morning saying that KFM has a security hole - if a user creates a file named “test.php.” (note the ‘.’ at the end), then it is run as if it was “test.php”, even if you explicitly banned the .php extension in your settings.

I immediately added a line of code to ban all filenames which end in ‘.’, released a new version of 1.3 (available on the front page of the site) and corrected 1.4 in SVN.

After thinking about it, I realised that the security problem is not as serious as it may seem (for KFM - not in general). It’s definitely a problem, but in order to use it, you need to have access to a KFM instance in the first place. As securing KFM is not difficult, I think the problem may be contained.

But I digress - this appears to be a problem in Apache. To test it, I checked if renaming a Perl CGI file from .cgi to .cgi. would work, and it did.

This is a little disturbing, as it does not appear to be documented anywhere, so there is no way that a developer would know to avoid this security hole.

So, if you write programs that allow your users to upload or rename files online, make sure that the filename does not have a ‘.’ at the end!

edit: OMG! I was reading the Apache source to try spot the problem, and found the area where it happens - it’s in the file “http/mod_mime.c”. The function “find_ct()” extracts the extension for the server to use. Unfortunately, it ignores all extensions it does not understand, so it’s not just a case of “test.php.” being parsed as ‘.php’, but also “test.php.fdabsfgdsahfj” and other similar rubbish files! This is a serious problem.

There are a number of solutions to this:

  1. Possibly the correct solution: Keep your downloadables outside the web-accessible area and force the download through a PHP script. Doesn’t matter what extension the file has then.
  2. Tricky but easier to make portable: Write your own extension identifier using the httpd source as a guide, so you know what Apache will identify the file as (annoyingly complex, possibly, but I’ll need to do it…)
  3. Easiest, but most annoying for users: Only allow one ‘.’ per filename.
  4. More difficult, but possibly also correct: Convince Apache that this needs to be fixed, then upgrade immediately when the fix is available.

further update: An easy solution. This problem rears its head when PHP is identified in your httpd.conf using this:

AddHandler php5-script .php

the solution is to change the above to specify the extension must be at the end.

<FilesMatch \.php$>
  SetHandler php5-script
</FilesMatch>

Didn’t do much on KFM this week. I’ve spent most of the time in work, sleeping, or trying to convince the kids that 3am is not a good time to be awake.

This morning (got up at 3.30…) I implemented lazy-loading for icon thumbnails.

What this means, is that in a folder which has 500 icons in it, if only 25 are visible without scrolling, then only 25 are actually downloaded. This helps speed up your usage in a few ways.

  • if you download an icon which is not immediately visible, then you are slowing down the showing of an icon which is right in front of you.
  • Sometimes you only want to see the first few icons of a directory anyway - let’s say they’re photos and the folder title is something like “DCIM1010″ (you know what I mean), then its easy to see if they’re the right photos by viewing the first few.
  • If you’re downloading 500 icons at one time, that means not many other HTTP actions can be taken until those have been taken care of… - so if you wanted to rename one of the visible files, for example, then you’ll just have to wait for the other hundreds of thumbs do download first!

What I’m supposed to be working on is the new translation system, but that’s very hard. There are some little problems I haven’t cleared in my head yet. Hopefully the solution will come to me before the end of the day so I can get it finished this weekend.

After a long break, I’m back working on KFM. I’ve done an average of maybe 2 hours every day this week, cleaning up code and preparing for future plans.

What I’m working on at the moment is a rewrite of the translations code. There are a few things wrong with the way that it works at the moment:

  • JavaScript and PHP language strings are currently separate - en.php and en.js for example.
  • Whenever KFM is loaded, the entire JS language file is loaded, even if very little of it will actually be used.
  • There is no easy way apart from hacking KFM to add translations for user-contributed plugins.

The solution we (Benjamin and myself) have come up with is to use a database solution, with an import facility for plugins. The idea is a complete rewrite of how we do it.

Currently, translations are recorded in a JS object something like this:

kfm.lang={
  Errors                  : "Ошибки",
  LastModified            : "последний раз изменен"
};

The above is easy to use in KFM, in that the strings can be accessed using normal object notation, kfm.lang.Errors for example. However, it should be easier.

What we will be doing is to convert all language files so they are written using the English string as the key instead of a code such as “LastModified“. And, using the common nomenclature of other languages, the translation will be done such as: alert(__("What do you want to rename %1 to?","default",filename));, where the second parameter is the language context (are we talking about files, people, dogs, etc?).

To help improve the speed at which KFM opens, only the most popular strings will be preloaded. If an unknown string is requested, it will be loaded through AJAX.

How that will work is that all translations will be asynchronous. When you request a translation, a span element will be returned containing the translation. If the translation is already known or cached by the client, then the element will be pre-filled. Otherwise, an AJAX request will be fired off, and when it returns, the element will be populated.

The popularity of the strings will be determined by the number of requests for it.

On the server side, when a request comes in, KFM will search its database looking for the string. If it is found, it is returned (and its ‘requests’ field incremented). If it is not found, then all installed plugins will be searched for language files, which will be imported into the database then returned. If the string is not found anywhere, then the plain English is recorded in the database, and a note is added that the translation was not found.

I’m considering whether or not to add in a bit which periodically reports back to the main KFM server a list of missing translations. Also, a periodic report of popular strings and even of unused strings, allowing us to prune the files for future releases.

If you want to try out the work, then download a copy of the trunk via SVN: svn checkout http://kfm.googlecode.com/svn/trunk/trunk/ kfm

I don't have a geansai gorm, but if I did, I might sometimes wear it.