<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Weblog by Lars Steinke</title><link>https://blog.lsweb.eu/</link><description>Recent posts from the blog.</description><generator>Hugo</generator><language>en</language><lastBuildDate>Sat, 31 Oct 2026 23:31:25 +0000</lastBuildDate><atom:link href="https://blog.lsweb.eu/index.xml" rel="self" type="application/rss+xml"/><item><title>How to counter vCard address book "bit rot"</title><link>https://blog.lsweb.eu/blog/how-to-counter-vcard-address-book-bit-rot/</link><pubDate>Fri, 30 Oct 2026 10:25:00 +0000</pubDate><guid>https://blog.lsweb.eu/blog/how-to-counter-vcard-address-book-bit-rot/</guid><description>&lt;p&gt;After a few years and mobile device generations the state of my address book was rather frustrating:
Starting with Nokia Symbian S60 (&lt;a href="https://sourceforge.net/projects/funambol" target="_blank" rel="noopener noreferrer"&gt;SyncML&lt;/a&gt;) over to early Android (using &lt;a href="https://www.fjsoft.at/de" target="_blank" rel="noopener noreferrer"&gt;Backups&lt;/a&gt;), on to BlackBerry 10 (Card/CalDAV &lt;a href="https://radicale.org" target="_blank" rel="noopener noreferrer"&gt;backend&lt;/a&gt;) and ultimately back to Android (using a &lt;a href="https://www.davx5.com" target="_blank" rel="noopener noreferrer"&gt;sync&lt;/a&gt; app) has introduced numerous duplications and invisible character additions by the respective address book apps (the Samsung &lt;a href="https://www.samsung.com/uk/support/mobile-devices/how-do-i-manage-my-contacts" target="_blank" rel="noopener noreferrer"&gt;Contacts&lt;/a&gt; app being the worst).&lt;/p&gt;
&lt;p&gt;In the era of agentic engineering that seemed like a good task for the &lt;a href="https://github.com/glennvdv/opencode-dockerized" target="_blank" rel="noopener noreferrer"&gt;OpenCode&lt;/a&gt; agent harness (in combination with &lt;a href="https://github.com/Niko1221/Strata" target="_blank" rel="noopener noreferrer"&gt;Strata&lt;/a&gt; as local LLM provider) to create a fix. A few iterations and testing with over 1000 contact entries yielded very promising results - so here is the &lt;a href="https://github.com/BOFH2k/vcf-cleaner" target="_blank" rel="noopener noreferrer"&gt;repo&lt;/a&gt; for anyone who might find the resulting Python script useful as well: &lt;code&gt;https://github.com/BOFH2k/vcf-cleaner&lt;/code&gt;&lt;/p&gt;</description></item><item><title>How to compare vCard address book entries</title><link>https://blog.lsweb.eu/blog/how-to-compare-vcard-address-book-entries/</link><pubDate>Fri, 06 Apr 2018 10:46:40 +0000</pubDate><guid>https://blog.lsweb.eu/blog/how-to-compare-vcard-address-book-entries/</guid><description>&lt;p&gt;Following a little mishap with the &lt;a href="https://f-droid.org/en/packages/at.bitfire.davdroid" target="_blank" rel="noopener noreferrer"&gt;DAVdroid&lt;/a&gt; app on my Fire HDX Android tablet, I ended up with a lot of duplicate contacts in my CardDAV account. Upon closer inspection I then noticed, that in the process of copying the contacts from the local contact store (on my Blackberry smartphone) to the CardDAV account, certain contact details had been lost and spurious characters (like spaces and question marks) introduced.&lt;/p&gt;
&lt;p&gt;Additionally, I had started editing the contact details for proper display in the Android contact app by Blackberry: The app does unfortunately not display the organization info provided for contacts not connected to a person (like institutions) in the address book view - contrary to that view on BlackBerry 10 before.&lt;/p&gt;</description></item><item><title>How to get Mezzanine up and running on cPanel shared hosting</title><link>https://blog.lsweb.eu/blog/how-to-get-mezzanine-up-and-running-on-cpanel-shared-hosting/</link><pubDate>Tue, 13 Feb 2018 19:15:05 +0000</pubDate><guid>https://blog.lsweb.eu/blog/how-to-get-mezzanine-up-and-running-on-cpanel-shared-hosting/</guid><description>&lt;p&gt;The follwing articles were of much use when switching this weblog from the no longer maintained &lt;a href="http://nucleuscms.org" target="_blank" rel="noopener noreferrer" title="Nucleus"&gt;Nucleus&lt;/a&gt; to &lt;a href="http://mezzanine.jupo.org" target="_blank" rel="noopener noreferrer" title="Mezzanine"&gt;Mezzanine&lt;/a&gt;, a modern blog and content management system, based on the &lt;a href="https://www.djangoproject.com" target="_blank" rel="noopener noreferrer" title="Django"&gt;Django&lt;/a&gt; web application framework and Python:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Setting up a Python virtual environment (required to be able to install local packages via &lt;code&gt;pip&lt;/code&gt;, the Python package installer):&lt;br&gt;
&lt;a href="https://web.archive.org/web/20180314215305/http://janealam.com/2017/10/06/how-to-install-virtualenv-python-for-flask-app-on-cpanel-base-shared-hosting" target="_blank" rel="noopener noreferrer" title="VEnv"&gt;http://janealam.com/2017/10/06/how-to-install-virtualenv-python-for-flask-app-on-cpanel-base-shared-hosting&lt;/a&gt; (archived)&lt;/li&gt;
&lt;li&gt;Installing Mezzanine with its dependencies (e.g. &lt;code&gt;psycopg2&lt;/code&gt; python support for the PostgreSQL database to be used as content repository):&lt;br&gt;
&lt;a href="https://www.rosslaird.com/2013/06/10/first-steps-with-mezzanine" target="_blank" rel="noopener noreferrer"&gt;https://www.rosslaird.com/2013/06/10/first-steps-with-mezzanine&lt;/a&gt; (no longer available)&lt;/li&gt;
&lt;li&gt;Running Mezzanine through the Phusion Passenger &lt;a href="https://documentation.cpanel.net/display/66Docs/66&amp;#43;Release&amp;#43;Notes#id-66ReleaseNotes-ApplicationManagerinterface" target="_blank" rel="noopener noreferrer" title="cPanel 66"&gt;Application Manager&lt;/a&gt; available in cPanel (via its &lt;a href="http://www.python.org/dev/peps/pep-3333" target="_blank" rel="noopener noreferrer" title="WSGI"&gt;WSGI&lt;/a&gt; loader):&lt;br&gt;
&lt;a href="https://help.dreamhost.com/hc/en-us/articles/215769548-Passenger-and-Python-WSGI" target="_blank" rel="noopener noreferrer" title="Passenger"&gt;https://help.dreamhost.com/hc/en-us/articles/215769548-Passenger-and-Python-WSGI&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;</description></item><item><title>Manual restore of Android databases fails</title><link>https://blog.lsweb.eu/blog/manual-restore-of-android-databases-fails/</link><pubDate>Fri, 04 Nov 2011 16:11:37 +0000</pubDate><guid>https://blog.lsweb.eu/blog/manual-restore-of-android-databases-fails/</guid><description>&lt;p&gt;As described in my earlier &lt;a href="https://blog.lsweb.eu/blog/android-firmware-updates-for-the-lg-gw620/"&gt;post&lt;/a&gt;, it is wise to create regular backups of your apps and data to SD card.&lt;/p&gt;
&lt;p&gt;This can be accomplished using &lt;code&gt;adb shell&lt;/code&gt; or the local Android terminal:&lt;br&gt;
&lt;code&gt;busybox tar cvf /mnt/sdcard/Backup/Full_`busybox date +%Y%m%d`.tar /system /data&lt;/code&gt;&lt;br&gt;
The correspondent command to for example restore your text messages would be:&lt;br&gt;
&lt;code&gt;cd /;busybox tar xvf /mnt/sdcard/Backup/Full_20111101.tar data/data/com.android.providers.telephony/databases/mmssms.db&lt;/code&gt;&lt;br&gt;
This worked fine up to Android 2.2, provided that you check file ownership and permissions afterwards, e.g.:&lt;/p&gt;</description></item><item><title>Android firmware updates for the LG GW620</title><link>https://blog.lsweb.eu/blog/android-firmware-updates-for-the-lg-gw620/</link><pubDate>Tue, 21 Jun 2011 14:36:00 +0000</pubDate><guid>https://blog.lsweb.eu/blog/android-firmware-updates-for-the-lg-gw620/</guid><description>&lt;p&gt;The OpenEtna community provides firmware updates for the GW620 phone by LG, which originally came with Android 1.5.&lt;/p&gt;
&lt;p&gt;After using the Korean Android 2.2 (Froyo) update provided by LG for a while, I then took the leap to OpenEVE Android 2.3 (Gingerbread) for usability reasons&lt;br&gt;
(2.2 was pretty laggy sometimes).&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Make a backup of your apps and data to SD card (this assumes you start off a rooted Froyo firmware with &lt;code&gt;busybox&lt;/code&gt; installed) using &lt;code&gt;adb shell&lt;/code&gt; or the local Android terminal:&lt;br&gt;
&lt;code&gt;busybox tar cvf /mnt/sdcard/Backup/Full_20110621.tar /system /data&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Reboot your device in fastboot mode (please note that mode might not be available, if you have upgraded to Froyo V20 using the offical LG KDZ updater for WIndows): Remove battery, then hook up USB cable while pressing &lt;code&gt;Menu+Space&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Backup your old boot and system images using fastboot and a recovery image: &lt;code&gt;fastboot boot gb-recovery.img&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Reset the device settings: &lt;code&gt;fastboot -w&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Flash the boot image: &lt;code&gt;fastboot flash boot boot234.img&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Flash the system image: &lt;code&gt;fastboot flash system system234.img&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Apply ZIP patches from SD card using fastboot to ClockWork Mod recovery image: &lt;code&gt;fastboot boot gb-recovery.img&lt;/code&gt;&lt;br&gt;
Apply gapps-gb-20110307-signed.zip &amp;amp; boot-gb234-110509-rndis-224mb.zip&lt;/li&gt;
&lt;li&gt;Untar your backup from SD card locally and push back data, as required, e.g.:
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;adb push contacts2.db /data/data/com.android.providers.contacts/databases 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;adb push calendar.db /data/data/com.android.providers.calendar/databases 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;adb push mmssms.db /data/data/com.android.providers.telephony/databases 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;adb push note_pad.db /data/data/org.openintents.notepad/databases 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;adb push shopping.db /data/data/org.openintents.shopping/databases
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;adb push mytracks.db /data/data/com.google.android.maps.mytracks/databases 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;adb push safe /data/data/org.openintents.safe/databases 
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;adb push database /data/data/com.timsu.astrid/databases
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&amp;hellip;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Depending on the image used, you might have to change the permissions for the files to be able to overwrite them: &lt;code&gt;chmod 666 ...&lt;/code&gt; (and back to &lt;code&gt;chmod 660 ...&lt;/code&gt; after the push). Also check that the uid/gid combination still agrees with the app directory and adjust using &lt;code&gt;busybox chown app_xy:app_xy ...&lt;/code&gt; (unless you are doing a device shell restore via &lt;code&gt;busybox tar&lt;/code&gt;, but even then the uid/gid combination might have changed for the new installation)!&lt;br&gt;
For more details please refer to the &lt;a href="https://web.archive.org/web/20120421193224/http://forum.openetna.com:80/index.php?board=1.0" target="_blank" rel="noopener noreferrer"&gt;OpenEtna&lt;/a&gt; forum.&lt;br&gt;
Infos on manual backups of Android databases may be found &lt;a href="http://wiki.dandascalescu.com/howtos/android#How_to_backup_Android_SMSes.2C_MMSes.2C_Contacts.2C_Call_Logs.2C_User_dictionary_etc._manually" target="_blank" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;</description></item><item><title>How to dual-boot Windows physically and virtually</title><link>https://blog.lsweb.eu/blog/how-to-dual-boot-windows-physically-and-virtually/</link><pubDate>Tue, 30 Nov 2010 09:22:55 +0000</pubDate><guid>https://blog.lsweb.eu/blog/how-to-dual-boot-windows-physically-and-virtually/</guid><description>&lt;p&gt;While this is no longer possible with Windows Activation Technologies in Win 7, Windows XP allows using Hardware Profiles for a shared installation that can be run either physically or virtually (e.g. using the KVM virtualization stack built into recent Linux kernels, which is a lot more convenient than VMWare Player with its kernel module dependencies, at the price of 3D graphics acceleration).&lt;/p&gt;
&lt;p&gt;The recommended sequence for such a setup:&lt;/p&gt;</description></item><item><title>How to repair an ext3 filesystem after mkdosfs format</title><link>https://blog.lsweb.eu/blog/how-to-repair-an-ext3-filesystem-after-mkdosfs-format/</link><pubDate>Thu, 05 Feb 2009 20:42:44 +0000</pubDate><guid>https://blog.lsweb.eu/blog/how-to-repair-an-ext3-filesystem-after-mkdosfs-format/</guid><description>&lt;p&gt;After shrinking a large &lt;a href="http://en.wikipedia.org/wiki/Ext3" target="_blank" rel="noopener noreferrer"&gt;ext3&lt;/a&gt; partition using gparted to make space for an additional partition, I did not take sufficient care to notice the leading partition I newly created with cfdisk subsequently was denoted as sdc2 instead of sdc1, as one might expect.&lt;/p&gt;
&lt;p&gt;Thus woe ensued when I issued a mkdosfs -F 32 /dev/sdc1 command without a closer look at the new partition numbering.&lt;/p&gt;
&lt;p&gt;So the interesting question now was, what can be salvaged from an ext3 filesystem with overwritten superblock (as well as a few of the inodes)?Luckily, the erroneous reformatting was FAT32, not ext3, which would have caused the inode block pointers to be zeroed, to quote the ext3 &lt;a href="http://batleth.sapienti-sat.org/projects/FAQs/ext3-faq.html" target="_blank" rel="noopener noreferrer"&gt;FAQ&lt;/a&gt;:&lt;br&gt;
&amp;ldquo;In order to ensure that ext3 can safely resume an unlink after a crash, it actually zeros out the block pointers in the inode, whereas ext2 just marks these blocks as unused in the block bitmaps and marks the inode as &amp;ldquo;deleted&amp;rdquo; and leaves the block pointers alone.&amp;rdquo;&lt;/p&gt;</description></item><item><title>How to boot a real harddisk in VMWare</title><link>https://blog.lsweb.eu/blog/how-to-boot-a-real-harddisk-in-vmware/</link><pubDate>Mon, 08 Jan 2007 19:53:00 +0000</pubDate><guid>https://blog.lsweb.eu/blog/how-to-boot-a-real-harddisk-in-vmware/</guid><description>&lt;p&gt;The knack is to install the VMWare SCSI driver (included with VMWare Tools) before booting the SATA or PATA harddisk.&lt;/p&gt;
&lt;p&gt;Then configure it in the VMX config file as follows:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;scsi0:0.present = &amp;#34;TRUE&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;scsi0:0.fileName = &amp;#34;win_raw.vmdk&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;scsi0:0.deviceType = &amp;#34;rawDisk&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;scsi0.present = &amp;#34;TRUE&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;scsi0.virtualDev = &amp;#34;buslogic&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Here&amp;rsquo;s the contents of &lt;code&gt;win_raw.vmdk&lt;/code&gt; for my harddrive:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;# Disk DescriptorFile
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;version=1
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;CID=adf9ef51
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;parentCID=ffffffff
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;createType=&amp;#34;fullDevice&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;# Extent description
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;RW 625142448 FLAT &amp;#34;/dev/sda&amp;#34; 0
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;# The Disk Data Base
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;#DDB
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ddb.virtualHWVersion = &amp;#34;3&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ddb.geometry.cylinders = &amp;#34;38913&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ddb.geometry.heads = &amp;#34;255&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ddb.geometry.sectors = &amp;#34;63&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ddb.geometry.biosCylinders = &amp;#34;38913&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ddb.geometry.biosHeads = &amp;#34;255&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ddb.geometry.biosSectors = &amp;#34;63&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ddb.adapterType = &amp;#34;buslogic&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ddb.toolsVersion = &amp;#34;6404&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And how to get those parameters? Exents und geometry can for instance be deduced from &lt;code&gt;hdparm /dev/sda&lt;/code&gt;:&lt;/p&gt;</description></item></channel></rss>