DHL outsmarts all

I sold a couple of things on eBay recently and went ahead to print labels for the packages on DHL.de. The user interface is clean and understandable until there, though they validate (or rather invalidate) my bank code for a GiroPay payment a bit late and even with a misguiding error message (no, I have not entered a wrong bank code, its just that my bank isn’t set up for GiroPay). But this alone is not the reason for this post, the reason is what awaited me after I was billed…

My expectations were simple: I thought I would be redirected to some page which would generate my parcel label on the fly, provide it as easy PDF download and thats it. It was that easy actually with DHL’s German competitor Hermes, but no, DHL had to outsmart the whole process.

On the final page in DHL’s booking process you have three options:

1) Open the label in a Java applet for viewing and printing
2) Saving the label via the Java applet
3) Saving the label as PDF

The “default” way – using the Java applet – did not work out at all for me on the Mac, neither in Safari nor Firefox. The applet simply did not load at all and “saving” the applet apparently meant for the DHL guys to save the HTML in which the applet code is embedded… cool. It doesn’t make a difference if the applet is embedded in an offline or online webpage, if the applet *itself* does not work!

Anyways, the PDF link seemed to be more familiar anyways, so I headed there and opened the downloaded file in OSX’ Preview.app. This was the result:

DHL pdf gone wild

The text in the red box on the left says that Javascript is disabled in Adobe Reader. Are you serious guys? Do I really have to install this bloatware Adobe Reader just to print out a simple label?

I had no other choice apparently. If the money was not already theirs, I’d have stopped by now, but I was part of their process.  Adobe Reader 9.20 was only a 32 MB download away (thanks god we all have broadband connections here – or do you think DHL would have paid for the roughly 90 minutes on a 56k dial-up connection?) and only 230 MB after installation, so I went ahead to the big moment – would I finally be able to view and print my beloved label?!

dhl2

Almost – now I reconized why Javascript was needed here after all: The document was “dynamic” in the way that it seemed to fetch the actual label data from a webservice located at https://www.dhl.de/popweb/services/LabelService?wsdl. (You really thought you could hang up your dialup connection after the Adobe Reader download?) All the label’s contents are overprinted with “MUSTER” (German for “SAMPLE”), even after the data were fetched. Printing only seemed to be possible once via a special yellow “Postage print now” button which appeared right in the document once the data had been loaded. The print now button seemed to remove the “MUSTER” overprints from the final print, but I actually cannot tell you that for sure, because I made the mistake to print to a PDF printer in the printer dialog – and Adobe’s distiller told me then:

This PostScript file was created from an encrypted PDF file.
Redistilling encrypted PDF is not permitted.

Opening my original PDF for the second time left me with my loss of roughly 6 Euro alone:

There went my money

“This parcel label has already been printed”. Yeah, they got me. I’ve played around and I lost. I’ve tried to outsmart the process, but they outsmarted me. My last chance to see at least some of my money is to contact their service support – which I did by now – but whatever comes out of that, they also lost me as customer for sure.

I mean, seriously, this vendor lock-in is hilarious. Its quite simple to create a unique pattern or scanner code for a single package which cannot be re-used and tampered – what came over them to invent something that brain-dead instead? Either they’re over paranoid or their IT guys never have dealt with crypto or they have some other huge pain in the ass which forces them and their customers to this process.

Deutschland braucht mehr Altenheime!

An der Ecke Täubchenweg / Breite Straße stand seit Jahren ein baufälliges altes Gründerzeithaus. Es wurde bezeiten mit grünen Spannfliess abgesichert und großflächig mit einem neuen Medizinzentrum (“Medineum”) beworben. Nachdem es dort aber nie wirklich voranging und zwischenzeitlich das Plakat selbst schon abgenommen wurde (die Bauherren glaubten wohl selbst nicht mehr daran), war ich dennoch erfreut zu sehen, als sich im letzten Sommer endlich etwas regte und das Haus abgerissen wurde. Soweit so gut, “eine Brachfläche mehr” dachte ich, aber weit gefehlt. Vor einigen Tagen war dann Grundsteinlegung für ein neues Bauprojekt. In diesen Zeiten werden nun jedoch nicht mehr an jeder Ecke neue Supermärkte hochgezogen, wie es noch Mitte / Ende der Neunziger Jahre der Fall war, nein, es gibt in einer immer älter werdenden Bevölkerung einen viel einträglicheren Milliardenmarkt, das Älterwerden und die damit verbundenen Dienstleistungen!

Ich würde wohl über den Bau eines neuen “Seniorenzentrum” nicht schreiben, wenn nicht schon direkt gegenüber 2008 ein “Seniorenstift” entstanden wäre. Zwei Altenheime direkt gegenüber? Direkt mit Tram-Anbindung? Ja, fantastisch! Nun fehlt eigentlich nur noch der ein oder andere Bestatter in direkter Nähe. Es gibt zwar schon einen 200m weiter in der Breiten Straße, aber hey, einer mehr kann da gar nicht zuviel sein, oder? Schließlich werden gerade die Kapazitäten ausgebaut und außerdem koexistieren gefühlte 20 Nagelstudios und zehn Friseurgeschäfte hier in der Umgebung auch nahezu Laden an Laden.

Nicht, das man das jetzt falsch versteht, ich habe nichts gegen alte Leute. Das wäre ungefähr genauso dumm wie etwas gegen Kinder zu haben. Wir waren alle mal Kinder und wir werden alle mal alt. Was mich aber einfach erschreckt ist die volle Breitseite der Kommerzialisierung und wie sie auf so ein Stadtviertel wie das meinige trifft. Sicher schaffen diese “Zentren” Jobs in der Pflege alter Menschen, doch wer kann sich so etwas überhaupt noch leisten? Und wollen die Menschen wirklich abgeschottet von der Außenwelt in diesen Bettenburgen “verwaltet” werden? Warum entsteht nicht ein Wohnpark, wo junge und alte Menschen gemeinsam leben und sich gegenseitig helfen, wo sich auch alte Menschen mit ihrem reichen Erfahrungsschatz und ihren Ideen aktiv in den Kiez einbringen können?

Und dann ärgert mich auch das einseitige Denken der Stadtplaner in Leipzig. Soll jetzt einfach jedes baufällige Gebäude in der Umgebung in einen neuen “Seniorenstift” umgewandelt werden? Gibt es keine anderen Ideen mehr, was man sonst mit brachliegenden Flächen anstellen könnte? Ist das wirklich das Signal, was man einem Wohngebiet geben möchte, “hier werden die Alten verwaltet”…?

Quick Tip: NetworkManager and /etc/resolv.conf

If you have trouble with NetworkManager overwriting your `search` and `domain` configuration after every startup and you’re using DHCP, add the following line to your `/etc/dhclient.conf`:

append domain-name " company.local other.company.local";

So whenever your DHCP server doesn’t provide these information (the one in my company does not), it’ll add this

domain company.local
search company.local other.company.local

to your `/etc/resolv.conf`.

Geht auf die Straße!

Das folgende Video stammt aus der WDR-Sendung “Mitternachtsspitzen” und ist schon einige Tage alt. Wilfried Schmickler, der hier zur absoluten Höchstform aufläuft, poltert gegen weltfremde Politiker in unseren tollen neuen neoliberalen “Kuschelkoalition”:

Solange allerdings die volle-Tasche-leere-Tasche-Politik so wie bisher weitergeführt wird (ein Euro mehr in der linken, dafür einsfuffzich weniger in der rechten), glaube ich nicht, dass der fromme Wunsch der Kabarettisten auf mehr Bürgerbeteiligung aufgeht.

monotone / guitone update

Thanks to Timothy (and probably also thanks to the bad weather) we’ve seen some development activity for monotone recently. It started out with the “key-by-hash” changes: keys are no longer identified by its name, but their unique ID which finally solves the “I have lost my monotone private key – help!” issues from the past. This already went into monotone 0.45 which was released about a month ago.

Now the upcoming monotone release includes another long-awaited feature which is in the trunk as of yesterday: being able to query database contents from remote monotone servers. This is particularily useful if you want to check what branches are available server-side before you fetch them all. I’ve teamed up with Timothy and made a “single-shot” version of his new `automate remote_stdio` command which can be used as follows:

 # this picks your default netsync server stored in the database
 $ mtn au remote branches
 # ... alternatively, give it an optional hostname
 $ mtn au remote --remote-stdio-host myserver.org branches

Since both `automate remote_stdio` and `automate remote` can execute any available remote automate command through this, a little lua guard was implemented which allows the server administrator to pick certain commands which he wants to make available. By default, no command can be executed:

function get_remote_automate_permitted(key_identity, command, options)

where `key_identity` identifies the calling user, command points to a table which contains the command’s name and arguments, and options points to another table which contains the options for the given command.

Now what has all this to do with guitone?

Especially the changes in 0.45 forced me already to pick my old pet project up again, because key-related commands changed their output in an incompatible manner and therefor my code needed to adapt to that as well. I’m also planning to finalize other features in the upcoming weeks, amongst that netsync support (whose automate versions incidentally have to be implemented in monotone at first as well), an improved changeset browser and probably other minor things and bugs which have been on hold since February.

Netsync dialog

The next guitone version won’t be out before monotone 0.46 hits the streets though, simply because I have to wait (and implement) a couple of things in monotone first and because I want to publish a release which does not explode the first time you’ll look at it. But hey, since I’m the release manager for monotone as well, its in my hands when it will be out 🙂
Its also likely that I’ll introduce a beta release cycle for the next guitone release and make a couple of binaries so people get their hands on it easier and earlier.

So, stay tuned for more updates on both projects!

Leipzig nimmt Platz

Am nächsten Samstag, den 17.10., ist es soweit: Nazis wollen unter dem Motto “Recht auf Zukunft” durch den Leipziger Osten marschieren und das Bündnis “Leipzig nimmt Platz” plant passiven Widerstand dazu. Wer rechtes Gedankengut verabscheut und es auch ertragen kann, dass Faschisten durch unsere Straßen marschieren, dem sei hiermit ans Herz gelegt, sich doch einfach an der Initiative zu beteiligen. Derzeit gibt es schon mindestens 600 Befürworter.

Was man schon im Vorfeld konkret tun kann? Hier sind zwei Möglichkeiten:

Was kann man am 17.10. tun?

  • am Straßenrand bzw. vom Fenster aus Flagge gegen Rechts zeigen
  • an Sitzblockaden mitwirken, um die Demo zu stoppen (sie ist jedoch schon in Erwartung bis 24 Uhr angemeldet worden)

Wie bei jeder Demo muss daran gedacht werden, dass alle Aktionen rechtsstaatlich abgesichert sein müssen. Gewalt ist also kein legitimes Mittel. Und auch wenn es bspw. den Polizisten an diesem Tag stinkt, sie müssen ihrem Job nachgehen und für die Störungsfreiheit der angemeldeten Demo sorgen.

Zum Schluss immer daran denken: Sie mögen viele sein, aber wir sind mehr! Demokratiefeinde haben weder in Reudnitz noch sonst irgendwo ungestörte Redefreiheit verdient!

Why the lucky stiff

I actually don’t know where this guy got his name from, nor how exactly I stumbled upon him or his excellent book on Ruby, but one is for sure: He’s one of those adorable people with more than one or two skills. You can already get this if you read the first few pages of the aforementioned book, which is even if you’re not interested in Ruby still worth a read alone for all his genious anecdotes, weird examples and funny cartoons. So if you have half an hour or two, look at it and think about it.

And yet again something repeats which I already encountered in other areas of my life: At the time I get to know to a particular band or in this case software evangelist, they already retired for unknown reasons from their work. All the best for you, you lucky stiff. I’m sure you’ll also do an excellent job in the “offline world”, wherever you are…

Holidays (Update)

I’ve finally managed to upload some pictures of our holidays in Sweden from September 2009. We’ve rented a small appartment nearby Malmköping, about 100km away from Stockholm – which we’ve (of course) visited as well.

Sweden impressed us all pretty much, I’ve never seen such a beautiful landscape in my life before. My little son has fallen in love with the equally young daughter of our host, named “Heather”, which he only met once, but constantly talked about later on. And finally my wife already starts to think about emigration while she’s looking for Swedish language courses…

In the end we all agreed that eight days Sweden is not much, probably way too less, and that we definitely want to come back again, even if it will not yet be forever. We’ve then spent the second part of our holidays in Hamburg and I’ll probably upload some pictures from there as well. I’m still speechless when I think of our visit in the “Miniaturwunderland”

Update: Here are the missing photos from our Hamburg visit.

Wahlergebnis

Wenn ich auf das Wahlergebnis schaue, bekomme ich schlechte Laune. Schwarz-Rot war schon schlimm, aber vier Jahre Schwarz-Gelb sind nicht gut für Deutschland. Hier nun noch einmal kurz zusammengefasst, was wir in der nächsten Zeit zu erwarten haben:

  1. keine Fortschritte in der Bildungspolitik – jedes Land darf weiterhin separat rumwurschteln und Schüler werden vorzeitig separiert
  2. Anhebung der Verbrauchssteuern zur Schuldentilgung (aber das hätten die anderen wohl auch gemacht)
  3. kein Atomausstieg, sondern eher Verlängerung bisheriger Laufzeiten, natürlich ohne Endlager
  4. weitere Überwachungsbegehrlichkeiten zum “Schutze des Bürgers”
  5. Verschlechterungen beim Kündigungsschutz und keine Arbeitnehmerschutzgesetze vor Lohndumping und schlechten Bedingungen
  6. keine wirksame Bankenregulierung bzw. Finanzaufsicht
  7. weiterhin keine wirksame Integrationspolitik
  8. kein Abbau von Subventionen bzw. Forderungen nach weiteren Marktbeschränkungen, etwa bei der “Milchquote”

Während in anderen europäischen Ländern notwendige Erneuerungsprozesse bereits voll im Gange sind bzw. schon abgeschlossen wurden, um auf sinkende Bevölkerungszahlen, Globalisierung der Wirtschaft und die aufkommende Energiekrise zu reagieren, wird in Deutschland in den nächsten vier Jahren wieder blind im Nebel gestochert, noch mehr als in der letzten Legislaturperiode.

Der Opposition, vor allem den Grünen, den Linken und den Piraten (die erfreulicherweise wohl 2% der Stimmen erhalten haben sollen, leider aber in meinem Wahlkreis nicht wählbar waren), bleiben nun vier Jahre Zeit, sich intensiv in Opposition zu üben und den Menschen wirksam zu vermitteln, dass es spätestens 2013 besser ist, nicht wieder Schwarz-Gelb zu wählen.

Gute Nacht, Deutschland.

Fixing MySQL / PDO error 2014

The following error on my current project at work really gave me lots of headaches today:

SQLSTATE[HY000]: General error: 2014 Cannot execute queries
while other unbuffered queries are active. Consider using
PDOStatement::fetchAll().
Alternatively, if your code is only ever going to run against
mysql, you may enable query buffering by setting the
PDO::MYSQL_ATTR_USE_BUFFERED_QUERY attribute.

So, yes, I already have PDO::MYSQL_ATTR_USE_BUFFERED_QUERY set to TRUE, so why is PDO still complaining? And especially why it is complaining now, because the same code which triggered the error today ran without problems for the past 9 months?

After struggling a lot I found the cause: I missed to close a statement which was reused in a loop!

So take care that you always call PDOStatement->closeCursor() in use cases like this:

$stmt = $con->prepare(“SELECT * FROM doodle WHERE id = ?”);

foreach (range(1,10) as $id)
{
$stmt->execute(array($id));
$row = $stmt->fetch();
$stmt->closeCursor();
}