For one of my customers, I’m developing a private web application that would probably make most Free Software enthusiasts – not just the advocates – cringe. It is developed in ASP.NET, with a SQLServer backend, and is targeted at iPad users. While in general this looks like a bad combination for a Free Software developer, paid work is paid work, and even working on Windows has its upsides, namely learning about alternative approaches and the good and bad things about them, to make your software better — to be honest I’m not sure I dislike ASP.NET more than I disliked Hobo (the Rails plugin) last year.
Putting the iPad to good use is also easy: I’m reading even those O’Reilly books that were previously cumbersome to read, PDFs like CJKV Information Processing which I bought last year and never went around to read, because of not being available in ePub format.
Let me say that, as a toy, the iPad is far from bad: Apple’s hands-on approach can be criticized, but the results for a naïve, jaded user are almost near perfection. On the other hand, I don’t think I’d trade my Milestone for an iPhone any time soon, even with all its troubles — the most bothersome issue is due to my CyanogenMod installation where the “hold call” button is pressed by my cheek while talking; it seems like I’m not alone and I’m now trying the method reported there to see if it helps.
While they really seem to have an app for everything, and their not-really-multitasking approach appears to work better than what I’m used to on Android, it is rough on the edges for the meddlers: I can’t install additional certificates (I can on Android); I can’t use an email address different than the GMail login (I can on Android); it doesn’t sync contacts on Google Contacts on the fly (Android does), and so on a few more “minor” things that I just love, in my Android.
But there is also one thing that the iPad can do and my Android can’t: printing. Of course it should be easy to do, especially given that Linux’s printing system is the same CUPS used by Apple – and actually, developed, given they bought the original developers! – but that’s not really the way they decided to do it. In a very environment unfriendly way, Apple decided that you can’t just use any printer with their iPad, you need to buy a new one, as they will not provide the AirPrint interface with older models.
You can guess that people already found out how to avoid that. I had saved a long time ago a post by Eric Sandeen on the topic, which later points to a GitHub project with a script that generates a service file for Avahi, which can then be used to advertise the printer properly.
But even with this it is far from being straightforward to deal with it. First problem I found is that the script needs the cups Python extension; this is not provided by
net-print/cups[python] as I first expected – I since updated the USE flags’ description in the
metadata.xml file: the interpreter flags are used for cups’s own CGI scripting support, which is definitely non-obvious – but rather by the
The next problem is that, because of technical limitations on the size of TXT records used in mDNS discovery – if you didn’t look up post and projects I have listed above, the AirPrint protocol is actually just the usual IPP as provided by cups, wrapped through mDNS with a custom record for exposing the printer’s features – some of the printer’s options are not exposed. One of those that is ignored is duplexing, but since my only real reason to print from the iPad is printing invoices, which I always print duplex – don’t get me started on why I should be printing invoices – I wanted to expose it. Luckily the generated Avahi service file is easy to fiddle with.
Next up, actually trying to print. Unfortunately there is one thing that could be a bit difficult to guess: CUPS validates the
Host header passed (IPP is based on HTTP/1.1). By default, if you don’t fiddle with its configuration, what it looks for is the same hostname as set in the system, but what gets sent by the iPad is what it has found through mDNS/Avahi, which is the base host name followed by the
.local domain. In my case that meant CUPS was expecting
deepspace9.home.flameeyes.eu and it got
deepspace9.local. Since the CUPS configuration is heavily inspired by Apache, just adding
ServerAlias should be enough… but it’s worth noting that when accessing CUPS through a browser, especially with SSL enabled, it will send the port number as well, so you should alias both
The takeaway of this all? Well, sometimes proprietary software solutions are not any better than Free Software — not that there is a good way to handle that for us as well, but it still shows its fragile support even using the same server software as the protocol’s creator.