10 Things I hate about the iPhone

I have had an iPhone 3G for a while now and it is a pretty nice and fun gadget. Its not as serious as a crackberry, but it does most things I want and there are many interesting apps available for it. Believe it or not, you can even use it as a phone.

There are however, many things about the iPhone that annoy me a lot. Most of them are related to the stupid artificial limitations enforced by Apple, or limitations of their software.

  1. It vibrates when new mail is received, which is pretty normal. But it also does this while you are on a call, not a pleasant feeling.
  2. It has no scheduling for email. Apple likes to say the iPhone is ready for enterprise use, but it misses a lot of the most basic features. As someone who is on-call a lot, my phone needs to be on at night, but I don't want to be woken every time I get an email. They could even save a lot of battery power and roaming costs this way.
  3. The iPhone supports 3G but unlike other phones, no tethering. I want to be able to connect it to my laptop when i'm on the road. It is technically possible, apple just doesn't allow it.
  4. Applications aren't allowed to run in the background. The phone has such huge potential - but this silly rule limits the usefulness of many applications a lot.
  5. The keyboard is difficult to use. In some places you can turn the phone to get a larger keyboard, in others you can't. The dictionary is worthless. In true American style, they completely forgot about countries where people speak multiple languages.
  6. No search functionality. Ever tried looking for an email if you get a hundreds a day? Surprising, for the people who created spotlight.
  7. The touchscreen sometimes registers clicks twice. I kept losing emails until I eventually figured out this was because the last character of my PIN was in the exact same place as the delete button. When I unlocked the phone, it would simply delete the message I had open at the time.
  8. You can't use it as an USB storage device. So you have a phone with multiple GB of storage, that connects to your computer via an USB cable. Then why can't it be used to store files on?
  9. No indication of missed calls. On most phones there is a little led that lights up when you have a missed call, or the screen backlight lights up a little.
  10. Battery life of course. With all functionality enabled, iPhones are usually found in their natural habitat, connected to the USB port of a computer.

Of course I could jailbreak the device to get around many of these limitations, but as I don't really own the device, that is not an option.

All in all, I still like the iPhone, but it is far from perfect. What I dislike most, is the company behind it. Apple fanboys like bashing Windows users, while – as an owner of several Apple products – I believe that Apple is a lot worse than Microsoft. They simply hide it behind a pretty design.

Blog Category:

Spam comments left by humans

In the past few months, Mollom has done a very good job blocking spam on my site. Its accuracy has increased a lot since I first installed it, nearly no spam gets through even though there are hundreds attempts a day.

However, I've been seeing a different kind of spam that does get through. Comments that are left by humans, who can solve the captcha shown by Mollom. These comments are usually on-topic and at first glance appear to be legit, except that the homepage URL of the author links to a spam site. I enabled nofollow a long time ago, but that doesn't appear to make much of a difference anymore.

I've even seen comments that had no link in them at all. I'm not sure what the purpose of those messages is. Maybe they are just checking whether someone removes these comments, or maybe they are trying to confuse Bayesian filters. Either way they are pretty annoying.

I could enable comment moderation on this site, but that would make me the bottleneck as I don't check the queue that often. I noticed that nearly all of these comments show up on a limited number of pages. So I wrote a simple little module that allows me to enable comment moderation for individual nodes and enabled this on the pages that are targeted by these spammers.
This has been running for about a week now and has blocked all such messages. There have even been less attempts, possibly because of the warning message that appears in the comment form. Lets hope it stays this way so I can remove the nofollow tags on links.

Modifying the vmware BIOS

For a little project that I was working on, I needed to modify the vmware BIOS slightly. After reading VMware BIOS modification - for Linux users, this turned out to be easier than I thought.

Step 1: Get the BIOS

  1. $ objcopy /usr/lib/vmware/bin/vmware-vmx -O binary -j .bios440 --set-section-flags .bios440=a bios440.rom.Z
  2. $ perl -e 'use Compress::Zlib; my $v; read STDIN, $v, 211638; $v = uncompress($v); print $v;' < bios440.rom.Z > bios440.rom

The value "211638" in this last line is the size of bios440.rom.Z.

Step 2: Modify the BIOS

This is a bit more difficult. I have been told the Phoenix BIOS Editor is pretty expensive. Luckily I knew someone who could make the changes for me.

Step 3: Use the new BIOS

After you changed the BIOS to suit your needs, all that is left to do, is edit your virtual machines .vmx file and append one line:

  1. bios440.filename = "path to your BIOS file"

Blog Category:

Using the varnish HTTP accelerator - Experiences so far

A couple weeks ago, I started experimenting with varnish as a reverse proxy server. My setup has changed a lot since then, I like to think it improved. So here are my experiences so far.

Use -trunk (or version 2.0), not the 1.1.2 release

Initially I was using the 1.1.2 release, but I ran into a couple problems. The worst one was the white screen of death for users behind a proxy server, such as squid. There was a problem with the way HTTP/1.0 requests were handled, resulting in blank pages being sent to the client.
The solution was to upgrade to -trunk, it contains several bug fixes and interesting new features and is pretty stable (at least at the moment). I usually don't like using the development version, but at the moment it seems to be the most reliable, and was also recommended by several people.
Version 2.0 will be released soon, use that one when its available.

One thing to keep in mind though is that there is a problem with subroutines. This bug has been reported, so for now I'd recommend not to use them.

Don't duplicate the default VCL functions

In VCL you can have multiple functions with the same name, they will simply be concatenated. This means that you don't have to duplicate the entire default functions if you just want to add a single line. This can simplify your VCL code a lot, and you still benefit from improvements made in the default functions.
For an example, see my new VCL below. I'm using this in all functions except for vcl_recv.

Again, for future reference, a copy of my new VCL code can be found below. As you can see, it has some new "features" but is simpler than the previous one. Note that the backend syntax has changed a little in trunk.

  1. # This is the vcl.conf file for andromeda.motd.be
  3. backend default {
  4. .host = "";
  5. .port = "80";
  6. }
  8. #
  9. # handling of request that are received from clients.
  10. # decide whether or not to lookup data in the cache first.
  11. # if we have multiple backends, we could specify them here but for now there is just the default
  12. #
  13. sub vcl_recv {
  14. # If the client sent an X-Forwarded-For header, remove it. It cannot be trusted.
  15. unset req.http.X-Forwarded-For;
  16. # Note that we don't need to add the client ip to the X-Forwarded-For header, varnish will do that for us
  18. if (req.http.Accept-Encoding) {
  19. # Handle compression correctly. Varnish treats headers literally, not
  20. # semantically. So it is very well possible that there are cache misses
  21. # because the headers sent by different browsers aren't the same.
  22. # @see: http:// varnish.projects.linpro.no/wiki/FAQ/Compression
  23. if (req.http.Accept-Encoding ~ "gzip") {
  24. # if the browser supports it, we'll use gzip
  25. set req.http.Accept-Encoding = "gzip";
  26. } elsif (req.http.Accept-Encoding ~ "deflate") {
  27. # next, try deflate if it is supported
  28. set req.http.Accept-Encoding = "deflate";
  29. } else {
  30. # unknown algorithm. Probably junk, remove it
  31. unset req.http.Accept-Encoding;
  32. }
  33. }
  35. # If we get a request for a page that has just been requested by another thread and
  36. # is still being fetched from the backend, allow serving a cached page so long as it hasn't
  37. # expired more than 30 seconds ago (prevents thread pileup on cache refreshes).
  38. # Note that this only works if obj.grace is also set:
  39. # "If no in-ttl object was found AND we have a graced object AND it is also
  40. # graced by req.grace AND it is being fetched: serve the graced object."
  41. set req.grace = 30s;
  43. # the default vcl_recv will only look up objects in the cache if there is no cookie
  44. # present in the request. Therefor, we remove the cookie header from all requests for
  45. # files which we know to be static.
  46. #
  47. # These are drupal-specific:
  48. # - everything in most of the standard drupal directories.
  49. # - txt and ico files (most important: robots.txt and favicon.ico)
  50. if (req.url ~ "^/(files|misc|sites|themes|modules)/" || req.url ~ "\.(txt|ico)$") {
  51. unset req.http.Cookie;
  52. }
  54. # No final action. Continues in the default vcl_recv which will only look up
  55. # items from the cache for GET and HEAD requests without cookies.
  56. }
  58. #
  59. # Called when entering pipe mode
  60. #
  61. sub vcl_pipe {
  62. # If we don't set the Connection: close header, any following
  63. # requests from the client will also be piped through and
  64. # left untouched by varnish. We don't want that.
  65. set req.http.connection = "close";
  67. # Note: no "pipe" action here - we'll fall back to the default
  68. # pipe method so that when any changes are made there, we
  69. # still inherit them.
  70. }
  72. #
  73. # Called when the requested object has been retrieved from the
  74. # backend, or the request to the backend has failed
  75. #
  76. sub vcl_fetch {
  77. if (obj.http.Pragma ~ "no-cache" || obj.http.Cache-Control ~ "(no-cache|no-store|private)") {
  78. # varnish by default ignores Pragma and Cache-Control headers. It
  79. # only looks at the "max-age=" value in the Cache-Control header to
  80. # determine the TTL. So we need this rule so that the cache respects
  81. # the wishes of the backend application.
  82. pass;
  83. }
  85. if (obj.ttl < 180s) {
  86. # force minimum ttl of 3 minutes for all cached objects.
  87. set obj.ttl = 180s;
  88. }
  90. # set the grace period for this object to a maximum of 30s. This is how
  91. # long after its expire time, it is still allowed to be served from cache if
  92. # directed to do so by vcl_recv.
  93. set obj.grace = 30s;
  95. if (req.http.Authorization && !obj.http.Cache-Control ~ "public") {
  96. # don't allow caching pages that are protected by basic authentication
  97. # unless when they explicitly set the cache-control to public.
  98. pass;
  99. }
  101. # Note: no final action - continue in the default vcl_fetch
  102. }


Subscribe to Bart Jansens RSS Subscribe to Bart Jansens - All comments