Blog

// Sending daily digest emails from Wunderlist

For some time, I am using Wunderlist as my to-do task manager (yup, I am surfing on GTD wave now). In some aspects, it is superior to its biggest competitor, Todoist (at least it has notifications for free and cleaner design). One feature I am missing the most is some kind of automatic daily digest sent to my email address every morning (and evening).

Fortunately, they have published their API some time ago. This allows 3rd party application to access and manage the whole content of user's profile.

I wrote simple script which grabs all unfinished tasks via API and sends an email with daily overview. I call it Wudd. I do not offer it as a service (yet?) so everyone has to deploy it on their own machine (See README file).

Main features:

  • 3 sections: Today tasks, unsorted (inbox) tasks without a date, tasks to be finished in 7 days. Generic definition structure allows to add another sections easily.
  • Both HTML and plaintext version for people who remember 90's.
  • Quick summary in subject.
  • Currently it uses Czech locale but it's easy to modify it (few strings only). I18n not supported yet.
  • Sends email via local SMTP (authorization & SSL support not supported yet).

Visit my Bitbucket repo to download Wudd. Also, you can post issues there. Enjoy!

// Thunderbird LDAP via SSL with self-signed certificate

Adding a LDAP directory as a contact source for Thunderbird can be quite tricky if you have SSL-only connection and your server is using self-signed certificate. For some reason there is no Add exception dialog appearing during the first connection attempt as we got used to when connecting to a mail server.

Following will help you to to add the exception manually:

  1. Go to Config editor (aka about:config, PreferencesAdvancedGeneral, press the Config editor button).
  2. Add new (or edit existing) string key 'network.security.ports.banned.override', set value to '636'. This will disable port blocking feature for port 636 (visit http://www-archive.mozilla.org/projects/netlib/PortBanning.html for more info).
  3. Go to SettingsAdvancedCertificatesViewServersAdd exception.
  4. Type your_ldap_host:636 to the Location field, click on Get certificate, then Confirm Security Exception.
  5. Add your LDAP directory to contacts
  6. Now you can revert the config 'network.security.ports.banned.override' to previous value, it is no longer needed.

Hope that helped ;-)

// Reading output of remote command with Dropbear ssh client

Today I faced strange behavior of Dropbear SSH client (dbclient) on my home OpenWRT home router. Before anything else, I would like to note that I do not have the recent version, but the version included in my OpenWRT installation. Exactly, it's Dropbear v0.53.1. But most distributions do not have recent versions so I hope this will remain usefull to others.

I have a shell script which uses ssh client to read some information from my other server. Imagine following shell code snippet:

result=`ssh -i key_file user@server remote_command` && {
  echo "Obtained information is $result"
}

This code will connect to remote machine and run remote_command which produces some output. This output will be assigned to variable $result. If remote command succeeds (returns exit code 0) the message with obtained value will be printed.

For particular reason, this snippet did not work if the whole script was run by cron. I googled a lot. I found some issues in Dropbear mailing list including quite dirty but working solution.

The reason is that script run by cron has no standard input available. Due to this, dbclient does not read any output from remote command either, so the $result variable is set empty and no error code is returned.

This behavior can be simulated from running shell as

ssh -i key_file user@server echo "foo" </dev/null

Nothing will be returned. Note that this modification does not affect OpenSSH client behavior (SSH implementation on most “big” Linux machines).

The quickest solution is to “create some stdin to ssh client”, redirect from /dev/zero is enough. Following code works:

result=`ssh -i key_file user@server remote_command </dev/zero` && {
  echo "Obtained information is $result"
}

Now the whole script works either standalone or as a cronjob.

// One Year with Amazon Kindle

About a year ago I finaly purchased my first Kindle 3 Wifi (later renamed to Kindle Keyboard Wifi). In these days new VAT limit for purchases out of EU was starting to be applied. But I ordered it in time before the final price raised by 20%. UPS delivered the package from US quicker than Czech Post Office is even able to deliver letter from one part of Prague to another (yes, they let you pay for it a lot). In parallel, leather cover was going from China. It took about 2 weeks to the delivery (but the shipping was free of charge).

It had not (and still has not) any sense to purchase Kindle from Czech retailer since the prize is much better and acording to many people on internet, Amazon return services are much better than services of arbitrary Czech e-shop.

Kindle in leather cover from DX.com

Primarily I've bought Kindle for school purposes (lecture notes and papers). I refused big Kindle DX because of its price and size, and purchased the small one. I became familiar with it very quickly, even for fictional books reading. After few years, the market with Czech written books finally arises but sometimes books include painful non-Amazon incompatible DRM stuff. Czech (and world's) classics is available for free from e.g. Municipal Library of Prague. In recent days I fell in love with shopping from Amazon, for both fictional and technical literature. Beside the fact that the price is much better, some books are not even available in Czech Republic.

Pros:

  • Size and weight. Now I need not to take big bag with books to a vacation.
  • e-Ink display. The most excellent LCD in the world cannot compete with it.
  • Amazon Whispernet. In combination with e.g. Send to Kindle Chrome extension, it's unbeatable for offline articles reading.
  • Dictionary integration. For us who do not handle English vocabulary so well.

Cons:

  • Inability to open non-Amazon DRMed books. Our local market with DRM protected books lays on Wooky or Adobe DRM technologies.
  • Low speed. When using dictionary, switching from book to dictionary and back is a bit slow. Also handling PDF documents is slow.
  • Kindle is unable to automatically check for new documents at Whispernet when in sleep mode. So I must remind to wake it before going to work if I manage to read newspaper.

// Compiling UI and resource files with PyQt

PyQt is a python binding for popular Qt library (which became LGPLed for non-commercial purposes recently). If you use Qt Designer, you have to compile XML description of UI or Qt resource files to Python code to use them in your application.

In C++, you can easily use qmake tool or Automake for creating suitable Makefile. For Python, there is no Makefile needed since Python compiles modules as they are loaded into VM. With PyQt, you can use uic module for compiling ui files or loading them as a Python class.

Alternatively, you can use pyuic4 and pyrcc4 command line tools in the similar way as appropriate Qt tools (uic, rcc). I'm using this way to produce Python code. Both tools have similar usage:

#compile ui file from Qt Designer
pyuic4 ui_file.ui -o compiled_ui_file.py
#compile resource file (icons, etc..)
pyrcc4 resource_file.qrc -o compiled_resource_file.py

Formerly, I had one shell script to compile all my resource files in project at once (because I was too lazy). This solution has two main disadvantages. At first, compilation of all resources takes more time than compiling of modified files only. This varies with amount of resource files your project has. The second one is more annoying to me. Since I also track compiled versions of UI and resource files (for no particular reason yet) with Mercurial, it always creates new changeset because pyuic4 tool adds information about compile time to Python code comments. So I refreshed my Makefile knowledge (and also used some old code snippets) and created following Makefile for compiling UI and resource files separately.

###### EDIT ##################### 
#Directory with ui and resource files
RESOURCE_DIR = src/resources
 
#Directory for compiled resources
COMPILED_DIR = src/ui
 
#UI files to compile
UI_FILES = confirm.ui main.ui repair.ui settings.ui statistics.ui
#Qt resource files to compile
RESOURCES = images.qrc 
 
#pyuic4 and pyrcc4 binaries
PYUIC = pyuic4.bat
PYRCC = pyrcc4
 
#################################
# DO NOT EDIT FOLLOWING
 
COMPILED_UI = $(UI_FILES:%.ui=$(COMPILED_DIR)/ui_%.py)
COMPILED_RESOURCES = $(RESOURCES:%.qrc=$(COMPILED_DIR)/%_rc.py)
 
all : resources ui 
 
resources : $(COMPILED_RESOURCES) 
 
ui : $(COMPILED_UI)
 
$(COMPILED_DIR)/ui_%.py : $(RESOURCE_DIR)/%.ui
	$(PYUIC) $< -o $@
 
$(COMPILED_DIR)/%_rc.py : $(RESOURCE_DIR)/%.qrc
	$(PYRCC) $< -o $@
 
clean : 
	$(RM) $(COMPILED_UI) $(COMPILED_RESOURCES) $(COMPILED_UI:.py=.pyc) $(COMPILED_RESOURCES:.py=.pyc)  

It works with GNU Make (from Cygwin or MigGW on Windows). It compiles files in following manner:

  • window.ui –> ui_window.py (GUI definition)
  • images.qrc –> images_rc.py (resources)

Now you can easily compile only modified files by only typing make in console. Make sure that your current working directory contains Makefile shown above.

About me
SW developer, amateur tennis player, rock'n'roll & heavy metal fan.