Firewall zones (profiles) in Linux, and how to switch them automatically if you use UFW

Firstly, a note on terminology: UFW (Uncomplicated Firewall) and its two GUI front-ends Gufw and UFW Frontends use the term ‘application profile’ to refer to a pre-configured set of rules specified in a file. Files containing UFW application profiles are placed in the directory /etc/ufw/applications.d/. An application profile for SMB, for example, enables the root user to use the UFW command ‘ufw allow Samba‘ (‘ufw allow CIFS‘ in Gentoo Linux) rather than having to enter UFW commands specifying the precise ports and network protocols that SMB uses. However, this blog post is not about UFW’s application profiles; it is about what Gufw calls ‘profiles’ and firewalld calls ‘zones’.

In essence a profile/zone is a collection of firewall policies and rules. Both Gufw and firewalld include the concept of a ‘zone’, although Gufw uses the term ‘profile’ rather than ‘zone’. UFW Frontends does not have the concept of a ‘zone’; rules entered via UFW Frontends apply to any network to which you connect your laptop. The ability to define different zones for different networks is handy. For example, you can have certain policies and rules when your laptop is connected to your home network, and different policies and rules when your laptop is connected to the network in a café, hotel, airport or other public place.

An attractive feature of firewalld when used in conjunction with NetworkManager and KDE Plasma is that it is possible to use the desktop environment’s network management module (‘System Settings’ > ‘Connections’) to specify a particular firewalld zone for a particular network connection. For example, let’s say you used firewalld to specify certain policies and rules for a zone you named ‘office’, and you then specified in the System Settings – Connections GUI that a connection named ‘ACM’ should use the zone ‘office’. Thereafter, whenever you connect your laptop to the network named ‘ACM’, firewalld will use the policies and rules you previously configured for the zone ‘office’.

Unlike firewalld, Gufw does not have the ability to switch profiles automatically according to which network the laptop is connected. You have to select manually the profile you wish to use. You would launch Gufw prior to connecting to, for example, your office’s network, select the profile ‘Office’ (or whatever you have named it), then connect your laptop to that network.

I think many people would be satisfied with the functionality currently provided by Gufw. I could use the Gufw GUI to create Gufw profiles with names such as ‘Home’, ‘HomeDave’, ‘Public’, ‘HQoffice’, ‘USoffice’, ‘PestanaRio’ and so on, and specify the different policies and rules I want for each profile. At home I would launch Gufw on my laptop and select the Home profile then connect to my home network; in the office at work I would launch Gufw on my laptop and select the HQoffice profile then connect to the office network; at my friend Dave’s house I would launch Gufw on my laptop and select the HomeDave profile then connect to the house network; and so on. Nevertheless I do see the attraction of automated zone switching, as provided by firewalld in conjunction with NetworkManager and KDE. It would be handy if my laptop could switch automatically to the Home profile when my laptop connected to the network at my home with the name ‘BTHub5-8EUQ’, automatically switch to the HQoffice profile when my laptop connected to the network named ‘HQ-Office2’ in the office, and so on.

I use UFW on my two laptops running Gentoo Linux. The package ufw-frontends is also installed but normally I use UFW directly via the command line. However I wanted to learn about zones/profiles while using UFW, and I also wanted to see if I could automate the switching of zones without resorting to installing firewalld. NetworkManager has the ability to launch ‘hook’ scripts when certain things happen — when a network connection changes, for example — and this seemed to me to be a way of switching profiles automatically.

I had not used Gufw before, so I decided to install it. A package is available in many Linux distributions but there is no ebuild for Gufw in Gentoo’s main Portage tree and I could not find an up-to-date ebuild for it in any Portage overlays. Therefore I created the ebuild for net-firewall/gufw-19.10.0 shown below. It probably needs improving, but it does install a working Gufw in Gentoo Linux.

# Copyright 1999-2019 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: $

EAPI=7
PYTHON_COMPAT=( python3_{5,6,7} )
DISTUTILS_IN_SOURCE_BUILD=1

inherit distutils-r1

MY_PN="gui-ufw"
MY_PV="$(ver_cut 1-2)"

DESCRIPTION="GUI frontend for managing ufw."
HOMEPAGE="https://gufw.org/"
SRC_URI="https://launchpad.net/${MY_PN}/trunk/${MY_PV}/+download/${MY_PN}-${PV}.tar.gz"

LICENSE="GPL-3"
SLOT="0"
KEYWORDS="~amd64"
IUSE=""

DEPEND="dev-python/python-distutils-extra"
RDEPEND="net-firewall/ufw
	dev-python/netifaces
	dev-python/pygobject:3
	net-libs/webkit-gtk[introspection]
	sys-auth/elogind
	sys-auth/polkit
	x11-libs/gtk+:3[introspection]
	x11-themes/gnome-icon-theme-symbolic
"
S=${WORKDIR}/${MY_PN}-${PV}

pkg_postinst() {
	sed '/dist-packages/d' -i /usr/bin/gufw-pkexec
	sed -E '/\/share\//d' -i /usr/bin/gufw-pkexec
	local PYTHONVERSION="$(python -c 'import sys; print("{}.{}".format(sys.version_info.major, sys.version_info.minor))')"
	sed -E "s|python3\.[0-9]|python${PYTHONVERSION}|g" -i /usr/bin/gufw-pkexec
	sed -E 's|\/lib\/|\/lib64\/|g' -i /usr/bin/gufw-pkexec
}

How To Set Up a Firewall with GUFW on Linux‘ is a good tutorial on Gufw.

As I had not used Gufw previously, I had to play around with it to understand better its functional design. I found that if I configure rules directly via UFW on the command line without using Gufw, Gufw does not allow me to edit those rules (but does allow me to delete them) and those rules exist whichever Gufw profile is selected in the Gufw GUI. Gufw profiles are stored in files named ‘/etc/gufw/*.profile‘ (e.g. /etc/gufw/Home.profile) and these files will not include UFW rules entered via the command line. On the other hand, UFW rules created via the Gufw GUI apply solely to the currently-selected Gufw profile, which is what I would have expected. In other words, I can create a different set of policies and rules in each Gufw profile. Therefore I believe Gufw profiles (as distinct from UFW application profiles) are basically analogous to firewalld’s zones. It also appears to me that Gufw maintains configuration files specifying policies and rules independently of UFW, which Gufw then applies to UFW. In other words, if you are a Gufw user you should not use UFW directly to configure policies and rules, otherwise Gufw’s configuration files will not include what you did directly using UFW. To reiterate, use only Gufw or only UFW, not both.

The current Gufw profile’s name is listed in the file /etc/gufw/gufw.cfg. For example, I currently have the Home profile selected in the Gufw GUI, and the file gufw.cfg contains the following:

[GufwConfiguration]
profile = Home
windowwidth = 542
windowheight = 530
confirmdetelerule = yes

If I examine the contents of the file /etc/gufw/Home.profle I see that it contains the UFW policies and rules I specified for the Gufw Home profile:

[fwBasic]
status = enabled
incoming = deny
outgoing = allow
routed = disabled

[Rule0]
ufw_rule = 137,138/udp ALLOW IN 192.168.1.0/24
description = Samba
command = /usr/sbin/ufw allow in proto udp from 192.168.1.0/24 to any port 137,138
policy = allow
direction = in
protocol = 
from_ip = 192.168.1.0/24
from_port = 
to_ip = 
to_port = 137,138/udp
iface = 
routed = 
logging = 

[Rule1]
ufw_rule = 139,445/tcp ALLOW IN 192.168.1.0/24
description = Samba
command = /usr/sbin/ufw allow in proto tcp from 192.168.1.0/24 to any port 139,445
policy = allow
direction = in
protocol = 
from_ip = 192.168.1.0/24
from_port = 
to_ip = 
to_port = 139,445/tcp
iface = 
routed = 
logging =

I also notice that the other Gufw profiles can differ. For example, my Office.profile file contains the following:

[fwBasic]
status = enabled
incoming = deny
outgoing = allow
routed = allow

The profile name listed in gufw.cfg gets changed when the user changes the profile using the Gufw GUI. It appears to me that only at the point in time when the user selects a certain Gufw profile in the Gufw GUI does Gufw parse the applicable *.profile file and issue commands to UFW to implement the policies and rules specified in the *.profile file.

Initially I tried to automate the process of changing the Gufw profile by doing the following:

  1. I created a NetworkManager Dispatcher hook script to:

    1. detect when the laptop connects to a network;

    2. determine whether the network is at my home, at my workplace or in a public place (café, airport or wherever) by looking at the connection name;

    3. edit gufw.cfg to change the name of the Gufw profile according to the network connected.
  2. I configured KDE to launch Gufw automatically at login, hoping that would implement the Gufw profile specified in gufw.cfg.

When I connected the laptop to various networks, Gufw did indeed show the name of the profile selected by the NetworkManager Dispatcher hook script, but the associated Gufw profile’s rules had not been applied. They were only applied if I clicked on the ‘Profile’ pull-down menu in Gufw, selected a different Gufw profile, then re-selected the desired Gufw profile. Therefore driving Gufw from a NetworkManager Dispatcher hook script is not possible. This is a pity, as Gufw is an easy way to manage UFW from a GUI; it allows the user to create, delete and edit zones (Gufw profiles) and to select them manually. What Gufw doesn’t do is enable the user to associate those zones with connection names, nor trigger specific zone automatically based on the selected network connection. firewalld, on the other hand, does enable the user to do both those things.

As my attempt at automating the switching of zones in Gufw had failed, I decided to create a NetworkManager Dispatcher hook script to switch zones automatically by using UFW commands. Initially I though about creating a bespoke UFW application profile for each zone and allowing/denying those in the script, but it is actually easier to use the fundamental UFW commands in the script, especially as UFW commands are relatively easy to understand. Also, this approach means everything is in a single file, which facilitates configuration. I can simply edit the script in order to: a) add or delete a zone; b) change a zone’s name; c) change policies and rules for a zone; d) add or delete a connection; e) change the name of a connection; f) change the zone a connection uses. Granted, editing a script is not as user-friendly as using the firewalld GUI to configure a zone and then using KDE Plasma’s system settings module Connections to specify that zone for a specific connection, but my script is not particularly difficult to understand and edit. And by using such a script I can continue to use UFW rather than installing firewalld and having to learn how to use it.

My NetworkManager Dispatcher hook script /etc/NetworkManager/dispatcher.d/20_ufw-zones is listed below. In the main body of the script I define the zone I wish to use for each connection, and in the function select_zone I define the policies and rules I want each zone to use.

#!/bin/bash
INTERFACE=$1
STATUS=$2
WIRED=enp4s0f1
WIFI=wlp3s0

CT_helper_rule() {
    echo "# The following is needed to enable Samba commands to" >> /etc/ufw/before.rules
    echo "# work properly for broadcast NetBIOS name resolution" >> /etc/ufw/before.rules
    echo "#"  >> /etc/ufw/before.rules
    echo "# raw table rules" >> /etc/ufw/before.rules
    echo "*raw" >> /etc/ufw/before.rules
    echo ":OUTPUT ACCEPT [0:0]" >> /etc/ufw/before.rules
    echo "-F OUTPUT" >> /etc/ufw/before.rules
    echo "-A OUTPUT -p udp -m udp --dport 137 -j CT --helper netbios-ns" >> /etc/ufw/before.rules
    echo "COMMIT" >> /etc/ufw/before.rules
}
 
select_zone() {
    ufw --force reset
    ufw --force enable
    ZONE=$1
    case "$ZONE" in
    'Home')
        ufw default deny incoming
        ufw default allow outgoing
        #
        # Rules for SMB
        ufw allow from 192.168.1.0/24 to any port 137,138 proto udp
        ufw allow from 192.168.1.0/24 to any port 139,445 proto tcp
        CT_helper_rule
        #
        # Rules for KDEConnect
        ufw allow from 192.168.1.0/24 to any port 1714:1764 proto udp
        ufw allow from 192.168.1.0/24 to any port 1714:1764 proto tcp
    ;;
    'Office')
        ufw default deny incoming
        ufw default allow outgoing
    ;;
    'Public')
        ufw default reject incoming
        ufw default allow outgoing
    ;;
    'JohnsHouse')
        ufw default deny incoming
        ufw default allow outgoing
        #
        # Rules for SMB
        ufw allow from 192.168.42.0/24 to any port 137,138 proto udp
        ufw allow from 192.168.42.0/24 to any port 139,445 proto tcp
        CT_helper_rule
        #
        # Rules for KDEConnect
        ufw allow from 192.168.42.0/24 to any port 1714:1764 proto udp
        ufw allow from 192.168.42.0/24 to any port 1714:1764 proto tcp
    ;;
    esac
    ufw --force reload
    rm /etc/ufw/*.rules.20* # Delete backups of *.rules files ufw makes every time it is reset
    echo -n `date +"[%F %T %Z]"` >> /var/log/ufw-zones.log
    echo " Zone $ZONE selected for connection $ACTIVE on interface $INTERFACE." >> /var/log/ufw-zones.log
}
 
# Check if either the wired or wireless interface is up
if [ "$INTERFACE" = "$WIRED" -o "$INTERFACE" = "$WIFI" ] && [ "$STATUS" = "up" ]; then
 
    # Check if a single connection is active
    if [ `nmcli c | grep -v "\-\-" | grep -v "NAME.*UUID.*TYPE.*DEVICE" | wc -l` -eq 1 ]; then
 
        # Ascertain the name of the active connection
        ACTIVE=`nmcli c | grep -v "\-\-" | grep -v "NAME.*UUID.*TYPE.*DEVICE" | awk -F' ' '{print $1}'`
 
        case "$ACTIVE" in
 
        'eth0')
            ZONE="Home"
        ;;
        'POR1-wired')
            ZONE="Office"
        ;;
        'BTHub5-8EUQ')
            ZONE="Home"
        ;;
        'BTHub5-8EUQ-5GHz')
            ZONE="Home"
        ;;
        'John1')
            ZONE="JohnsHouse"
        ;;
        'GRAND MERCURE')
            ZONE="Public"
        ;;
        *)
            # If connection name is not in above list
            ZONE="Public"
        ;;

        esac

        select_zone $ZONE
        exit $?

    fi
fi

The log file that the script uses contains a chronological record of the connections made and the zones selected:

$ cat /var/log/ufw-zones.log 
[2019-09-30 20:13:52 BST] Zone Home selected for connection eth0 on interface enp4s0f1.
[2019-10-01 22:59:18 BST] Zone Home selected for connection BTHub5-8EUQ-5GHz on interface wlp3s0.
[2019-10-02 17:59:23 EDT] Zone Public selected for connection loganwifi on interface wlp3s0.
[2019-10-03 10:12:46 EDT] Zone Office selected for connection POR1-wired on interface enp4s0f1.
Advertisements

Paul Gideon Dann’s patchset for Poppler to enable Okular (Qt5) to use Cairo rather than Splash to render PDF files

If you view the same PDF file in Okular (KDE) and Evince (GNOME), you may notice that fonts and lines are rendered better in Evince. Both applications use Poppler to render text and graphics in PDF files, but Poppler uses a different rendering backend in the two applications. For Evince Poppler uses the Cairo library, whereas for Okular Poppler uses Splash, a backend inherited from Poppler’s predecessor Xpdf (still in development). Unfortunately for KDE users, Cairo often does a better job than Splash. However, independent software engineer Paul Gideon Dann came to the rescue by producing the patchset poppler-cairo-backend to modify Poppler in order to make it use the Cairo library instead of Splash when Poppler is used by Okular. To quote the README file for Paul’s patchset:

Purpose of this Patchset

Currently, the default backend for the Qt5 wrapper (used by Okular) is Splash. Unfortunately, Splash does not support subpixel rendering of fonts, so those of us using KDE are stuck with somewhat ugly-looking fonts. This patchset adds support for the Cairo backend to the Qt5 wrapper. It also forces subpixel rendering in the Cairo backend. The upshot of this is that we get beautiful fonts in Okular.

The README focuses on fonts, but in fact the rendering of lines in graphics in PDF files can also be improved by the application of the patchset.

Apparently the Poppler maintainer feels that the introduction of a dependency on Cairo to the Qt5 wrapper (even an optional dependency) in Poppler would be controversial, and he is not willing to merge the patchset. For Okular users who already have Cairo installed (e.g. for Firefox, Inkscape, Scribus and so on), and who are noticing inadequate rendering of some PDF files, Paul’s patchset is worth trying.

In Gentoo Linux, which is a source code-based distribution, it is very easy to apply the patchset. For example, I did the following to apply the patchset for Poppler 0.80.0 in a ~amd64 (Testing Branch) installation:

1. Created a package-specific and version-specific directory to hold the patchset:

root # mkdir -p /etc/portage/patches/app-text/poppler-0.80.0

2. Downloaded the patchset for Poppler 0.80.0 from the following Web page:

https://github.com/giddie/poppler-cairo-backend/tree/76e607bcf010d6d9b8df5cb0f851ef9c91d4caf2

3. Copied the patchset to the directory created in Step 1:

root # cp /home/fitzcarraldo/Downloads/*.patch /etc/portage/patches/app-text/poppler-0.80.0/
root # ls -1 /etc/portage/patches/app-text/poppler-0.80.0
0001-Cairo-backend-added-to-Qt5-wrapper.patch
0002-Setting-default-Qt5-backend-to-Cairo.patch
0003-Apply-subpixel-rendering-in-Cairo-Backend.patch

4. Checked first that the patchset could be applied successfully before actually using it:

root # cd /usr/portage/app-text/poppler
root # ebuild poppler-0.80.0.ebuild clean prepare
 * poppler-0.80.0.tar.xz BLAKE2B SHA512 size ;-) ...                                     [ ok ]
 * checking ebuild checksums ;-) ...                                                     [ ok ]
 * checking auxfile checksums ;-) ...                                                    [ ok ]
 * checking miscfile checksums ;-) ...                                                   [ ok ]
>>> Unpacking source...
>>> Unpacking poppler-0.80.0.tar.xz to /var/tmp/portage/app-text/poppler-0.80.0/work
>>> Source unpacked in /var/tmp/portage/app-text/poppler-0.80.0/work
>>> Preparing source in /var/tmp/portage/app-text/poppler-0.80.0/work/poppler-0.80.0 ...
 * Applying poppler-0.60.1-qt5-dependencies.patch ...                                    [ ok ]
 * Applying poppler-0.28.1-fix-multilib-configuration.patch ...                          [ ok ]
 * Applying poppler-0.78.0-respect-cflags.patch ...                                      [ ok ]
 * Applying poppler-0.61.0-respect-cflags.patch ...                                      [ ok ]
 * Applying poppler-0.57.0-disable-internal-jpx.patch ...                                [ ok ]
 * Applying 0001-Cairo-backend-added-to-Qt5-wrapper.patch ...                            [ ok ]
 * Applying 0002-Setting-default-Qt5-backend-to-Cairo.patch ...                          [ ok ]
 * Applying 0003-Apply-subpixel-rendering-in-Cairo-Backend.patch ...                     [ ok ]
 * User patches applied.
>>> Source prepared.

5. Re-merged Poppler to apply the patchset to the Poppler source code and rebuild the patched package:

root # emerge -1v poppler

These are the packages that would be merged, in order:

Calculating dependencies... done!
[ebuild   R    ] app-text/poppler-0.80.0:0/90::gentoo  USE="cairo cjk cxx introspection jpeg jpeg2k lcms png qt5 tiff utils -curl -debug -doc -nss" 0 KiB

Total: 1 package (1 reinstall), Size of downloads: 0 KiB

>>> Verifying ebuild manifests
>>> Emerging (1 of 1) app-text/poppler-0.80.0::gentoo
>>> Installing (1 of 1) app-text/poppler-0.80.0::gentoo
>>> Jobs: 1 of 1 complete                           Load avg: 1.06, 1.11, 0.95
>>> Auto-cleaning packages...

>>> No outdated packages were found on your system.

 * GNU info directory index is up-to-date.

6. Re-merged Okular so that it uses the patched Poppler dependency:

root # emerge -1v okular

These are the packages that would be merged, in order:

Calculating dependencies... done!
[ebuild   R    ] kde-apps/okular-19.08.1:5::gentoo  USE="chm crypt djvu image-backend pdf postscript tiff -debug -epub -handbook -markdown -mobi -mobile -plucker -share -speech -test" 0 KiB

Total: 1 package (1 reinstall), Size of downloads: 0 KiB

>>> Verifying ebuild manifests
>>> Emerging (1 of 1) kde-apps/okular-19.08.1::gentoo
>>> Installing (1 of 1) kde-apps/okular-19.08.1::gentoo
>>> Jobs: 1 of 1 complete                           Load avg: 1.17, 1.13, 1.04
>>> Auto-cleaning packages...

>>> No outdated packages were found on your system.

 * GNU info directory index is up-to-date.

My thanks go to Paul for taking the time to produce the patchset.

How to run KDE Dolphin, Kate and KWrite as root user

When using KDE I occasionally wish to launch KWrite or Kate as root user in order to edit system files more easily than using a TUI editor in a terminal window (either launched as root user or by using the sudoedit command). Being able to browse using Dolphin as the root user occasionally is also useful. These all used to be possible by launching the application with the kdesu command, but in 2017 KDE developer Martin Gräßlin removed this option on security grounds (see his blog post ‘Editing files as root‘). Attempting to launch e.g. Kate using the sudo command results in the following message:

$ sudo kate
Executing Kate with sudo is not possible due to unfixable security vulnerabilities.

Attempting to launch e.g. Kate using the kdesu command results in a pop-up window prompting me to enter the root user’s password, but then does not launch Kate:

$ kdesu kate
$

I am willing to accept a small risk despite the ‘unfixable security vulnerabilities’ , and a 2018 Kubuntu Forums post by KDE user Rog131 provided me with a solution. It is possible to launch Dolphin, Kate and KWrite as root from your user account by using the pkexec command. For example, to launch Dolphin you can enter:

$ pkexec env DISPLAY=$DISPLAY XAUTHORITY=$XAUTHORITY KDE_SESSION_VERSION=5 KDE_FULL_SESSION=true dolphin

Dolphin first displays an orange-coloured box with the warning message ‘Running Dolphin as root can be dangerous. Please be careful.’ and you can then browse and open root-owned directories and files.

You can also launch Kate and KWrite as root from your user account in the same way:

$ pkexec env DISPLAY=$DISPLAY XAUTHORITY=$XAUTHORITY KDE_SESSION_VERSION=5 KDE_FULL_SESSION=true kate
$ pkexec env DISPLAY=$DISPLAY XAUTHORITY=$XAUTHORITY KDE_SESSION_VERSION=5 KDE_FULL_SESSION=true kwrite

To make it easy to launch them as root user from e.g. Konsole or Yakuake you could set aliases for the three commands in your ~/.bashrc file:

$ tail -n 3 ~/.bashrc
alias dolroot="pkexec env DISPLAY=$DISPLAY XAUTHORITY=$XAUTHORITY KDE_SESSION_VERSION=5 KDE_FULL_SESSION=true dolphin"
alias kateroot="pkexec env DISPLAY=$DISPLAY XAUTHORITY=$XAUTHORITY KDE_SESSION_VERSION=5 KDE_FULL_SESSION=true kate"
alias kwriteroot="pkexec env DISPLAY=$DISPLAY XAUTHORITY=$XAUTHORITY KDE_SESSION_VERSION=5 KDE_FULL_SESSION=true kwrite"

Then all you would need to type in a terminal window would be:

$ dolroot
$ kateroot
$ kwriteroot

which are no more difficult than having to type:

$ kdesu dolphin
$ kdesu kate
$ kdesu kwrite

If an alias is used, rooted-Dolphin/Kate/KWrite can be launched from the command line but cannot be launched via KDE’s Application Launcher menu or KRunner. On the other hand, if a wrapper script is used, rooted-Dolphin/Kate?KWrite can be launched from the user’s command line and via KDE’s Application Launcher menu (and therefore via KRunner too). For example, I created three tiny Bash scripts dolroot, kateroot and kwriteroot. The scripts simply contain the aforementioned pkexec command. For example, dolroot contains:

#!/bin/bash
pkexec env DISPLAY=$DISPLAY XAUTHORITY=$XAUTHORITY KDE_SESSION_VERSION=5 KDE_FULL_SESSION=true dolphin

Don’t forget to make them executable:

$ chmod 700 dolroot
$ chmod 700 kateroot
$ chmod 700 kwriteroot
$ ls -la *root
-rwx------ 1 fitzcarraldo fitzcarraldo 115 Jul 30 15:33 dolroot
-rwx------ 1 fitzcarraldo fitzcarraldo 112 Jul 30 15:34 kateroot
-rwx------ 1 fitzcarraldo fitzcarraldo 114 Jul 30 15:34 kwriteroot	

After adding entries for dolroot, kateroot and kwriteroot to the KDE Application Launcher’s menu, you can press Alt+F2 as usual to display the KRunner launcher then enter ‘dolroot’, ‘kateroot’ or ‘kwriteroot’ (without the quotes, obviously) in the KRunner window to launch Dolphin/Kate/KWrite as root user. A window will pop-up for you to enter the root user’s password. Once you have entered the root user’s password, the application will be launched.

Thankfully KDE’s Nathaniel Graham is pragmatic:

D12795 – Re-allow running Dolphin as the root user (but still not using sudo)
D12732 – Show a warning when running as the root user

How to change the height of the Kickoff Application Launcher menu in KDE Plasma

The height of the KDE Plasma Kickoff Application Launcher menu is not user-configurable, which is odd in a Desktop Environment with a reputation for being highly user-configurable.

It turns out that the height and width of the pop-up menu are hard-coded in the ASCII file /usr/share/plasma/plasmoids/org.kde.plasma.kickoff/contents/ui/FullRepresentation.qml:

root # grep -E "Layout.minimumHeight.*units.gridUnit" /usr/share/plasma/plasmoids/org.kde.plasma.kickoff/contents/ui/FullRepresentation.qml
    Layout.minimumHeight: units.gridUnit * 34
root # grep -E "Layout.minimumWidth.*units.gridUnit" /usr/share/plasma/plasmoids/org.kde.plasma.kickoff/contents/ui/FullRepresentation.qml
    Layout.minimumWidth: units.gridUnit * 26

Now, I was a bit fed up having to scroll up and down the launcher menu to see all fourteen entries in my Favourites list, so I decided to increase the height of the menu, which I did by editing /usr/share/plasma/plasmoids/org.kde.plasma.kickoff/contents/ui/FullRepresentation.qml as root user:

root # nano /usr/share/plasma/plasmoids/org.kde.plasma.kickoff/contents/ui/FullRepresentation.qml
root # grep -E "Layout.minimumHeight.*units.gridUnit" /usr/share/plasma/plasmoids/org.kde.plasma.kickoff/contents/ui/FullRepresentation.qml
    Layout.minimumHeight: units.gridUnit * 44

The only downside to this is that the file will be overwritten when the package kde-plasma/plasma-desktop is upgraded.

The following command would allow me to make sure the file contains the height value of ’44’ that I want:

root # sed -i '/Layout.minimumHeight: units.gridUnit/ c\    Layout.minimumHeight: units.gridUnit * 44' /usr/share/plasma/plasmoids/org.kde.plasma.kickoff/contents/ui/FullRepresentation.qml

Therefore, to automate the editing of the file in my Gentoo installations that use OpenRC I created a shell script /etc/local.d/50-set_Kickoff_height.start with the following contents:

#!/bin/bash
if [ -e /usr/share/plasma/plasmoids/org.kde.plasma.kickoff/contents/ui/FullRepresentation.qml ]; then
    sed -i '/Layout.minimumHeight: units.gridUnit/ c\    Layout.minimumHeight: units.gridUnit * 44' /usr/share/plasma/plasmoids/org.kde.plasma.kickoff/contents/ui/FullRepresentation.qml
fi

The FullRepresentation.qml file will then be edited every time the machine boots, which is a tad inefficient but not a big overhead.

This is not a perfect solution because the menu will revert to its default height following an upgrade to the package kde-plasma/plasma-desktop until I reboot the machine, but it is good enough for me.

KDE Device Notifier work-around

KDE Device Notifier can be annoying sometimes. The problem is that clicking on the Eject icon in Device Notifier (tooltip ‘Click to safely remove this device’) both unmounts and ejects the device (two separate commands). Of course, in the case of a USB device the device remains physically connected until you pull out the USB plug. You cannot re-mount the device in KDE Device Notifier until you unplug it and plug it in again. However, there is a hack that can help somewhat, as I explain below.

Firstly, note that it is possible to mount and unmount drives by using the ‘udisksctl’ command. For example, consider one of my USB HDDs which has the label ‘USBHDD01’ (I assign a label to all HDD partitions, be they on internal HDDs or on external HDDs/pendrives). It is possible to unmount the specific USB device and remount it by using the following commands:

fitzcarraldo@clevow230ss ~ $ udisksctl unmount -b /dev/disk/by-label/USBHDD01
Unmounted /dev/sdb1.
fitzcarraldo@clevow230ss ~ $ udisksctl mount -b /dev/disk/by-label/USBHDD01
Mounted /dev/sdb1 at /run/media/fitzcarraldo/USBHDD01.

In both the above cases the USB device remains visible in Device Notifier. I have created a couple of executable Desktop Configuration Files in the directory ~/Desktop/ which I can double-click to run each of the above commands. I have given each of them an appropriate icon:

The file ~/Desktop/Mount_USBHDD01.desktop contains the following:

[Desktop Entry]
Comment[en_GB]=Mount USB HDD with label USBHDD01
Comment=Mount USB HDD with label USBHDD01
Exec=udisksctl mount -b /dev/disk/by-label/USBHDD01
GenericName[en_GB]=Mount_USBHDD01
GenericName=Mount_USBHDD01
Icon=media-mount
MimeType=
Name[en_GB]=Mount_USBHDD01
Name=Mount_USBHDD01
Path=
StartupNotify=true
Terminal=false
TerminalOptions=
Type=Application
X-DBUS-ServiceName=
X-DBUS-StartupType=none
X-KDE-SubstituteUID=false
X-KDE-Username=fitzcarraldo

The file ~/Desktop/Unmount_USBHDD01.desktop contains the following:

[Desktop Entry]
Comment[en_GB]=Unmount USB HDD with label USBHDD01
Comment=Unmount USB HDD with label USBHDD01
Exec=udisksctl unmount -b /dev/disk/by-label/USBHDD01
GenericName[en_GB]=Unmount_USBHDD01
GenericName=Unmount_USBHDD01
Icon=media-eject
MimeType=
Name[en_GB]=Unmount_USBHDD01
Name=Unmount_USBHDD01
Path=
StartupNotify=true
Terminal=false
TerminalOptions=
Type=Application
X-DBUS-ServiceName=
X-DBUS-StartupType=none
X-KDE-SubstituteUID=false
X-KDE-Username=fitzcarraldo

(N.B. Since I could not find a media-unmount icon, I have used the media-eject icon to represent Unmount.)

This is not perfect in the sense that the device will still disappear from Device Notifier if you click on the Eject icon in Device Notifier. But at least I can avoid doing that until I really do want to unplug the device from my laptop. In other cases I simply double-click on the Mount_USBHDD01 icon and Unmount_USBHDD01 icon on my Desktop to mount and unmount the USB device as many times as I need to.

HEIC image files in Linux

I was at an event recently where the attendees were asked to upload their camera and smartphone photos and videos to a shared Google Drive folder. Some of the uploaded photo files have a .HEIC (High Efficiency Image Container) extension, which I had not come across before. I have since learnt that these HEIC files were produced by iPhones running iOS 11, encoded using the HEIF (High Efficiency Image File) format. Apparently the HEIF format is superior to the JPEG format in a number of ways (see the links at the end of my post, especially the image examples given by Nokia), although it is subject to patents and therefore I believe there are certain constraints to coding image files in HEIC format. Anyway, I’ll leave you to read the fine print. My interest was simply because I wanted to be able to download the above-mentioned photo files and view them all in the file managers and image-viewing applications in Linux and Android on my various devices.

Now, I can browse and view the above-mentioned shared HEIC images in Google Drive in the Firefox and Chrome browsers in Linux, although an ownCloud site viewed using the same browsers displays the HEIC files as grey icons that can only be downloaded, not opened and viewed in the browser. I also found that Cirrus, the Android app for ownCloud that I use on my Galaxy Note 8 phone, cannot display HEIC photos either.

I downloaded the HEIC files to a machine running Lubuntu 18.04 and to a machine running Gentoo Linux. The file manager PCManFM in Lubuntu 18.04 displays grey icons rather than thumbnails for these HEIC files, and KDE’s Dolphin 18.08.3 file manager in Gentoo Linux displays green image icons rather than thumbnails for them. As far as Linux image viewers go, in Lubuntu 18.04 I find that GPicView 0.2.5 and Geeqie 1.4 cannot display HEIC images, and in Gentoo Linux KDE I find that GQview 2.1.5-r1, Okular 18.08.3 and Gwenview 18.08.3 cannot display HEIC images. So I set about converting all the HEIC files to JPG files. I managed to do this but needed to use a range of tools, as illustrated by a couple of examples below for Lubuntu 18.04 and Gentoo Linux. This post might seem long-winded but perhaps may be of help to Linux users coming across .HEIC files for the first time.

From the .HEIC files I had downloaded I picked one at random to try and convert to a JPG file: IMG_3706.HEIC. Its EXIF data confirms it is an HEIC file:

user $ exiftool IMG_3706.HEIC | grep "File Type"
File Type                       : HEIC
File Type Extension             : heic
user $ exiftool IMG_3706.HEIC | grep "Camera Model"
Camera Model Name               : iPhone 7 Plus

Several of the files with the .HEIC suffix that I downloaded were not real HEIC files according to their EXIF data:

user $ exiftool IMG_9474.HEIC | grep "File Type"
File Type                       : JPEG
File Type Extension             : jpg
user $ exiftool IMG_9474.HEIC | grep "Camera Model"
Camera Model Name               : iPhone 8

Those files were apparently treated as JPEG files by the tools I mention below, so I have omitted the results for those ‘false’ HEIC files.

Lubuntu 18.04

1. I installed the libheif example tools:

user $ sudo apt install libheif-examples

2. I used the heif-info command to check the file:

user $ heif-info IMG_3706.HEIC 
image: 3024x4032 (id=49), primary
  thumbnail: 240x320
  alpha channel: no
  depth channel: no

3. I tried to convert the file using the heif-convert command:

user $ heif-convert IMG_3706.HEIC IMG_3706.jpg
File contains 1 images
Written to IMG_3706.jpg

4. Apparently Imagemagick >=7.0.7-22 compiled with --with-libheif is supposed to be able to convert HEIC files to JPG. Anyway, I tried to convert the file using the current version of Imagemagick in Lubuntu 18.04 (the current package version is 8:6.9.7.4+dfsg-16ubuntu6.4):

user $ convert IMG_3706.HEIC IMG_3706a.jpg
convert-im6.q16: no decode delegate for this image format `HEIC' @ error/constitute.c/ReadImage/504.
convert-im6.q16: no images defined `IMG_3706a.jpg' @ error/convert.c/ConvertImageCommand/3258.

5. Apparently the GIMP >=2.10.2 supports HEIF by using heif-gimp-plugin. Anyway, I tried to open the file with the current version of the GIMP in Lubuntu 18.04 (the current package version is 2.8.22-1). The GIMP launches and pops-up a window with the title ‘GIMP Message’ containing the following message and an ‘OK’ button:

GIMP Message
Opening /home/fitzcarraldo/IMG_3706.HEIC’ failed: Unknown file type

6. I used the online tool ‘libheif decoder demo’ (https://strukturag.github.io/libheif/) in a browser window. This can load the file IMG_3706.HEIC (‘Browse…’ button) and convert it (‘Save image…’ button) to IMG_3706.jpeg.

Gentoo Linux with KDE 5

1. I installed the libheif example tools implicitly by re-merging Imagemagick with USE="heif", which installs libheif.

root # cat /etc/portage/package.use/imagemagick 
media-gfx/imagemagick heif
root # emerge imagemagick

2. I used the heif-info command to check the file:

user $ heif-info IMG_3706.HEIC  
image: 3024x4032 (id=49), primary
  thumbnail: 240x320
  alpha channel: no
  depth channel: no

3. I tried to convert the file using the heif-convert command:

user $ heif-convert IMG_3706.HEIC IMG_3706.jpg
File contains 1 images
Written to IMG_3706.jpg

4. I tried to convert the file using Imagemagick >=7.0.7-22 compiled with --with-libheif (Imagemagick merged with USE="heif"):

user $ convert IMG_3706.HEIC IMG_3706a.jpg
user $

So Imagemagick 7.0.8.16 in Gentoo has no trouble with the file IMG_3706.HEIC.

5. I tried to open the file with the GIMP >=2.10.2, which supports HEIF using heif-gimp-plugin (GIMP >=2.10.6-r1 with USE="heif" in the case of Gentoo Linux)

First I re-merged the GIMP with the heif USE flag:

root # cat /etc/portage/package.accept_keywords/gimp
=media-gfx/gimp-2.10.8-r1 ~amd64
# required by media-gfx/gimp-2.10.8-r1::gentoo
=media-libs/libmypaint-1.3.0 ~amd64
# required by media-gfx/gimp-2.10.8-r1::gentoo
=media-gfx/mypaint-brushes-1.3.0-r1 ~amd64
# required by media-gfx/gimp-2.10.8-r1::gentoo
=media-libs/gegl-0.4.12 ~amd64
# required by media-gfx/gimp-2.10.8-r1::gentoo
=media-libs/babl-0.1.60 ~amd64
root # cat /etc/portage/package.use/gimp
media-gfx/gimp heif
root # emerge -1vp gimp

These are the packages that would be merged, in order:

Calculating dependencies... done!
[ebuild  N    ~] media-gfx/mypaint-brushes-1.3.0-r1:1.0::gentoo  2,390 KiB
[ebuild     U ~] media-libs/babl-0.1.60::gentoo [0.1.38::gentoo] USE="(-altivec)" CPU_FLAGS_X86="mmx sse sse2 sse3%* sse4_1 -f16c" 670 KiB
[ebuild  N     ] media-libs/gexiv2-0.10.8::gentoo  USE="-introspection -python -static-libs -test -vala" PYTHON_TARGETS="python2_7 python3_6 -python3_4 -python3_5" 620 KiB
[ebuild  NS   ~] media-libs/gegl-0.4.12:0.4::gentoo [0.2.0-r5:0::gentoo] USE="cairo ffmpeg introspection lcms openexr sdl svg tiff v4l -debug -jpeg2k -lensfun -libav -raw -test -umfpack -vala -webp" CPU_FLAGS_X86="mmx sse" 6,900 KiB
[ebuild  NS    ] media-libs/gegl-0.3.26:0.3::gentoo [0.2.0-r5:0::gentoo] USE="cairo ffmpeg introspection lcms openexr sdl svg tiff v4l -debug -jpeg2k -lensfun -raw -test -umfpack -vala -webp" CPU_FLAGS_X86="mmx sse" 6,378 KiB
[ebuild  N    ~] media-libs/libmypaint-1.3.0::gentoo  USE="gegl nls openmp -introspection" 428 KiB
[ebuild     U ~] media-gfx/gimp-2.10.8-r1:2::gentoo [2.8.22-r1:2::gentoo] USE="alsa heif%* mng openexr%* udev wmf -aalib (-altivec) (-aqua) -debug -doc -gnome -jpeg2k -postscript -python -smp -test -unwind% -vector-icons% -webp% -xpm (-bzip2%*) (-curl%) (-dbus%*) (-exif%*) (-jpeg%*) (-lcms%*) (-pdf%*) (-png%*) (-svg%*) (-tiff%*)" CPU_FLAGS_X86="mmx sse" PYTHON_TARGETS="python2_7" 31,206 KiB

Total: 7 packages (2 upgrades, 3 new, 2 in new slots), Size of downloads: 48,591 KiB

I then launched the GIMP and successfully opened the file IMG_3706.HEIC, and I was able to export it as IMG_3706.jpg.

6. As would be expected, the online tool ‘libheif decoder demo’ (https://strukturag.github.io/libheif/) behaves exactly the same in Gentoo Linux as it does in Lubuntu 18.04 (see earlier).

Summary

So there you have it; if the Linux file manager and/or image viewing applications you use cannot already handle HEIC files, the tools in Linux that I found may work are as follows:

  • heif-convert (from the package libheif-examples in Ubuntu/Lubuntu, or from from the package libheif in Gentoo).
  • Imagemagick (not every version).
  • The GIMP (not every version).
  • the online tool ‘libheif decoder demo’ (https://strukturag.github.io/libheif/).

I have not tried the copyright open-source code from Nokia (see link under Further Reading below), qt-heif-image-plugin and tifig (not in active development). If you have had success using another tool to convert HEIC files, please post a comment below for the benefit of other users, giving the name of the tool, the package name and version, and the Linux distribution (including release number, if not a rolling distribution).

Further reading

  1. Wikipedia – High Efficiency Image File Format
  2. Lifewire – What Are HEIF and HEIC, and Why Is Apple Using Them?
  3. Nokia – High Efficiency Image File Format (HEIF)
  4. libheif – a ISO/IEC 23008-12:2017 HEIF file format decoder and encoder
  5. askubuntu – Any app on Ubuntu to open HEIF (.heic, High Efficiency Image File Format) pictures?

Installing Dropbox in Gentoo Linux following the recent restrictions introduced for Dropbox for Linux

In a 2013 post I explained how I installed Dropbox in Gentoo Linux running KDE 4. The Dropbox company has recently imposed some restrictions in the Linux client, so this is to explain what I did to get Dropbox working again in my two Gentoo Linux installations, both using the ext4 filesystem (unencrypted) and, these days, KDE Plasma 5.

Both my laptops running Gentoo Linux had a version of Dropbox installed via the Portage package manager: dropbox-45.3.88 in the case of the laptop running Gentoo amd64, and dropbox-48.3.56 in the case of the laptop running Gentoo ~amd64. Recently a Dropbox window popped up, warning me to upgrade Dropbox to the latest version within seven days otherwise the client would no longer be able to sync with the remote Dropbox server. I also received an e-mail from the Dropbox company titled ‘[Action required] We’re updating Linux system requirements‘ informing me that the only supported Linux distributions from now on would be Ubuntu 14.04 or higher and Fedora 21 or higher, and furthermore that the client will only work on an unencrypted ext4 filesystem. As both my Gentoo installations use unencrypted ext4, I was OK on that score, but I still had the problem that an up-to-date Dropbox ebuild is not available for Gentoo and the old Dropbox versions I was using no longer sync. However, I managed to install the latest version of Dropbox (currently 55.4.171) in Gentoo, and it works fine. The Dropbox client’s icon is on the KDE Plasma 5 Panel, and the local Dropbox directory is being sync’ed correctly. Below I explain what I did.

1. I selected ‘Quit Dropbox’ from the old Dropbox client’s menu, and the Dropbox icon disappeared from the Panel.

2. I removed the Dropbox daemon from the list of script files to be started at login (‘System Settings’ > ‘Startup and Shutdown’ > ‘Autostart’).

3. I unmerged (uninstalled) the dropbox package:

clevow230ss /home/fitzcarraldo # emerge --ask --depclean dropbox

4. I deleted the directories ~/.dropbox and ~/.dropbox-dist but kept the directory ~/Dropbox and its contents.

fitzcarraldo@clevow230ss ~ $ rm -rf ~/.dropbox ~/.dropbox-dist

5. I followed the instructions under ‘Dropbox Headless install via command line‘ on the Dropbox Website to re-install the latest version of the daemon and client:

fitzcarraldo@clevow230ss ~ $ cd ~ && wget -O - "https://www.dropbox.com/download?plat=lnx.x86_64" | tar xzf -

6. I configured KDE Plasma 5 to start ~/.dropbox-dist/dropboxd at login (‘System Settings’ > ‘Startup and Shutdown’ > ‘Autostart’ > ‘Add Script…’).

7. I launched ~/.dropbox-dist/dropboxd manually from a Konsole window. The Dropbox client icon appeared on the Panel and I was prompted to login to my Dropbox account via a Web browser, as per the instructions on the Dropbox Website (see link in in Step 5):

If you’re running Dropbox on your server for the first time, you’ll be asked to copy and paste a link in a working browser to create a new account or add your server to an existing account. Once you do, your Dropbox folder will be created in your home directory.

8. I logged in to my Dropbox account via the Firefox browser. As soon as I had logged in via the browser, a message appeared in the browser window informing me that “Your computer was successfully linked to your account”, and the Dropbox client icon appeared on the Panel and showed that the contents of ~/Dropbox were being synchronised.

Everything seems to be working as before. The Dropbox icon on the Panel has the same menu items it had previously. ‘Preferences…’ shows the Dropbox version as v55.4.171. I have not ticked ‘Start Dropbox on system startup’ under Dropbox Preferences because I configured automatic startup using KDE Plasma 5 ‘System Settings’ as described in Step 6 above, and the Dropbox daemon is indeed started automatically when I login.

The Dropbox Website’s instructions (see link in Step 5) also include the following:

Download this Python script to control Dropbox from the command line. For easy access, put a symlink to the script anywhere in your PATH.

I did download that Python script and made it executable:

fitzcarraldo@clevow230ss ~/Dropbox $ chmod +x dropbox.py

However the Python 3.6 interpreter in my Gentoo Linux installations report a syntax error in the script when I run it, I assume because it was written for a different version of Python:

fitzcarraldo@clevow230ss ~/Dropbox $ ./dropbox.py 
  File "./dropbox.py", line 233
    except OSError, e:
                  ^
SyntaxError: invalid syntax

Anyway, as the Dropbox client icon is on the KDE Plasma 5 Panel and I can control Dropbox from there, I see no need for the Python script.

9. My Gentoo installations have a Bash script ~/dbox.sh that I had created to be launched by a Desktop Configuration file ~/Desktop/Dropbox.desktop with a nice icon which I double-click on if I want to relaunch the Dropbox daemon (if I previously quit Dropbox from the client’s menu, for example). I had to modify ~/dbox.sh by replacing the command ‘dbus-launch dropbox start > /dev/null‘ with the command ‘/home/fitzcarraldo/.dropbox-dist/dropboxd‘ as shown below.

dbox.sh

#!/bin/bash
notify-send 'Launching Dropbox' 'Daemon will be (re)started in 20 seconds' --icon=dialog-information
sleep 20s
ps auxww | awk '$0~/dropbox/&&$0!~/awk/{print $2}' | xargs kill
/home/fitzcarraldo/.dropbox-dist/dropboxd

Dropbox.desktop

[Desktop Entry]
Comment[en_GB]=(re)launch Dropbox daemon
Comment=(re)launch Dropbox daemon
Exec=/home/fitzcarraldo/dbox.sh
GenericName[en_GB]=Dropbox
GenericName=Dropbox
Icon=kipi-dropbox
MimeType=
Name[en_GB]=Dropbox
Name=Dropbox
Path=
StartupNotify=true
Terminal=false
TerminalOptions=
Type=Application
X-DBUS-ServiceName=
X-DBUS-StartupType=none
X-KDE-SubstituteUID=false
X-KDE-Username=fitzcarraldo

10. At the moment Dropbox is working fine again in my Gentoo installations. However, I noticed that Gentoo Linux user zsitvaij posted the following comment in a Gentoo Forums thread:

On every dropbox update, I have to remove ~/.dropbox-dist/dropbox-lnx./libdrm.so.2 to avoid having it crash on launch, works fine after until they update again.

I do not know if that will be necessary in my case, as I have not yet had to upgrade Dropbox from the Version 55.4.171 that I recently installed. When a new version of Dropbox becomes available I will update this post to confirm whether or not I had to do anything to keep Dropbox working.

Addendum (5 October 2019): With reference to my addendum of 31 August 2018, the Python script dropbox.py that can be downloaded from the Dropbox Web site has been updated and is now written in Python 3, so you can ignore my addendum of 31 August 2018.

Addendum (1 October 2018): With reference to my addendum of 2 September 2018, if you are using OpenRC it is possible to automate the deletion of the file ~/.dropbox-dist/dropbox-lnx.x86_64-/libdrm.so.2 by creating a Bash script /etc/local.d/40dropbox.start containing the following:

#!/bin/bash
if [ -e /home/fitzcarraldo/.dropbox-dist/dropbox-lnx.x86_64-*/libdrm.so.2 ]
then
    rm /home/fitzcarraldo/.dropbox-dist/dropbox-lnx.x86_64-*/libdrm.so.2
fi

Replace my username with your username, obviously. Of course the conditional test could be dispensed with and the script could just contain the shebang line and the rm line, which would still work even if the file does not exist, but it feels a bit tidier to only attempt to delete the file if it actually exists.

Addendum (2 September 2018): I have just installed Dropbox Version 56.4.94 in my Gentoo ~amd64 installation and I had to use the command shown below once in order to stop the daemon segfaulting when I entered the command ~/.dropbox-dist/dropboxd in a Konsole window:

fitzcarraldo@clevow230ss ~/Dropbox $ rm ~/.dropbox-dist/dropbox-lnx.x86_64-56.4.94/libdrm.so.2

Addendum (31 August 2018): The Python script dropbox.py that can be downloaded from the Dropbox Web site (see Step 8 above) is old, as can be seen in the comments in the header of the script:

# Dropbox frontend script
# This file is part of nautilus-dropbox 2015.10.28.

It is written in Python 2. Although I do not need to use it, I managed to get it to run in my Gentoo installations by replacing the shebang line ‘#!/usr/bin/python‘ with ‘#!/usr/bin/env python2‘. This works in my Gentoo installations because they have both Python 2.7 and Python 3.6 installed. When I now run dropbox.py I see the following:

fitzcarraldo@clevow230ss ~/Dropbox $ ./dropbox.py 
Dropbox command-line interface

commands:

Note: use dropbox help  to view usage for a specific command.

 status       get current status of the dropboxd
 throttle     set bandwidth limits for Dropbox
 help         provide help
 stop         stop dropboxd
 running      return whether dropbox is running
 start        start dropboxd
 filestatus   get current sync status of one or more files
 ls           list directory contents with current sync status
 autostart    automatically start dropbox at login
 exclude      ignores/excludes a directory from syncing
 lansync      enables or disables LAN sync
 sharelink    get a shared link for a file in your dropbox
 proxy        set proxy settings for Dropbox

fitzcarraldo@clevow230ss ~/Dropbox $ ./dropbox.py status
Up to date
fitzcarraldo@clevow230ss ~/Dropbox $ ./dropbox.py running
fitzcarraldo@clevow230ss ~/Dropbox $ ./dropbox.py filestatus ~/Dropbox/Getting\ Started.pdf 
/home/fitzcarraldo/Dropbox/Getting Started.pdf: up to date
fitzcarraldo@clevow230ss ~/Dropbox $

Notice that the command ./dropbox.py running does not return anything even though the daemon is definitely running, so I do not trust the script anyway.

Installing the Onboard on-screen keyboard in Gentoo Linux

Onboard on-screen keyboard with the Compact British English layout, Droid theme and international character selection enabled for the long-press action

Onboard on-screen keyboard configured with the British English layout, Droid theme and international character selection enabled for the long-press action



The most sophisticated and polished virtual keyboard I have seen so far in Linux is Onboard, the on-screen keyboard previously provided in Ubuntu prior to the switch to GNOME 3. The current version of Onboard is 1.4.1 and it can be installed and used in other Linux distributions and desktop environments. Thanks to Gentoo Linux user wjn an ebuild is available in the wjn-overlay overlay and can be installed from there via Portage. However, I prefer to use a local overlay so I copied the ebuild to my local overlay and installed it from there instead. Here is what I did to install app-accessibility/onboard in the Gentoo Stable installation running KDE Plasma 5 on my Clevo W230SS laptop:

1. I first made sure the preferred Python interpreter was selected (I should have done that when the Gentoo Linux developers recently replaced Python 3.5 with Python 3.6 in the default Python targets for Gentoo installations):

root # grep PYTHON /etc/portage/make.conf
PYTHON_TARGETS="python2_7 python3_6"
PYTHON_SINGLE_TARGET="python3_6"
root # eselect python list
Available Python interpreters, in order of preference:
  [1]   python2.7
  [2]   python3.5 (uninstalled)
  [3]   python3.4
  [4]   python3.6 (fallback)
root # eselect python set 4
root # eselect python list 
Available Python interpreters, in order of preference:
  [1]   python3.6
  [2]   python2.7
  [3]   python3.5 (uninstalled)
  [4]   python3.4

2. Then I copied the ebuild to my local overlay:

root # mkdir -p /usr/local/portage/app-accessibility/onboard/files
root # cd /usr/local/portage/app-accessibility/onboard/files/
root # wget https://bitbucket.org/wjn/wjn-overlay/raw/5d7fe162af7c0cde9b401a9a30fb3ab8b2b65e3d/app-accessibility/onboard/files/# onboard-1.4.1-remove-duplicated-docs.patch
root # cd ..
root # wget wget https://bitbucket.org/wjn/wjn-overlay/raw/5d7fe162af7c0cde9b401a9a30fb3ab8b2b65e3d/app-accessibility/onboard/onboard-1.4.1.ebuild
root # ebuild onboard-1.4.1.ebuild manifest

3. As I am using using Gentoo Stable I unmasked the ebuild by keyword:

root # nano /etc/portage/package.accept_keywords/onboard
root # cat /etc/portage/package.accept_keywords/onboard
=app-accessibility/onboard-1.4.1 **

4. Then I installed the package:

root # emerge onboard
root # eix onboard
[I] app-accessibility/onboard [1]
     Available versions:  (~)1.4.1^m {PYTHON_TARGETS="python3_5 python3_6"}
     Installed versions:  1.4.1^m(15:28:57 25/06/18)(PYTHON_TARGETS="python3_6 -python3_4 -python3_5")
     Homepage:            https://launchpad.net/onboard
     Description:         Onscreen keyboard for everybody who can't use a hardware keyboard

[1] "local_overlay" /usr/local/portage

Icons for Onboard and Onboard Settings were added to the KDE Application Launcher’s menu (Applications > Utilities) and they can be launched from there or by entering the command ‘onboard‘ in a Konsole window under the user’s account.

5. The only thing that did not work ‘out of the box’ in KDE Plasma 5.12.5 in Gentoo was selecting ‘Help’ from the pop-up menu displayed by clicking on the Onboard icon on the Plasma 5 Panel:

FileNotFoundError: [Errno 2] No such file or directory: ‘/usr/bin/yelp’: ‘/usr/bin/yelp’

This was simply because the package gnome-extra/yelp had not been installed in my KDE installation. Now, I could have just installed it separately:

root # emerge yelp

but I chose intead to edit the onboard ebuild to add yelp to the list of runtime dependencies:

RDEPEND="${COMMON_DEPEND}
        app-accessibility/at-spi2-core
        app-text/iso-codes
        gnome-extra/mousetweaks
        gnome-extra/yelp
        x11-libs/libxkbfile"

and I then re-installed the package, which then automatically installed yelp and its dependencies:

root # ebuild onboard-1.4.1.ebuild manifest
root # emerge onboard

Onboard is a nice utility, and I hope its developers continue to maintain and develop it even though Ubuntu now uses the GNOME 3 on-screen keyboard instead, as it can be used in other desktop environments and in other Linux distributions.

Gentoo Linux: A work-around to be able to Resume from Suspend to RAM when using the NVIDIA closed-source driver

My Clevo W230SS laptop has NVIDIA Optimus graphics hardware (NVIDIA GPU plus Intel IGP). I do not use Bumblebee, preferring to switch between the Intel video driver and the NVIDIA closed-source driver myself (see Switching between Intel and NVIDIA graphics processors on a laptop with NVIDIA Optimus hardware running Gentoo Linux). The laptop can suspend to RAM and resume perfectly when using the Intel video driver (but see Stopping my laptop spontaneously resuming immediately after Suspend to RAM, which is applicable whatever the GPU or IGP).

In order to be able to resume properly from Suspend-to-RAM when using the NVIDIA driver, the laptop needs to disable compositing before suspending, then re-enable compositing after resuming. For how I achieve that, see under Problem 2 in the third link above. If this is not done, the graphics on the Desktop are corrupted after resuming.

However, recently when using the NVIDIA driver and KDE Plasma 5 (I am currently using nvidia-drivers-387.22 and plasma-meta-5.11.5), when resuming from suspension the monitor would briefly display the LightDM wallpaper (I use different wallpapers for the display manager and the lock screen, so I know it was not the KDE lock screen) followed by a blank screen with a mouse pointer (which I could move normally). More recently, in between displaying the display manager’s wallpaper and the blank screen, the monitor would briefly display an earlier image of the Desktop just before the laptop suspended.

Now, I could simply leave the laptop configured to use the Intel driver. However, sometimes I need to use a CAD application and the performance is better when using the NVIDIA GPU.

There are umpteen posts on the Web about this problem, and the root cause seems to be the closed-source NVIDIA driver. I have seen the KDE lock screen mentioned in some posts as the culprit, so I disabled the lock screen (‘System Settings’ > ‘Desktop Behaviour’ > ‘Screen Locking’) but that did not solve the problem.

I put up with this for several weeks in the hope that the next release of the NVIDIA driver would fix the problem. If I suspended to RAM while the laptop was using the NVIDIA driver, I was able to resume and get to a working Desktop – albeit without the open windows and applications that had been running before suspending – by pressing Ctrl+Alt+F1 to get to TTY1, logging in as the root user and entering the command ‘/etc/init.d/xdm restart‘. However, the final straw was in a meeting a couple of weeks ago when I wanted to resume the laptop and show a worksheet to someone. The laptop monitor of course displayed a blank screen with a mouse pointer, and it took me a couple of minutes to restart the display manager, login to KDE Plasma 5 and open the spreadsheet again. So this week I decided to look into the problem to see if I could at least find a work-around that would enable the laptop to resume without needing to restart X Windows and login to Plasma 5 each time.

I created a Bash script in /etc/pm/sleep.d/ to unload the NVIDIA modules before suspending to RAM and to re-load them when resuming, but that did not solve the problem either.

I switched the rendering background from OpenGL 2.0 to OpenGL 3.1 (‘System Settings’ > ‘Display and Monitor’ > ‘Compositor’), but that did not work either. I switched the rendering backend to XRender, and that did enable the laptop to resume from suspend successfully with the NVIDIA driver, but I do not want to use that work-around. Firstly, with software rendering there is a performance hit, and, secondly, there was no KDE Desktop Cube when using XRender instead of OpenGL. I use the Desktop Cube when working, as I often have a lot of windows open on each virtual desktop (cube side), and I find it easier to use the cube than a flat UI.

Eventually I found that, after resuming, if I pressed Ctrl+Alt+F1 to get to a virtual console, logged into my user account, entered the command ‘DISPLAY=:0 /usr/bin/kwin_x11 --resume‘ and then pressed Ctrl+Alt+F7 to get back to TTY7, my Desktop would appear on TTY7. Even so, I noticed on TTY1 that the following error messages were displayed when I ran that command:

kwin_core: OpenGL 2 compositing setup failed
kwin_core: Failed to initialize compositing, compositing disabled

Anyway, the Plasma 5 Desktop was displayed on TTY7, and with the windows that were open when I suspended the laptop, so restarting KWin would at least be a viable work-around until NVIDIA fix their video driver.

I incoporated the command in my script /etc/pm/sleep.d/02-toggle-compositing like so:

#!/bin/sh
#
# Turn off compositing on hibernate or suspend
# Turn on compositing on thaw or resume

username=fitzcarraldo
userhome=/home/$username
export XAUTHORITY="$userhome/.Xauthority"
export DISPLAY=":0"

case "$1" in
     suspend|hibernate)
          su $username -c "qdbus org.kde.KWin /Compositor suspend" &
     ;;
     resume|thaw)
          su $username -c "qdbus org.kde.KWin /Compositor resume" &
          su $username -c "/usr/bin/kwin_x11 --replace" &
     ;;
     *)
          exit $NA
     ;;
esac

It is an ugly hack, but at least now the laptop can resume properly from Suspend-to-RAM while the NVIDIA driver is being used.

Perhaps Linus Torvalds was correct. I will try to avoid NVIDIA hardware when I replace my current laptop.

xdotool comes to the rescue

In a previous post I explained how I implemented a method for adding my current location and the local time to my e-mail signature wherever I happen to be in the World, irrespective of the time on the laptop’s hardware clock and system clock. In that post I described how I created a keyboard shortcut using the Linux application AutoKey. Unfortunately AutoKey has not been updated for several years and no longer works properly in KDE Plasma 5 on my laptops. Therefore I decided to replace it with a KDE keyboard shortcut, and this is to explain how I did it.

First create a custom shortcut in KDE:

  1. ‘System Settings’ > ‘Shortcuts’ > ‘Custom Shortcuts’
  2. ‘Edit’ > ‘New’ > ‘Global Shortcut’ > ‘Command/URL’, and name the New Action ‘Insert current time’
  3. On the Comment pane for ‘Insert current time’, add the comment ‘Insert current time at specified location’ (without the quotes)
  4. On the Trigger pane, configure the shortcut to be Ctrl+Alt+Space
  5. On the Action pane, enter the Command/URL as ‘/home/fitzcarraldo/timezone_signature_GeoNames.sh‘ (without the quotes)
  6. Click ‘Apply’

Next modify the Bash script timezone_signature_GeoNames.sh so that it contains the following (obviously change the username and path to suit):

#!/bin/bash

place=$(kdialog --title "Current Location" --inputbox "Enter your location:")

placetime=$(perl /home/fitzcarraldo/now1.pl $place)

# xdotool does not output a space in a string, so we have to extract each field from the string
# and print each field individually, separated by a space character.

city=$(echo $placetime | awk -F "|" '{print $1}')
country=$(echo $placetime | awk -F "|" '{print $2}' | sed 's/[)(]//g')
region=$(echo $placetime | awk -F "|" '{print $4}')

datetime=$(/usr/bin/zdump $region | awk -F " " '{print $2" "$3" "$4" "$5" "$6" "$7}')
dayofweek=$(echo $datetime | awk -F " " '{print $1}')
month=$(echo $datetime | awk -F " " '{print $2}')
day=$(echo $datetime | awk -F " " '{print $3}')
time=$(echo $datetime | awk -F " " '{print $4}')
year=$(echo $datetime | awk -F " " '{print $5}')
timezone=$(echo $datetime | awk -F " " '{print $6}')

activewindow=$(xdotool getactivewindow)

xdotool type --window $activewindow "Sent from:"
for oneword in $city; do
    xdotool key --window $activewindow space
    sleep 0.1s
    xdotool type --window $activewindow --delay 100 $oneword
done
xdotool key --window $activewindow comma
for oneword in $country; do
    xdotool key --window $activewindow space
    sleep 0.1s
    xdotool type --window $activewindow --delay 100 $oneword
done
xdotool key --window $activewindow Return
xdotool type --window $activewindow "Local time now: "
xdotool type --window $activewindow $dayofweek
xdotool type --window $activewindow " "
xdotool type --window $activewindow $month
xdotool type --window $activewindow " "
xdotool type --window $activewindow $day
xdotool type --window $activewindow " "
xdotool type --window $activewindow $time
xdotool type --window $activewindow " "
xdotool type --window $activewindow $year
xdotool type --window $activewindow " "
if [ ${timezone:0:1} = "-" ]; then
    timezone="UTC-"${timezone#*-}
elif [ ${timezone:0:1} = "+" ]; then
    timezone="UTC+"${timezone#*+}
fi
xdotool type --window $activewindow $timezone
xdotool type --window $activewindow " "
xdotool key --window $activewindow Return
xdotool key --window $activewindow Return
echo

The Perl script now1.pl is listed in my my earlier post. Notice that the script timezone_signature_GeoNames.sh in my earlier post was much simpler. This was because the AutoKey shortcut took care of sending the text to the currently active window. Without AutoKey, I now had to do this myself in the script timezone_signature_GeoNames.sh, and the command xdotool came to the rescue. The developer explains what xdotool does as follows:

This tool lets you simulate keyboard input and mouse activity, move and resize windows, etc. It does this using X11’s XTEST extension and other Xlib functions.

Additionally, you can search for windows and move, resize, hide, and modify window properties like the title. If your window manager supports it, you can use xdotool to switch desktops, move windows between desktops, and change the number of desktops.

So I installed xdotool via the Gentoo package manager:

# emerge xdotool
# eix xdotool
[I] x11-misc/xdotool
     Available versions:  3.20150503.1-r1^t ~3.20160805.1^t {examples}
     Installed versions:  3.20150503.1-r1^t(22:51:30 02/04/17)(-examples)
     Homepage:            http://www.semicomplete.com/projects/xdotool/
     Description:         Simulate keyboard input and mouse activity, move and resize windows

Anyway, my Bash script using xdotool works a treat with Thunderbird (and KWrite, LibreOffice Writer, etc.). I used to experience a problem with certain characters, for example a colon was printed as a semi-colon (see the xdotool bug report xdotool writes the wrong case #121), but that no longer happens in my current KDE Plasma 5 installation:

Sent from: Galeão International Airport, Brazil
Local time now: Thu Jul 6 15:11:40 2017 UTC-03

What a useful tool xdotool is!