The Librem 5 uses GNOME Contacts to manage contacts, but it does not yet have a way to import contacts from files. I decided to fix this and create a simple application to import contacts from vcard files. This means you can now easily migrate your contacts from Android and iCloud to the Librem 5!
If you have technical problems in the Free Software world chances are others ran into it too and publicly discussed how to solve it. The Openmoko project worked on a similar problem and Ubuntu Touch users have also discussed how to sync contacts. While these aren’t complete solutions, there’s plenty of useful advice to build on.
Also, don’t forget to ask for help and feedback from others 🙂 Thank you to Jeremiah, Kyle, Richard and Mladen from the Purism team for your help on my project.
You will user the following applications on your Librem 5 to build the application:
Install the missing dependencies:
sudo apt install yad libnotify-bin syncevolution
Then let’s create a file for the app and make it executable:
touch /home/purism/bin/contacts-importer.sh
chmod a+x /home/purism/bin/contacts-importer.sh
The first thing we are going to add is the user interface to select a vcard file.
FILE=`yad --title "Import Contacts" --text="Select a VCF file to import" --file=`
Passing the –file= option to yad allows the user to select a file. The –title and –text set the window title and helper text.
If there’s an error, for example the user didn’t select a file, show an error message and exit the application.
if [ "$FILE" == "" ]; then
`yad --title "Import Contacts" --text="You did not selected any file"` exit 1
fi
If there’s no error, notify the user that the file is being imported:
notify-send -t 1000 "Import Contacts" "Importing Contacts from $FILE"
GNOME contacts uses Evolution Data Server as a backend and it can have several different contact databases. I’ve decided to import contacts into the default local system address book. To import the contacts we need to provide an address book name (“Personal”) but it changes with the system language. If PureOS is configured to use Portuguese it will be called “Pessoal”, in German “Persönlich” and so on.
To solve this we use syncevolution to list of all Evolution Data Server contacts and calendar databases, grep to filter the list and sed to clean the result and store the correct name in CONTACTDB.
CONTACTDB=$(syncevolution --print-databases | grep "system-address-book" | sed 's#(.*##' | sed 's# ##g' )
We use the file command to get the mimetype of the user’s file, and if it is not equal to text/vcard we display an error message and exit the application.
MIMETYPE=$(file --mime-type -b $FILE)
CONTROL="text/vcard"
if [[ "$MIMETYPE" != "$CONTROL" ]]; then
notify-send -t 1000 "File is not a vcard! Bye!" && exit 1
fi
Unfortunately syncevolution
has an issue processing vcard files with multiple contacts not separated with new lines. To workaround this we will break a vcard into multipe vcard files each with a single contact.
It is good practice to create temporary files under the /tmp directory rather than the user’s HOME directory, you don’t want to risk modifying a user’s personal files!
TEMP=$(mktemp -d -t contacts-importer-XXXXXXXXXXXXX-$(date +%Y-%m-%d-%H-%M-%S))
In our temporary directory we use cat to read the vcard file $FILE and awk to search and split each vcard (beginning with “BEGIN:VCARD”) and save it to a file “card_import_L5_n” where n is the contact number.
cd $TEMP
cat $FILE | awk ‘ /BEGIN:VCARD/ { ++a; fn=sprintf(“card_import_L5_%02d.vcf”, a); print “Writing: “, fn } { print $0 » fn; } ‘ $1
Now all we have to do is loop over and import the multiple vcard files:
for f in $TEMP/card_import_L5*
do syncevolution --import ${f%} backend=evolution-contacts database=${CONTACTDB}
done
To finish off, we check if the import was successful and notify the user.
if [ $? -eq 0 ] then
notify-send "Successful import";
exit 0
else
notify-send "Error" >&2
exit 1
fi
#!/bin/bash -e
# Original Script: https://www.isticktoit.net/?p=1536
# Adapted for the L5 use case with gnome-contacts
#Selecting a file
FILE=`yad --title "Import Contacts" --text="Select a VCF file to import" --file=`
if [ "$FILE" == "" ]; then
`yad --title "Import Contacts" --text="You did not selected any file"` exit 1
fi
notify-send -t 1000 "Import Contacts" "Importing Contacts from $FILE"
#Name of the database where the contacts will be imported to.
CONTACTDB=$(syncevolution --print-databases | grep "system-address-book"| sed 's#(.*##' | sed 's# ##g' )
#Temp directory to mess with files:
TEMP=$(mktemp -d -t contacts-importer-XXXXXXXXXXXXX-$(date +%Y-%m-%d-%H-%M-%S))
#Some control info to make sure the file is a vcard
MIMETYPE=$(file --mime-type -b $FILE)
CONTROL="text/vcard"
if [[ "$MIMETYPE" != "$CONTROL" ]]; then
notify-send -t 1000 "File is not a vcard! Bye!" && exit 1
fi
#Begin importing contacts
cd $TEMP
cat $FILE | awk ' /BEGIN:VCARD/ { ++a; fn=sprintf("card_import_L5_%02d.vcf", a); print "Writing: ", fn } { print $0 >> fn; } ' $1
for f in $TEMP/card_import_L5*
do syncevolution --import ${f%} backend=evolution-contacts database=${CONTACTDB}
done
if [ $? -eq 0 ]
then
notify-send "Successful import";
exit 0
else
notify-send "Error" >&2
exit 1
fi
Following Kyle’s lead in his Flashlight App and Screenshot App tutorial let’s make our app easier to use by adding a Desktop Entry.
Create the Desktop Entry file:
touch /home/purism/.local/share/applications/contacts-importer.desktop
Then add the following content:
[Desktop Entry]
Name=Contacts Importer
Type=Application
Icon=preferences-desktop-personal
Exec=contacts-importer.sh
Categories=Utility;
Your app will now have convenient icon in the app drawer.
The Librem 5 runs pretty much the same software stack as regular PureOS which means our app will run on most GNU/Linux systems. Let’s see what it looks like on a Librem laptop running PureOS:
With only 25 lines of bash (and a desktop entry) we created a complete application with error handling and notifications that runs on desktop and mobile Linux. This is the power of the Librem 5, a fully-featured desktop GNU/Linux ecosystem in your pocket!
Purism believes building the Librem 5 is just one step on the road to launching a digital rights movement, where we—the-people stand up for our digital rights, where we place the control of your data and your family’s data back where it belongs: in your own hands.