Archive for January 2007

Mutt and GNOME MIME types

A little while ago I wanted to launch an OGG file attached to an email. Since I read email in Mutt and it does such an excellent job of delegating unknown MIME types to external applications I simply pressed v (to see the attachments), selected the OGG attachment and pressed enter. Realplayer launched! Imagine my surprise.

After purging Realplayer from my system I had an idea. Mutt uses mailcap to determine how to deal with MIME types it can’t display, but since I’m using GNOME and it has a different system to deal with MIME types I frequently am surprised when viewing attachments in Mutt. Isn’t there some way of combining the two? Well, I frequently use gnome-open to launch viewers from the command line. But it forks off a new process for the viewer so it can’t be used in mailcapi. I spent some time looking into the inner workings of gnome-open and it might be possible to hack it to add a command line option to make it wait for the viewer to exit. However my quick test using Python suggests that it’d require changes in the underlying librariesii.

From what I learned looking through the implementation of gnome-open I hacked together the following short Python script:

#! /usr/bin/env python

import gnomevfs
import os
import sys

mime_type = gnomevfs.get_mime_type(sys.argv[1])
mime_app = gnomevfs.mime_get_default_application(mime_type)
application = os.popen(’whereis %s’ % mime_app[2]).readline().split(’ ‘)[1]

os.execl(application, application, sys.argv[1])

Then I added a line to the top of ~/.mailcap:

application/*; ${HOME}/bin/gnopen '%s'; test=test -n "$DISPLAY"

Works like a charm, but of course suggestions/improvement are welcome!

  1. It seems Mutt removes the temporary file as soon as the viewer returns, so if gnome-open forks and exits Mutt will delete the file before the actual viewer gets to load it. Bugger.[back]
  2. I traced it down to a call to g_spawn_async that should be changed to g_spawn_sync, but that’s deep down in the underbelly of GNOME-VFS.[back]

Epilicious 0.10.2

The only change is the addition of a translation to Esperanto (thanks Antono Vasiljev).

In related news, it seems like Fedore might be getting some Epilicious goodness coming its way. The packager also pointed out that the utility library (libepilicious) probably shouldn’t be installed in Epiphany’s extension library. Its location is now configurable at install time.

Playing unsafe haskell

Well, at first I thought I’d call this post “Doing Haskell without a condom” but decided it was probably best not to. :-) I can’t really take full credit for this post, I’ve stolen almost all of it from emails after I posted a question on haskell-cafe. All praise should go to the helpful people there!

What I wanted to do was model a finite stream of external events as a list and then map a function on that list. The processing of an event should happen as soon as an event is encoutered (one could say that the list of events should be lazy). Due to the wording “external events” the solution will have to be in the IO monad. It’s all a bit vague at this point, so let’s take it down to a more concrete level and then at the end make the solution more generic again. Let’s read characters until we read a q and print them.

First attempt, infinite list

Let’s start with an infinite list:

listChars :: [IO Char]
listChars = repeat getChars

Then I can map printChar like this:

mapM_ (\ x -> x >>= printChar) listChars

The result is almost what I want, each character is printed immediately. The only problem is that there is no end to the stream of characters. This means that the processing never terminates, that’s not a good thing.

Recursive (non-)solution

Solving the problem with the infinite list is easy if we do it recursively:

processChars :: IO ()
processChars = do
    c <- getChar
    printChar c
    if c == 'q'
        then return ()
        else processChars

This is easy to make more generic, but I expressively wanted to map a function on a list. So a recursive solution won’t cut it this time. However, the same pattern can be used to create a list inside the IO monad:

listChars :: IO [Char]
listChars = do
    c <- getChar
    if c == ‘q’
        then return [c]
        else liftM2 (:) (return c) listChars

Now mapping putChar on the result of this doesn’t quite produce the desired result.

listChar >>= mapM_ putChar

It doesn’t print characters as soon as they are entered. That is, it’s not lazy.

Adding laziness

Monads have an ordering effect on things. Since listChar executes in the IO monad, and the result then is passed to putChar, which also executes in the IO monad, we get a strict ordering between the two functions. What we need is to somehow interleave the IO in listChars with the IO in putChar. Put interleave into Hoogle and you’re pointed to unsafeInterleaveIO in System.IO.Unsafe. We can put it to use like this:

listChars :: IO [Char]
listChars = unsafeInterleaveIO $ do
    c <- getChar
    if c == ‘q’
        then return [c]
        else liftM2 (:) (return c) listChars

And now we get the required behaviour. Great!

IO inside on the haskell wiki has the following comment on unsafeInterleaveIO:

But there is an even stranger operation called ‘unsafeInterleaveIO’ that gets the “official baton”, makes its own pirate copy, and then runs an “illegal” relay-race in parallel with the main one! I can’t talk further about its behavior without causing grief and indignation, so it’s no surprise that this operation is widely used in countries that are hotbeds of software piracy such as Russia and China! ;) Don’t even ask me - I won’t say anything more about this dirty trick I use all the time ;)

So, I suppose it’s worth the effort to think through just how we put it to use here. Basically one can say that unsafeInterleaveIO creates a second IO monad, and in order to keep some level of determinism in the program the use of the new one should be kept separate from the use of the main IO monad, i.e. the one that main executes in. In this case the main IO monad is used to print characters to stdout while the one created by unsafeInterleaveIO reads characters from stdin. According to my limited understanding of IO in haskell this should mean we are safe, the two IO monads run no risk of ever “crossing”.

Another solution

Joachim Breitner suggested another, very cute solution based on cutting the infinite list short.

listChars =
    let
        sequence' (x:xs) = do
            r  <- x
            rs <- unsafeInterleaveIO (sequence' xs)
            return (r:rs)
    in do
        allChars <- sequence' $ repeat getChar
        let getChars = takeWhile (/= 'q') allChars
        return getChars

Generalisations

Recursive solution:

listIO :: IO [a] -> (a -> Bool) -> IO [a]
listIO getF testF = unsafeInterleaveIO $ do
    c <- getF
    if testF c
        then return [c]
        else liftM2 (:) (return c) listIO

listChars = listIO getChar (’q’ ==)

Joachim’s solution:

listIO :: IO [a] -> (a -> Bool) -> IO [a]
listIO getF testF=
    let
        sequence’ (x:xs) = do
            r  <- x
            rs <- unsafeInterleaveIO (sequence’ xs)
            return (r:rs)
    in do
        allChars <- sequence’ $ repeat getF
        let getA = takeWhile testF allChars
        return getA

listChars = listIO getChar (’q’ \=)

Could ListT be used in a solution?

This was one of my first thoughts. I mean what I want is the combination of two monads, List and IO. So, ListT IO Char should offer a solution right?

In theory it could! In practice it doesn’t! Apparantly ListT imposes unnecessary strictness. That means that it doesn’t offer a solution in this case.

Some of my thoughts on DRM…

An excellent paper on the cost of DRM in Windows Vista has been making its rounds on the internet for a few weeks now. The topic’s been picked up by Security Now (episode 73 and episode 74). The former gives a nice background to the technical side and the latter has Peter Gutman, the author of the paper, as a guest.

This has triggered my writing something about my thoughts on the topic of DRM. Now, I don’t consider myself an expert on this topic. I’ve formed most of my opinions on DRM by reading things like Cory Doctorow’s excellent talk at Microsoft Research and the Darknet paper from Microsoft. I’ve also worked for a large consumer electronics company for almost 5 years, of which the last 18 months to 2 years on security-related issues in consumer devices.

Why do the consumer electronics companies do DRM?

For the last 50 years consumers have bought new devices for the simple reason that the newer devices had more features, were faster, had better resolution, better audio… in short this year’s models were better than last year’s models. So, why on earth would these companies be interested in bringing out models that are fundamentally flawed through DRM? The easy answer is Hollywood… but as a professor of mine used to say, “Every difficult problem has an easy answer… which is wrong”. Hollywood isn’t the answer in my opinion. Hollywood is only a convenient scape goat. The real answer is format control.

A company that controls a format makes money even when a competitor sells a device. Just think of the patent Philips and Sony had on CDs. That patent pulled in money on every CD sold, worldwide. Talk about a gravy train. Nowadays content formats involve a lot of companies and I guess it’s less lucrative because license money will have to be shared between more companies (just think of the MPEG group). DRM is still a fairly new area of standardisation and there’s a good chance of cashing in even more than on the format itself, especially if DRM is written into lawi.

Consumer electronics companies and the broadcast flag

A while back the broadcast flag was beaten in the US. A court found that the FCC didn’t have the authority to introduce such a flag and the US was saved. At least for now. What wasn’t reported so widely on was the fact that when the broadcast flag was put on the table there was an outcry among the consumer electronics companies (a few other companies joined in as well). No, don’t be fooled, they weren’t considering the consumer, they weren’t interested in keeping TV the way it was. No, they were outraged because the suggested broadcast flag allowed only one DRM system. A system controlled by 5C (if I remember correctly). Companies not in the core group were facing extortionate licenses (basically giving up all IP to the core companies). No wonder they were outraged. Intense lobbying of the FCC followed and the outcome was that a set of DRM technologies would be “legal” in the US. That’s where the consumer electronics industry spent their time and money. They were fighting the possibility of 5C gaining a strangling grip in the market rather then stand up and try to do the right thing which would have been to work to make it possible to bring to market the best possible devices.

Consumer electronics companies and security

When working on security at the research branch of a consumer electronics company I quickly found myself “attached” to DRM-related projects. That was the only place where they were interested in security at all. Of course they weren’t interested in keeping consumers safe in a future where tellys have internet connections. No, the interest was solely in keeping customers out of the telly, preventing them to do interesting things with the boxes they bought. So, who paid for this sort of research project? The IP/standardisation department, that’s who. They practically poured money into DRM projects while the parts of the company that actually made devices showed little interest. (On a personaly note I have to admit that this aspect of security was one of the reasons why I left the company.)

End note

Well, I hope I’ve made some sense and that I’ve added something to the discussion about DRM that currently is taking place. Peter Gutman has done a great job in making people aware of it and I’m looking forward to see what happens once Vista really hits the homes. I’m of course hoping that there is broad disapproval and that Vista does appallingly based solely on its DRM.

  1. This brings me to a rather paranoid theory of mine, involving the “unholy trinity” of software patents, DMCA-like laws and DRM that can be used to explain some companies’ behaviour. That would probably have to be the topic of another post though.[back]

Dancing through airport security…

Brilliant clip from Family Guy:

Thought on Alingsås’ future…

Over Christmas I’ve talked quite a bit with my Dad about the local politics in Alingsås. One thing that kept comming up was the strange way that local politicians look at the town. In response to Allum in Partille (a new, very boring shopping centre) they are constructing a new indoor shopping centre at Kvarteret Storken. Unfortunately they are likely to only try to attract the regular, boring hig-street crowd of stores, i.e. the exact same stores that can be found in Allum. I can’t see how that ever will attract someone to drive to Alingsås for some Saturday shopping. You can get all that, and a lot more by going to Gothenburg.

Partille had basically nothing in way of stores before Allum, so there it was actually an improvement. In Alingsås it’s likely to decrease the small-town feeling and hence drive away people rather than attract. Why don’t they instead do something different, something that truly sets Alingsås apart?

Currently Alingsås is a small town, with cobblestone streets in the centre and award winning preservation of old wooden buildings. There is really only one shopping street, but it’s full of small stores with character rather then the impersonal chains you find typically find. This should be extended and pushed further. I don’t mind the idea of an indoor shopping centre, but don’t give up the space to boring chains. No, make sure there is room for smaller intriguing stores. Stores you won’t find in other places. I.e. the kind of stores that people would love to travel to for shopping. Add the numerous cafes that already exist and I think you have a unique and winning combination.

Of course it would also be necessary to make it easy to open a store in Alingsås, how else would there be the kind of experimentation that is necessary to make this happen? Of course it’s most likely that the local politicians will squander yet another opportunity to put in some effort and be rewarded thousandfold and instead make sure that Alingsås ends up being yet another run-of-the-mill medium-sized Swedish town. It would be such a shame!

Misc thoughts

During the trip to Sweden I’ve had a few thoughts I thought I’d “put out there”.

The Americans really ought to raise a statue honoring Hitler. Yes, I’m (almost) serious. I don’t think USA would be as strong as it is today if it weren’t for the brain drain from Europe to America that Hitler caused. I also can’t help thinking that it’s a shame they didn’t go to Canada instead…

Haskell is a great language, the only bad thing about it is it’s strength. Recently I came across some code using HXT. Haskell allows creation of something that can almost be called mini-languages due to it allowing the programmer to create new in-fix functions. This means that in many cases Haskell forces me to read documentation on a library/toolkit before being able to even guess at the meaning of some functions. I like it and get frustrated by it at the same time :)

Way back in the day many countries found it necessary to separate the church and the state. Maybe we’re ready to separate the “market” and the state now? I get something dreamy in my eyes when thinking of a future where politicians don’t govern based on their own, often short-term, financial gain.

Alingsås in the winter…

Well, we’re back in rainy, dreary Cambridge after a week and a half in rainy, dreary Alingsås. But hey! It was Christmas and we got to spend it with family. The weather really isn’t that important then. Though it would have been nice with snow on the 23rd when we went to Liseberg to see the lights. Also I wouldn’t have minded a dry New Years Eve, walking from the restaurant to the car is so much better than sprinting through heavy rain.

The trip was great. Thea was in great shape and it was good I had been keeping up with the gym during the autumn. Novah was adorable, just as the last time. My sister was tired, but who can blame her? Her partner seemed to attract bugs like crazy. My brother and his partner were great as always. Both sets of parents were going strong. We even got to see my aunt and uncle, my cousins and their kids. Great! What more can one desire for the holidays? Not much, I tell you!

Bye, bye, wallet!

After an hour in a class at the gym I came back to the locker to find the lock gone and my trousers and jacket missing. After a little while my brain wrapped itself around the situation and I stuffed what was left in the locker in my bag and went out to ask in reception if anyone had handed in my missing garments. No such luck, but one of the “gym people” went back with me to the locker room to inspect the locker. After a quick look around we opened a few unlocked ones and promptly found both my trousers and my jacket. The only thing missing was my wallet. The thief hadn’t taken my car keys, my house keys, my MP3 player, or my wedding ring. All of which were in my trousers. Apparently he (no stereo-typing here, it was a men’s locker room) was satisfied with my wallet, which contained exactly £0, a single debit card, a driving license, a few store cards, a gym membership card, and a few other bits and bobs of only emotional value (e.g. an adorable picture of my wife when she was a kid).

It’s all been reported to the police, despite the obvious lack of value of what was stolen. The bank has blocked the card and they told me of a failed attempt to use it about 20 minutes before I noticed the theft. Now all I have to do is go through the tedious procedure of replacing the stuff and fill a new wallet. Oh, I also need to buy a new wallet. Given that I’ve been semi-looking for a wallet for the last 6 months but haven’t found one to my liking I might have to lower my standards and buy one that doesn’t meet my exacting standards. Well, well… poor me!

It seems I was lucky, another poor bloke lost house keys, car keys (including the car it turned out), and a wallet with considerably more valuable stuff than I keep in mine.

Come to think of it I might also buy a more serious lock than the one sold by the gym, they do look a little weak. I hope this isn’t a new trend, I really like that gym and it’s not practical to carry valuables with you into the sauna…