torstaina, helmikuuta 11, 2010
torstaina, marraskuuta 19, 2009
Programmers of popular programming languages
Hmm... as some of you probably know, I collect exotic programming languages. This quote made me think:
If you program in the most popular programming language, your skill in that particular language is a commodity. If you program only in the most popular programming language, you have made yourself a commodity. A commodity can only compete on location and price, and location doesn't really get you much on the Internet. This means that only people with a poor understanding of economics program in PHP.Lifted from http://gilesbowkett.blogspot.com/2009/01/why-hacker-news-thinks-php-won.html
What do you think?
sunnuntaina, lokakuuta 25, 2009
How american health care works
Check out this podcast on iTunes:
http://phobos.apple.com/WebObjects/MZStore.woa/wa/viewPodcast?id=201671138
http://phobos.apple.com/WebObjects/MZStore.woa/wa/viewPodcast?id=201671138
Thanks to Juha for recommending it to me.
maanantaina, elokuuta 31, 2009
Come again?
From HP's customer service web site:
Note: You must have administrative privileges on your Mac computer to install the software. Click System Preferences, Accounts, and check Allow user to administer this computer.Now let me get this straight: You should grant your account administrative access in order to install some software. But you need administrative access to grant administrative access, don't you, so why bother?
sunnuntaina, elokuuta 23, 2009
Learning XPath
Many of the Mac OS X command line utilities have a -plist option, which makes the utility do its thing in the "plist xml" format. I had the idea that maybe it would a good idea to use it and then use some of the xml tools to extract the information I want, instead of the usual pipeline of grep, awk and sed commands.
Specifically, I wanted to find out the mount point of a file system. I know the device file of the disk partition/slice.
I could try the mount command, but if the mount point directory has whitespace characters, parsing the output of the mount command is a bit fragile.
diskutil info is an OS X specific command that gives me what I want. After learning about XPath a bit, I came up with something like this:
diskutil info -plist /dev/disk0s2 | xpath "//string[preceding-sibling::key[1]='VolumeName']"
This is not yet perfect. The volume name is surrounded by <string> and </string> but I can live with that. The final insight for the XPath expression came from this post.
P.S. This post was written in Blogger's rich text editor in the Safari browser. This was the first time it worked well enough to be useful.
sunnuntaina, toukokuuta 03, 2009
The best programming language, part 3
I wrote some time ago about my search for the best programming language. Now I have discovered a new language that meets a lot of the demands: Clojure.
Clojure is very much like Lisp. It runs on a Java VM. Java VMs are stable and either already installed on many platforms or easily available. All the objects you can import into Java are available for calling from Clojure. The Clojure programs can be deployed as .jar files and no-one needs to know you actually produced it with a high-level functional language.
Clojure also has good support for multi-threading and it does it with a new and interesting way by implementing software-transactional-memory, which apparently makes thread programming easier than using locks.
It is licensed under the Eclipse license. IANAL but it looks to me like it would be possible to use it for commercial software development without any major problems.
I'm still reading the documentation and I haven't written anything more complicated than a hello-world with it, but I'm liking what I see so far.
Clojure is very much like Lisp. It runs on a Java VM. Java VMs are stable and either already installed on many platforms or easily available. All the objects you can import into Java are available for calling from Clojure. The Clojure programs can be deployed as .jar files and no-one needs to know you actually produced it with a high-level functional language.
Clojure also has good support for multi-threading and it does it with a new and interesting way by implementing software-transactional-memory, which apparently makes thread programming easier than using locks.
It is licensed under the Eclipse license. IANAL but it looks to me like it would be possible to use it for commercial software development without any major problems.
I'm still reading the documentation and I haven't written anything more complicated than a hello-world with it, but I'm liking what I see so far.
sunnuntaina, maaliskuuta 08, 2009
Parkkeeraus on taitolaji
maanantaina, helmikuuta 23, 2009
Simple = good
Modern day gadgets, devices and equipment mostly suck and have bad failure modes. Let's illustrate this with some examples:
I have a digital TV receiver, Handan CV-3300 CNX. The picture and sound works. Subtitles also work most of the time. A few times a week the device turns on but there is just a black, blank screen on the TV and no sound. A power-cycle makes it ok again.
Like all digital TV receivers, it includes a feature called EPG or electronic program guide. This is supposed to be a display of past, current and future programming of all TV channels. When I press the EPG button on my remote, I get this information for some channels but the rows for other channels are empty. Sometimes it helps if the receiver is on for a while. Sometimes those rows stay empty for hours.
This is probably a bug in the receiver's software and will go away when the manufacturer makes a firmware upgrade available. I have had the box from 2005 and it has never found an upgrade. I have also navigated the device's menus and found the command to search for upgrades. Nothing there either. There are no upgrades on the Internet either. In fact, the manufacturer's web site has no record of this device.
My friend has a stereo set with a turntable. When we were listening to his LP records, we discovered the turntable was broken: when the arm reached the end of the record, it did not automatically lift up and return itself to the rest next to the revolving plate. The mechanism is broken. But one can push a lever to lift the arm and then push the arm to the resting position with a fingertip.
This got me thinking: The turntable is broken, yes, but not badly. It still plays the records and the small problem it has is easily amended with just a little flick of a finger. And even if the turntable develops more serious issues, it will probably still be able to play the records but with a loss in sound quality. The worse the problem, the greater the impact on sound quality. But the problem will have to be very serious indeed to completely prevent enjoying recorded music. To make it short: it fails gracefully.
Another example: Last week I got a coffee grinder. Not an electric monster but an old-fashioned one with a crank on the top. I have never used a coffee grinder. In fact, I have only seen them in films. The grinder came with a small sheet of paper on which were some hard-to-understand instructions. I could not figure them out. But the device was so simple and made from just a couple of pieces of wood and metal held together with screws, so it was easy to take it apart and figure out how it works, which way to turn the crank and how to adjust the coarseness of the grind.
It is a beautiful piece of equipment that is simple, does only one thing, does it well and is easy to understand, operate and repair. It also fails gracefully. (The device did not fail at all, the manual did.) And let me tell you: If you like coffee, you should grind it yourself. There is a remarkable difference in the taste. I did not believe it until I tried.
I am beginning to like simple things which I can understand and fix. Maybe I am getting old. Maybe it is because all day long at work I have to build and fix complex things that can and will fail in a lot of different ways. And all of those failures are bad, or very bad.
Is it even possible to build software that fails gracefully? I don't think I have ever seen such a thing...
I have a digital TV receiver, Handan CV-3300 CNX. The picture and sound works. Subtitles also work most of the time. A few times a week the device turns on but there is just a black, blank screen on the TV and no sound. A power-cycle makes it ok again.
Like all digital TV receivers, it includes a feature called EPG or electronic program guide. This is supposed to be a display of past, current and future programming of all TV channels. When I press the EPG button on my remote, I get this information for some channels but the rows for other channels are empty. Sometimes it helps if the receiver is on for a while. Sometimes those rows stay empty for hours.
This is probably a bug in the receiver's software and will go away when the manufacturer makes a firmware upgrade available. I have had the box from 2005 and it has never found an upgrade. I have also navigated the device's menus and found the command to search for upgrades. Nothing there either. There are no upgrades on the Internet either. In fact, the manufacturer's web site has no record of this device.
My friend has a stereo set with a turntable. When we were listening to his LP records, we discovered the turntable was broken: when the arm reached the end of the record, it did not automatically lift up and return itself to the rest next to the revolving plate. The mechanism is broken. But one can push a lever to lift the arm and then push the arm to the resting position with a fingertip.
This got me thinking: The turntable is broken, yes, but not badly. It still plays the records and the small problem it has is easily amended with just a little flick of a finger. And even if the turntable develops more serious issues, it will probably still be able to play the records but with a loss in sound quality. The worse the problem, the greater the impact on sound quality. But the problem will have to be very serious indeed to completely prevent enjoying recorded music. To make it short: it fails gracefully.
Another example: Last week I got a coffee grinder. Not an electric monster but an old-fashioned one with a crank on the top. I have never used a coffee grinder. In fact, I have only seen them in films. The grinder came with a small sheet of paper on which were some hard-to-understand instructions. I could not figure them out. But the device was so simple and made from just a couple of pieces of wood and metal held together with screws, so it was easy to take it apart and figure out how it works, which way to turn the crank and how to adjust the coarseness of the grind.
It is a beautiful piece of equipment that is simple, does only one thing, does it well and is easy to understand, operate and repair. It also fails gracefully. (The device did not fail at all, the manual did.) And let me tell you: If you like coffee, you should grind it yourself. There is a remarkable difference in the taste. I did not believe it until I tried.
I am beginning to like simple things which I can understand and fix. Maybe I am getting old. Maybe it is because all day long at work I have to build and fix complex things that can and will fail in a lot of different ways. And all of those failures are bad, or very bad.
Is it even possible to build software that fails gracefully? I don't think I have ever seen such a thing...
Uusi ulkonäkö
Otin Bloggerin uudet ulkonäköasetukset käyttöön ja samalla muutin blogin pohjaa ja tein vähän muitakin pieniä muutoksia.
sunnuntaina, helmikuuta 15, 2009
Best game in a while
World of Goo is a great game! It is very easy to learn. You can play a quick game when you have the time and come back to it later. It is addictive and fun. No obvious bugs. It is cheap ($20) and carries no obnoxious DRM. It does not need a powerful computer but still has attractive graphics. It is available for Mac, Windows and Linux (and Wii.)
At the price point of 15 euros it is starting to become questionable if it is even worth the time and trouble to pirate this game. For me it was easy to decide to buy it.
Get the demo, play it, then buy the full version. Support the couple of guys behind this piece of pure genius!
At the price point of 15 euros it is starting to become questionable if it is even worth the time and trouble to pirate this game. For me it was easy to decide to buy it.
Get the demo, play it, then buy the full version. Support the couple of guys behind this piece of pure genius!
sunnuntaina, helmikuuta 01, 2009
Cheap music
I was shopping in Anttila yesterday. On my way out my eyes happened on a display of music cds with an attractive price: 1,00 euro. Most of the cds had classical music, but some was music for children.
Classical music at 1,00 euro / cd is much cheaper than in iTunes Store, so I picked up Tchaikovski's Symphony #5 Op. 64, Dvorak's Serenade for strings in E Op. 22 and a collection of Johan Strauss Jr.'s most popular works.
The cds have no real packaging to speak of. They reside in square cardboard envelope with a portrait of the composer on the cover.
Obviously the publisher of these cds understands that these days the packaging is no longer important to many music consumers. The physical disc is only the medium for transferring the music from the shop to the consumer's computer and mp3 player. After the transfer, the disc can be either discarded or (preferably) archived.
I commend the music industry for coming up with this idea for competing with iTunes: Make the music cheap enough by discarding unnecessary baggage and people might still buy the discs. At least I don't have to make a backup copy of this music. And it doesn't carry any form of obnoxious DRM.
[I know all iTunes music is DRM-free these days. Unfortunately I have 365 songs in my iTunes that have DRM. Well, I can only blame myself. Nobody forced me to buy from iTunes.]
Obviously the 1 EUR price point is possible only because the music on the disc is in public domain, but I suspect the big record companies could scale back their profit margins and make up the difference by increasing sales, just like Hollywood movie studios have done. One hardly needs to pay more than 6-8 EUR for a movie DVD, unless it is from Disney.
Classical music at 1,00 euro / cd is much cheaper than in iTunes Store, so I picked up Tchaikovski's Symphony #5 Op. 64, Dvorak's Serenade for strings in E Op. 22 and a collection of Johan Strauss Jr.'s most popular works.
The cds have no real packaging to speak of. They reside in square cardboard envelope with a portrait of the composer on the cover.
Obviously the publisher of these cds understands that these days the packaging is no longer important to many music consumers. The physical disc is only the medium for transferring the music from the shop to the consumer's computer and mp3 player. After the transfer, the disc can be either discarded or (preferably) archived.
I commend the music industry for coming up with this idea for competing with iTunes: Make the music cheap enough by discarding unnecessary baggage and people might still buy the discs. At least I don't have to make a backup copy of this music. And it doesn't carry any form of obnoxious DRM.
[I know all iTunes music is DRM-free these days. Unfortunately I have 365 songs in my iTunes that have DRM. Well, I can only blame myself. Nobody forced me to buy from iTunes.]
Obviously the 1 EUR price point is possible only because the music on the disc is in public domain, but I suspect the big record companies could scale back their profit margins and make up the difference by increasing sales, just like Hollywood movie studios have done. One hardly needs to pay more than 6-8 EUR for a movie DVD, unless it is from Disney.
sunnuntaina, tammikuuta 25, 2009
Why do I use Safari
During this weekend I have had a discussion on Twitter about Safari vs. Firefox. Well, in reality it hasn't been much of a discussion because it is hard to present a good argument in 140 characters. So I will elaborate here.
Why do I use Safari? Some people might have difficulty even understanding the question. 70% of Internet users surf with Internet Explorer. Many, if not most of them have never even heard of Firefox or Safari. But it so happens that I live in an environment filled with technically savvy nerds and literally everyone of my peers runs Firefox.
Except me.
Why?
I want to be different. For some reason I think there is something wrong with anything that is wildly popular. I hate crowded places. If everyone uses Firefox, I want to be different. I'm just wired that way. I also want to code in exotic, preferably dead languages: Forth, Lisp, Smalltalk, Erlang.
If I wanted to be like everyone else, I would run Firefox on Windows or Linux and code in C++ or Java.
I also have some practical reasons for preferring Safari:
Practical reason 1: Safari is smaller and starts up faster. This is important to me because my home computer is a 1st generation Mac mini, PowerPC CPU and 1 GB RAM. It normally has at least 3 users logged in, so memory is tight. I have developed a habit to quit the web browser when I'm done with the web pages or when I leave the Mac. If I were to run Firefox and keep it running, it would take ages to swap it in or out when switching users. If I always quit Firefox after viewing a web page, I will spend a lot of time waiting for Firefox to start.
This is much less of an issue on my work machine but I like to keep my work and home environment similar to minimize confusion.
Practical reason 2: Mac keyboard shortcuts conflict with Firefox Back- and Forward keys. Many are the web page forms where I have written a lot of text and hit cmd+left arrow to go to beginning of line. BOOM! Bad idea. Firefox immediately leaves the page and goes back in browser history. Never mind I had lots of unsaved text written on the page. Sometimes you can cmd+right arrow to go back and the text is still there. On some web services you get a blank page or an error. Safari is smart enough to interpret cmd+left arrow as beginning-of-line if the keyboard focus is in a text field.
Practical reason 3: I don't like tabbed browsing. Yes, I'm weird that way. Everyone of my peers has dozens of tabs in their Firefox. I don't understand how they manage. Tabs are essentially a two-way list. If you use the keyboard, you can only switch to the tab on the right or tab on the left. Those who remember the university Data structures and algorithms course will see this is the O(n) behavior. If you have a lot of tabs, you will spend a lot of time hitting ctrl+tab. The only random access available is to click on a tab with a mouse. But there's only about 8-9 tabs that fit in a Firefox window of reasonable width. The other tabs are hidden.
If you open new browser windows instead of tabs, you can use Expose (F10) to navigate them. Any browser window is within your reach with a couple of key presses or a flick of a mouse, especially if you set an active corner to invoke Expose.
Don't get me wrong, I do use tabs. I often open closely related web pages in tabs in the same browser window. So normally I have 4-5 browser windows and a couple of them have 3 or 4 tabs.
Now it is late. In the words of the immortal Forrest Gump: That is all I have to say about that.
Why do I use Safari? Some people might have difficulty even understanding the question. 70% of Internet users surf with Internet Explorer. Many, if not most of them have never even heard of Firefox or Safari. But it so happens that I live in an environment filled with technically savvy nerds and literally everyone of my peers runs Firefox.
Except me.
Why?
I want to be different. For some reason I think there is something wrong with anything that is wildly popular. I hate crowded places. If everyone uses Firefox, I want to be different. I'm just wired that way. I also want to code in exotic, preferably dead languages: Forth, Lisp, Smalltalk, Erlang.
If I wanted to be like everyone else, I would run Firefox on Windows or Linux and code in C++ or Java.
I also have some practical reasons for preferring Safari:
Practical reason 1: Safari is smaller and starts up faster. This is important to me because my home computer is a 1st generation Mac mini, PowerPC CPU and 1 GB RAM. It normally has at least 3 users logged in, so memory is tight. I have developed a habit to quit the web browser when I'm done with the web pages or when I leave the Mac. If I were to run Firefox and keep it running, it would take ages to swap it in or out when switching users. If I always quit Firefox after viewing a web page, I will spend a lot of time waiting for Firefox to start.
This is much less of an issue on my work machine but I like to keep my work and home environment similar to minimize confusion.
Practical reason 2: Mac keyboard shortcuts conflict with Firefox Back- and Forward keys. Many are the web page forms where I have written a lot of text and hit cmd+left arrow to go to beginning of line. BOOM! Bad idea. Firefox immediately leaves the page and goes back in browser history. Never mind I had lots of unsaved text written on the page. Sometimes you can cmd+right arrow to go back and the text is still there. On some web services you get a blank page or an error. Safari is smart enough to interpret cmd+left arrow as beginning-of-line if the keyboard focus is in a text field.
Practical reason 3: I don't like tabbed browsing. Yes, I'm weird that way. Everyone of my peers has dozens of tabs in their Firefox. I don't understand how they manage. Tabs are essentially a two-way list. If you use the keyboard, you can only switch to the tab on the right or tab on the left. Those who remember the university Data structures and algorithms course will see this is the O(n) behavior. If you have a lot of tabs, you will spend a lot of time hitting ctrl+tab. The only random access available is to click on a tab with a mouse. But there's only about 8-9 tabs that fit in a Firefox window of reasonable width. The other tabs are hidden.
If you open new browser windows instead of tabs, you can use Expose (F10) to navigate them. Any browser window is within your reach with a couple of key presses or a flick of a mouse, especially if you set an active corner to invoke Expose.
Don't get me wrong, I do use tabs. I often open closely related web pages in tabs in the same browser window. So normally I have 4-5 browser windows and a couple of them have 3 or 4 tabs.
Now it is late. In the words of the immortal Forrest Gump: That is all I have to say about that.
keskiviikkona, tammikuuta 07, 2009
perjantaina, tammikuuta 02, 2009
The best programming language
I have been doing most (well, pretty much all) of my professional programming in the C language. I'm beginning to really hate it. It is so difficult and error-prone to do string manipulation in C. It is easy to leak memory. There are no standard high-level data structures.
I have been looking for alternatives for a long time. The alternative should:
I have been looking for alternatives for a long time. The alternative should:
- have good libraries
- have good interface to libraries written in C
- have support for threads
- be small
- have good performance
- not have many dependencies to operating system libraries
- it should be possible to make closed-source programs with it
I have looked at Smalltalk, Erlang and Python.
Smalltalk has good libraries and the Smalltalk virtual machines tend to have very few outside dependencies. The Smalltalk I'm best familiar with, Squeak, has no support for threads and seems to interface somewhat badly to the outside world. I was especially disappointed by its support for running subprocesses and controlling them. Also, it is pretty much impossible to make closed-source software with Squeak. All the source is included in the image or can be reverse-engineered easily.
Erlang is an even more niche language than Smalltalk. There aren't many other people using it. Erlang is difficult to extend with libraries in C. Apparently not many C libraries can easily live with the extreme parallelism and thousands of light-weight processes a typical Erlang environment looks like. OTOH Erlang has good support for running subprocesses and communicating with them. Erlang sucks particularly bad in performance, unless your problem parallelizes to the extreme and you have the hardware to support it. For the more conventional cases Erlang is probably not a performance booster.
Python is sexy but slow. Python is also mostly single-threaded. It has threads but only one of them can execute in the interpreter at once.
Java is very un-sexy and also very slow. It has good thread support but it is a huge bloated monster.
All the languages above are very big. I call it very big if the customer has to install 30+ MB of language support/runtime/virtual machine to deploy a piece of software.
At the moment it looks to me like C++ or Objective-C would be the solution. Also there is this thing called Haskell, but I haven't looked into it sufficiently to have any idea how it stacks up with the contenders above.
tiistaina, joulukuuta 30, 2008
Should I stay or should I go?
Joel Spolsky and Jeff Atwood are a bit harsh. Essentially they say if you even think about leaving the software profession, you really should go, that even entertaining a thought like that is a sign of a bad programmer.
During the last couple of years I have been considering ways to become a professional horse trainer/stable-boy or something like that. Sorry, but I did not realize by doing that I was committing an act of treason against our beloved profession.
I never considered myself to be an excellent programmer but I never knew the bar was so high. Ok, maybe I'm not that great, but I haven't figured out a way to get someone to pay for playing with horses all day and well, I do like coding. So maybe I'll stick around a while longer.
But I do think people can be good at what they do but still get tired about it for a reason or another. And it is a very big world out there with a lot of things to do. It would be foolish to assume one can be happy only by programming computers. Yes, it pays well, like Joel says, but money is not equal to happiness. Happiness comes in many forms and can be found in many ways.
I am happy now. I hope you are too.
During the last couple of years I have been considering ways to become a professional horse trainer/stable-boy or something like that. Sorry, but I did not realize by doing that I was committing an act of treason against our beloved profession.
I never considered myself to be an excellent programmer but I never knew the bar was so high. Ok, maybe I'm not that great, but I haven't figured out a way to get someone to pay for playing with horses all day and well, I do like coding. So maybe I'll stick around a while longer.
But I do think people can be good at what they do but still get tired about it for a reason or another. And it is a very big world out there with a lot of things to do. It would be foolish to assume one can be happy only by programming computers. Yes, it pays well, like Joel says, but money is not equal to happiness. Happiness comes in many forms and can be found in many ways.
I am happy now. I hope you are too.
maanantaina, joulukuuta 29, 2008
Automating TVkaista with Automator
I have been a very satisfied user of TVkaista.fi, a tv-show recording service. I have been using it to download shows I missed for some reason and I have also used it to download tv shows to my iPod via its iTunes feed.
Only recently I realized I should perhaps automate downloading the shows I follow regularly and it was only then I discovered TVkaista has an RSS feed for each tv channel. Then it came to me that I could try to use Automator to automate the downloads. And it seems it has been a success.
There were a couple of issues.
First, I only wanted to download each show once, even if I accidentally invoked the download more than once. I solved this by subscribing the tv channel RSS feeds into Mail.app. Mail can keep track of the read/unread status of each feed article. Alternatively, each article can be flagged or unflagged. I chose to flag an article when it has been downloaded and only download unflagged shows.
Second issue was a bit strange. The Automator workflow I had made worked OK when I ran it from Automator. However, it did not download anything when I saved the workflow as an iCal plugin and had iCal invoke the download at certain times. There seems to be very little one can do to debug Automator. Eventually I realized the iCal plugin is actually an application bundle and when it wants to authenticate to TVkaista, Keychain does not allow it. After using Keychain to allow access to all programs for TVkaista authentication, my scheduled downloads work just fine.
You can check the Automator workflow I use to download Hill Street Blues. It looks like this:

If you are a TVkaista subscriber, you can try it too after subscribing to the YLE FST channel RSS feed in Mail. If you want to schedule the download, open the workflow in Automator, then from the File menu, Save as plugin, choose iCal plugin and give it a descriptive name. Then switch to iCal where you will find an event that is set to invoke an application. Change the event to run and repeat the way you like. The iCal plugins are actually app bundles saved into Library/Workflows/Application/iCal under your home directory.
Only recently I realized I should perhaps automate downloading the shows I follow regularly and it was only then I discovered TVkaista has an RSS feed for each tv channel. Then it came to me that I could try to use Automator to automate the downloads. And it seems it has been a success.
There were a couple of issues.
First, I only wanted to download each show once, even if I accidentally invoked the download more than once. I solved this by subscribing the tv channel RSS feeds into Mail.app. Mail can keep track of the read/unread status of each feed article. Alternatively, each article can be flagged or unflagged. I chose to flag an article when it has been downloaded and only download unflagged shows.
Second issue was a bit strange. The Automator workflow I had made worked OK when I ran it from Automator. However, it did not download anything when I saved the workflow as an iCal plugin and had iCal invoke the download at certain times. There seems to be very little one can do to debug Automator. Eventually I realized the iCal plugin is actually an application bundle and when it wants to authenticate to TVkaista, Keychain does not allow it. After using Keychain to allow access to all programs for TVkaista authentication, my scheduled downloads work just fine.
You can check the Automator workflow I use to download Hill Street Blues. It looks like this:

If you are a TVkaista subscriber, you can try it too after subscribing to the YLE FST channel RSS feed in Mail. If you want to schedule the download, open the workflow in Automator, then from the File menu, Save as plugin, choose iCal plugin and give it a descriptive name. Then switch to iCal where you will find an event that is set to invoke an application. Change the event to run and repeat the way you like. The iCal plugins are actually app bundles saved into Library/Workflows/Application/iCal under your home directory.
tiistaina, joulukuuta 02, 2008
torstaina, marraskuuta 13, 2008
Tilaa:
Blogitekstit (Atom)