Category Archives: Uncategorized

Generating Invoice PDFs

I need to generate PDF files for invoices. How hard can it be? My project is developed using PHP, so I first had a look at the available PDF libraries for PHP.

TCPDF

TCPDF is a project to generate PDF files from PHP. It is available since 2002 and is used in many projects. However, there are a few concerns:

  • The API is not object oriented, but uses one huge TCPDF class. It uses PHP constants for several configuration options and the API does not use constants, but strings.
  • Example: To create a new TCPDF object with the page format A4 and mm as units, you would use: new TCPDF(‘P’, ‘mm’, ‘A4’);
  • The biggest showstopper is that configuration for fonts takes place using PHP constants, which, once defined, cannot be changed. That means that it is very hard to integrate TCPDF into Symfony2.

ZendPDF

ZendPDF is the PDF class from the Zend Framework. I have looked at ZendPDF Version 2. Given the repository activity on GitHub, it seems that ZendPDF is not really maintained and documentation is completely missing.

phantomjs

PhantomJS is a headless web browser based on WebKit, which can also be used to render the output of a HTML page to a file. Unfortunately, phantomjs has a serious kerning problem as seen here: Example PDF. The exact same issue occurs using wkhtmltopdf.

LaTeX

LaTeX is…well…LaTeX. Either you have it or you love it. In my case, the lack of experience with LaTeX and struggling for 2 hours implementing a proper footer placed LaTeX on the bottom of the priority list.

Web-based services

I had a look at several web-based invoicing solutions, including Sage One and Freshbooks. Sage One didn’t support downloading of invoice PDFs via the API, and Freshbooks wasn’t able to produce invoices switchable date formats per invoice.

Conclusion

Right now, my best bet is probably using LaTeX. I might update this post at a later point

 

OneTimeMail: Reducing mail for evaluating web services

When you sign up to a web service these days, you often only want to try things out. Vendors will usually send you emails, followed by special offers, how to use their products and so on.

I often tend to forget to cancel accounts, so my Inbox gets filled with many mails I have to manually sort and delete. In order to reduce the amounts of mail, I implemented a little filter rule to automatically filter mails for web services which I evaluate.

In order to do that, I follow the convention of adding -otm-<vendor> to the mail I’m registering at those web services. For example, if my email was herbert@example.org, and I would want to sign up with Google, I would sign up with herbert-otm-google@example.org.

As my mails are hosted at uberspace, I created a simply mailfilter rule:

Now all OneTimeMails are moved to a subdirectory of my inbox. I still can retrieve the mails if required (to click activation links for example), but my main Inbox is now cleaner.

DHL Shipping Labels, Adobe Reader and HP Printers

Printers. They suck since I started using them. But often, drivers are the real culprit. The task was simple: Print DHL shipping labels on one paper tray, and A4 stuff on the other tray. The printer in question is a HP P3015 with one additional tray. A4 sits in tray 3, the A5 shipping labels in tray 2. However, this isn’t as simple as it may sound.

Adobe Reader has an option to automatically select the paper tray based on paper size. Initially I thought: “Well, that’s pretty much what I want”. But after some testing, I encountered those symptoms:

  • When printing A4 paper, often the printer would decide that I have to feed him from Tray 1 (manual feed) instead of the A4 paper sitting in tray 3.
  • When printing A5 shipping labels, the printer requires the user to confirm each page on the menu for Tray 2.
  • The printer driver often ignores the tray setting and tries to print from tray 1, regardless of the selected paper format or available paper

One major issue with that setup is that DHL supplies DIN A5 labels, but their PDF is in some envelope format – that’s why Adobe Reader most likely can’t choose the correct paper tray. And even if it did, the HP driver seems to have some major bugs regarding paper tray selection.

After fiddling around with the drivers for 2 hours, I decided to do the following setup:

  • 2 Printer Drivers for the same printer (in my case, HP P3015 DIN A4 and HP P3015 DIN A5)
  • Each printer has set the other paper trays to be not available
  • Removal of “Automatically select paper size” in Adobe Reader

This setup works now, but it isn’t optimal, as the user needs to switch between the two printer drivers – but at least this works now.

cryptsetup-1.6.6 breaks my crypto! BLARGH!

I updated my NAS server today, which runs on Debian Jessie (testing). After upgrading to cryptsetup-1.6.6, I noticed that my main share didn’t mount anymore. I investigated, and a very odd thing happened while entering the passphrase: cryptsetup took *any* key I entered!

Well, that’s not entirely true. Usually, cryptsetup asks multiple times if the key is wrong, but in my case, it silently dropped me back to my shell without any information.  Running cryptsetup with –verbose revealed that there was:

My heart stopped for a second, because I thought: SHIT, there’s something wrong with the physical disk! Of course, everything was okay – cryptsetup-1.6.6 has a bug which obviously has problems decrypting at least one cipher I use. That particular version of cryptsetup actually did decrypt my other crypto.

Here’s the luksDump info of the drive cryptsetup-1.6.6 couldn’t open:

To downgrade to a more stable version of cryptsetup, I added the stable repo:

Then I pinned the versions of cryptsetup, cryptsetup-bin and libcryptsetup4 to their stable versions:

After running apt-get update, the system should downgrade to cryptsetup-1.4.4. In my case, luksOpen did work again. WHEW!

Hacking and Living on Lanzarote: Day 0 and 1

Day 0

After a flight of only 4 hours I arrived at 8:30AM at Lanzarote Airport. I only got maybe two hours of sleep, but at least everything with my luggage was okay. We went shopping for food and checked out an abandoned building site which was supposed to become a tourist centre. In the evening, David cooked a nice meal and we were discussing plans on how to proceed.

Day 1

We started to dig a hole for a toilet at the place where we are currently staying to do a favor to the owner. The hole needs to be 2m deep, and we made like half a meter of progress. We made a nice time lapse video of it:

We then headed for an abandoned dam to see if it would be suitable to live in. We were hiking for an hour to reach the top of the mountain, and eventually got down to the dam. It was in pretty good shape, however, there isn’t much space inside the dam to use. We talked to a local who told us that there were actually people living inside the dam, and the police eventually came and threw them out.

We discussed a few ideas about how to get sponsorship and talked to a few other locals about opportunities to buy land.

In the evening, David cooked a nice meal and we set up syncthing in order to be able to share files without the need for an online connection.

OXID Rants

Today I had a major outage in an OXID-based shop system. The reason is unknown; it did resolve “itself” as quickly as it appeared, leaving behind an almost 3 hour downtime of the system. I assume that it’s a combination of their odd caching, and during debugging what went wrong, I took some notes which I eventually wrote down in this blog entry.

OXID, why do you disable modules without any visual indication on the modules list?

OXID shows that modules are enabled, but some aren’t. Nothing in the error logs. No information on the GUI. After an hour of digging into the code, I found out that there’s a configuration entry in the OXCONFIG table (of course, crypted see below) which holds a serialized PHP array of disabled modules (“adisabledmodules”). I do not know at this point where this array is filled, but if it is, modules are silently ignored – and the worst thing: They are shown as if they are enabled.

OXID, why don’t you give any hints why a module can’t be enabled?

If OXID fails to enable a module, it does so silently. At least, this time you actually see that the module is disabled again, but you get no clue why.

OXID, why you store your config encrypted in the database?

OXID uses DECODE() and ENCODE() with a public known key to store data in the OXCONFIG table. This is next to useless and only makes maintenance harder. The key is actually the same for each installation. Of course, one could change the key, but this isn’t documented. Additionally, some contents of the OXCONFIG table are stored as temporary, unencrypted data in the tmp folder anyways.

OXID, why do you use a custom class extension system?

OXID uses a custom class extension system. Probably to emulate some kind of multiple inheritance. In theory, this doesn’t sound too bad, but in practice, this gives headaches, because it is implemented poorly.

Class names are mangled to lower case in some places, but not in others, causing all sorts of problems, combined with too much or simply wrong caching mechanisms. One needs to add their class extensions into a file called “metadata.php”, which looks like this:

Don’t ever change the case of _any_ class name. Here’s where the inconsistency begins: The actual PHP class name is “Thankyou”. Most modules so far use “thankyou” as class identifier for the “extend” portion of the array. If you’d use “Thankyou” as identifier, you’d mess up the whole system, resulting in “method not found” errors. And if you did that once, it gets cached in the system, and you have no chance to revert this unless you manually delete the information from the OXCONFIG table.

Conclusion

When I first started out with OXID, it didn’t seem too bad as a shop system: They got unit tests and a wide range of modules. Some of them are available as purchase-only variants, which is okay.

However, the quality of the whole OXID infrastructure is a big problem. It uses smarty templates all over the place, even in their admin backend. Modules assume that they are the only one who extend a template, which is often not the case (example: List headers). There’s no documentation on where you should extend functionality. There’s no overall picture of how the business logic works. You can even purchase two modules, which change the business logic.

The lack of technical documentation is a big no-go. Did you knew that database properties are mapped to an object’s tablename__fieldname property? If you want to retrieve an order’s order date, you need to use:

This is neither documented within the oxBase class nor on their OXIDForge Website. If you decide to step into OXID development, be aware that you’ll be on your own – forums aren’t too much help, and expect to read lots of (odd), undocumented code.

We need more troubleshooters for 31c3 (and other big chaos events as well)

This is a small personal review of the 30c3. I realized that the congress (and other big chaos events as well) need more troubleshooters – that is, angels that take responsibility for minor problems and willing to solve them.

Update: jz pointed out that your troubleshooter for all concerns is heaven (DECT 1023), even for minor tasks. So this blog post is mostly obsolete, but kept as-is for reference. However, you (as an angel) still may want to take responsibility to call heaven when you spot a problem which you can’t solve.

While I was not able to attend the congress as I had planned to due to a cold, I did 4 hours of NOC Helpdesk as well as other minor tasks. During that, here is a small list of items which occurred:

  • (unconfirmed) It appeared that some switches (if not all) had ports 1-4 reserved for NAT64, which was not labeled on the switches themselves.
  • The NOC Helpdesk did not have enough seating for the 4 angels assigned to the NOC helpdesk shifts
  • The NOC Helpdesk didn’t have pens, paper and a list of contacts to call (like the NOC itself). This was partially solved
  • Each Colo Server should have a set of contact information (name, DECT/GSM number, departure date, IP address). People put the labels onto by themselves with missing information, until we realized that a printed form would be a better idea (that also decreased setup time for each Colo server)
  • People were going up to the Colo by themselves, without being aware of that they need to report to the NOC helpdesk prior putting their servers up (solved by putting up some signs which said something like “YOU SHOULDN’T BE HERE, REPORT TO THE NOC HELPDESK”)
  • At least one person reported that the WIFI access data should be put up as signs all over the congress (aka you can use any Username/Password combination and which WiFi does what), especially as the wiki was down (was not solved AFAIR, but couldn’t solve it myself due to the cold)
  • A local wiki mirror should have been put up, as it was down several times

All those items listed required that some angel stepped up and took care of it (=responsibility).

This might also go wrong in some cases; in my case, I opened the door for the NOC to the Colo with some lockpicking tricks (the person with the key to the colo was asleep) and I was “caught” by a security angel. I tried to explain the situation, however, even saying that this was for the NOC and he should call the NOC to resolve the issue was ignored. Yes, I probably shouldn’t have opened the door and instead calling somebody, but that wasn’t obvious to me in that situation. So yes, taking responsibility for things sometimes goes horribly wrong and you might end up with wrong decisions.

But again, we need more angels who not only do what they’re told to do, but who do take responsibility and willing to resolve problems (or do improvements) as they appear. After the congress experience (and, of course, the OHM2013 experience where I acted as emergency toilet cleaner/soap/toilet paper refiller), I really feel that there’s a big need for angel problem solvers – maybe not only within their shifts, but in general. This will make the congress more enjoyable for everyone.

Probably there should be a team of “troubleshooters”, which takes care of any “interdisciplinary” issues occurring. That team should also be walking around and ask angels doing shifts what could be improved – because often, angels can’t leave their posts to solve those issues.

SolarWind currently out of order

A few weeks ago, SolarWind became pretty unstable. This mainly has 2 reasons:

  • The router draws too much power (I planned to upgrade to Carambola2, but haven’t gotten the time yet), thus it becomes unreachable in the night. This was expected.
  • It doesn’t connect to my home WiFi network anymore, which I’m unable to debug due to lack of the serial interface – I’m using the serial to communicate with the power measurement board

This means that there’s no data. I hope that I can free some money to buy a larger panel and finish the Carambola2 upgrade. In the meantime no data is available – sorry!

SolarWind OHM2013 slides

Here are the slides for my talk at OHM2013: Solar Powered Autonomous Routers @ OHM2013

Warum ich Google meine Daten gebe

Seit Jahren herrscht die Diskussion über: “Google ist böse, gib denen nicht deine Daten” und “Google ist nicht böse, gib Ihnen deine Daten”. Bevor ihr den Blogpost jetzt zerreist, gebe ich euch beim Lesen folgendes mit auf den Weg: “Es muß jeder selbst wissen”.

Ich persönlich verwende viele Google-Dienste: Calendar, Contacts und viele weitere. Hauptsächlich Contacts und Calendar sind mir wichtig, denn Google schafft etwas, was ich in den frühen 2000er Jahren vergeblich gesucht habe: Termine und Kontakte auf jeden Device, welches es unterstützt.

Mein erstes Handy war ein Siemens C25 – für heutige Verhältnisse riesig, aber 1999 gab es nur wenig Auswahl. Und: Es hatte (soweit ich mich richtig erinnere) 8 Kurzwahlspeicher. Da das natürlich nicht ausreichte, nutzte man zu dieser Zeit PDAs – ich hatte einen Palm.

Und damit ging dann das Vergnügen los – syncronisieren von Kontakten vom Rechner zum PDA. Ich möchte nicht wissen, wieviele Kontakte und Kontaktdetails verloren gingen – oftmals fehlte der Geburtstag (ich gehöre zu den Menschen, die sich keine Geburtstage merken können). Einfach weg. Oder falsche Daten – das “Resolve Conflicts”-Fenster hat sich bis heute in mein Hirn gebrannt.

Anno 2001 folgte dann das nächste Handy: Ein Sony CMD J5. Es hatte wahnsinnige 500 Addressbucheinträge, inklusive vollständiger Kontaktverwaltung. Natürlich konnte man nicht einfach so die Daten von einem Gerät auf ein anderes schieben – schon gar nicht unter FOSS. Aber damals hatte ich immer eine Windows-Kiste griffbereit.

In 2003 ging es mit dem NEC N22i weiter. Toll – es hatte iMode (was irgendwie nie funktionierte), aber die Sync-Software war wieder ein Grauen. Auch da ging’s wieder rund mit Kontaktverlusten. Und meine Mutter ärgerte sich schon wieder, weil ich Ihren Geburtstag um einen Tag verpasst habe.

Ähnliche Probleme gab es dann mit dem Motorola RAZR v3 in 2005, dem Blackberry Curve 8310 in 2007, bis ich mir 2010 mein erstes Handy mit Android und Google-Datenmonster zulegte: Ein HTC Desire Z. Und plötzlich war der Sync-Krampf vergessen: Die Kontakte liegen in der Cloud, ich kann von jedem Browser auf die Kontakte zugreifen und mein Smartphone synct es brav. Genauso mit den Kalendereinträgen: Da Google nicht von heute auf morgen umkippen wird, kann ich auch getrost Termine in den Kalender schreiben, die erst in einem Jahr relevant sind (z.b. Impfungen). Ich habe erst vor einigen Tagen mein Nexus 4 bekommen – eingerichtet, sync läuft, fertig. Ich weiß nicht, wie Google das macht, aber Google macht es gut. Das ist für mich die Hauptsache.