Latest weblog entries

2017-05-09 Check PDF file header with Swift

Here's a little Swift playground that shows how you can check whether a Data object (for example from a file) is a PDF. It's done by checking the first couple of bytes.

    import UIKit
    func dataWithHexString(hex: String) -> Data {
        var hex = hex
        var data = Data()
        while(hex.characters.count > 0) {
            let c: String = hex.substring(to: hex.index(hex.startIndex, offsetBy: 2))
            hex = hex.substring(from: hex.index(hex.startIndex, offsetBy: 2))
            var ch: UInt32 = 0
            Scanner(string: c).scanHexInt32(&ch)
            var char = UInt8(ch)
            data.append(&char, count: 1)
        return data
    struct HeaderError: Error {
    let smallestPDFasHex = "255044462D312E0D747261696C65723C3C2F526F6F743C3C2F50616765733C3C2F4B6964735B3C3C2F4D65646961426F785B302030203320335D3E3E5D3E3E3E3E3E3E"
    let data = dataWithHexString(hex: smallestPDFasHex)
    let headerRange: Range<Data.Index> = 0..<4
    let header = data.subdata(in: headerRange)
    guard let headerString = String(data: header, encoding: .ascii) else {
        print("Header not found")
        throw HeaderError()
    if headerString == "%PDF" {
        print("It's a PDF")
    } else {
        print("It's NOT a PDF")

2017-04-11 UIStackView playground

Here's a nice way to play with a UIStackView. Copy and paste the following code into a playground, and next to the final line, click the screen icon to permanently show it. Then adjust the parameters of the playground where necessary.

    import UIKit
    var view = UIView(frame: CGRect(x: 0, y: 0, width: 300, height: 300))
    view.backgroundColor = UIColor.yellow
    let label1 = UILabel()
    label1.text = "label 1"
    let label2 = UILabel()
    label2.text = "label 2"
    let spacer1 = UIView()
    spacer1.backgroundColor =
    spacer1.translatesAutoresizingMaskIntoConstraints = false
    spacer1.widthAnchor.constraint(equalToConstant: 3).isActive = true
    let spacer2 = UIView()
    spacer2.backgroundColor = UIColor.gray
    let stackView = UIStackView(arrangedSubviews: [label1, spacer1, label2, spacer2])
    stackView.distribution = .fill
    stackView.axis = .horizontal
    stackView.translatesAutoresizingMaskIntoConstraints = false
    stackView.spacing = 20
    stackView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
    stackView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
    stackView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
    stackView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true

The result should look something like this:

uistackview playground 2017-04-11.png

2017-04-07 Stopping autoplaying videos

There's a larger and larger number of websites that auto-play completely unrelated videos when opening a page on their website. In my opinion, a very user unfriendly business.

Thankfully Firefox has an extension for this, FlashStopper:

Before and after installing, open for example this page on the Reuters website:

2017-04-04 UITextView with placeholders

For my current project, the user needs to select a template from a list. The template contains a number of placeholders where text needs to be filled in, and further editing needs to be done.

I've created an example Xcode project on GitHub which shows how this can be done:

2017-02-21 Linux VPS with TeamViewer

Here are my short notes on creating a Linux VPS (virtual private service) which can be remotely accessed via TeamViewer. I prefer TeamViewer over other ways of remotely accessing a desktop, because it works cross-platform and through NAT and firewalls.

The big problem is often that a Linux VPS doesn't have a virtual graphical card. For remote access to the GUI, most VPS providers advise VNC while I prefer TeamViewer.

I've tried a number of Linux distributions on a number of VPS providers. The instructions below fail on VPSes at Scaleway or DigitalOcean, but the combination of Fedora 25 and Linode or Vultr made this all very easy.

First of all, register or log in at Linode or Vultr, and create a VPS. You'll need at least 1 GB of memory.

After it's started, log in via SSH as root and do the following:

  # yum -y groupinstall "Fedora Workstation"

Then get the TeamViewer download URL and install the package:

  # wget ""
  # yum -y install ./teamviewer.i686.rpm

Next reboot, make sure the GUI starts:

  # systemctl set-default

If your VPS runs at Vultr, disable Wayland. Edit the file /etc/gdm/custom.conf and remove the comment for the line WaylandEnable=false so GDM uses Linode already has this correctly set.

Then, add a user for yourself:

  # useradd -m -U mynewusername
  # passwd mynewusername

Add the new user to the sudoers, and reboot:

  # visudo
  # reboot

If you're on Linode, open remote access via glish, which is Linode's way of giving you graphical access to your VPS, through your browser. Log into the Linode management console, click on the node, then in the tab Remote Access, click the link "Launch Graphical Web Console".

If you're on Vultr, open remote access by navigating to the Instances tab in the management console, then click the three dots at the right of your server and in the menu, click "View Console":

vultr 2017-02-21.png

You should see the graphical Linux login screen. In the top left corner, set shell to "Gnome Xorg" (this is important!) and then continue to log into Gnome.

Linode login 2017-02-21.png

In Gnome, start TeamViewer. Check the three boxes to enable remote access. You'll need to provide TeamViewer username/password, as well as click the link in the email you'll get, to confirm adding this VPS to your TeamViewer device list.


Note: a current disadvantage is that you're constricted to pretty low resolutions. On Linode, you can't set the resolution to something bigger than 1280x768. On Vultr, the maximum is 1280x1024.


Weblog Archive

Weblog entries 2017

Weblog entries 2016

Weblog entries 2015

Weblog entries 2014

Weblog entries 2013

Weblog entries 2012

Weblog entries 2011

Weblog entries 2010

Weblog entries 2009

Weblog entries 2008

Weblog entries 2007

Weblog entries 2006

Weblog entries 2005

Weblog entries 2004

All weblog entries


Articles, chronologically (latest first). This is pretty old stuff.


Not yet finished. Maybe will never be finished. Maybe they'll get deleted. Who knows?


System administration: