Little Britain

Little Britain is an amalgamation of the terms ‘Little England‘ and ‘Great Britain’, and is also the name of a Victorian neighbourhood and a modern street in London. Says Wikipedia. It’s also what I think will remain of Great Britain in a few years. Maybe defacto already in a few days or weeks. But okay.

This is not a big problem. More serious problems are geopolitical. I do think Russia will gain from not having England (in the end not Great Britain, but just England) in the European Union: it’ll make the UK’s (or England’s) voice in NATO sound less part of one block. To remain significant will the EU block have to find a new way.

I propose to form a European military. Initially make NATO part of it. The idea would be that each country in Western Europe can join this military alliance based on negotiated contribution criteria. Let’s learn from our mistakes and allow countries to leave and be kicked out: Especially if a country doesn’t contribute enough to the alliance, it should be kicked out (temporarily).

That allows for England or Little Britain to keep its geopolitical relevance, yet allows for the EU member states to exchange economy-currency into military-currency and vice versa. Let’s show some European teeth. But let’s also remain calm and intelligent.

Meanwhile we can slow down NATO becoming a geopolitical playball against Russia. This Cold-War 2.0 nonsense isn’t benefiting world peace. Keeping the world of humans in as much peace as possible should nowadays be NATO’s only goal. I hope there is still some time before any big war starts, to stop it from happening at all. We have so much technology, happiness and growth to give to the world of humans. Let us not waste it in a big stupid worldwide conflict.

 

 

Experimentieel artikeltje over economie

Een consument kan zijn geld maar één keer uitgeven. Maar men geeft het wel uit onderheving aan inflatie. Dit wil zeggen dat wanneer we een goed kochten in juni 2006, bv. een auto, dat het uitgegeven geld, volgens de EUCPI2005 index, zo’n 17,95% goedkoper is in 2016. Louter op basis van inflatie. Dit was zo tijdens een decennium met jaren van quasi deflatie (= ongezien). Toch halen we bijna 18% waardevermindering op tien jaar.

Wat gebeurt er economisch wanneer de consument betaalt met privacy? Men zal in de toekomst immers een deel van de auto betalen d.m.v. privacy op te geven: de prijs van die wagen zal dalen precies omdat allerlei organizaties zich gaan bezig houden met locatiedata van de consument (en weet ik veel wat nog allemaal). De consument betaalt dat deel met wat ik privacy-currency zal noemen.

Mijn eigen inzicht is dat een privacy-currency weliswaar meervoudig uitgegeven wordt; oude gegevens worden steeds minder waard. Maar diensten die met privacy-currency werken hebben vaak een langdurige stroom bij haar consument bemachtigd. Daarmee bedoel ik dat het over een sensor gaat (een smartphone met pervasieve app, een thermostaat die jaren aan de muur hangt, een digicorder die dankzij monopolie jaren lang TV-kijkgewoontes vastlegt) die niet éénmalig maar wel steeds weer dezelfde consumentenprivacy “verkoopt” aan het bedrijf.

Zo’n sensor kan slechts enkelmalig geïnstalleerd worden. Want de markt zorgt ervoor dat een privacygegeven zo goedkoop mogelijk geëxtraheerd wordt. Vijf keer vastleggen wat de TV-kijkgewoontes van een consument zijn, heeft in de markt geen nut: de markt zal de efficiëntste verkiezen. Die zal het aan de anderen verkopen.

Dit wil voor mij zeggen dat privacy-currency in inflatie zal gaan. De currency wordt steeds minder waard. De installatie van een sensor heeft nu een zekere prijs (je moet je dwaze product aan de man brengen), maar zal in de toekomst steeds minder opbrengen.

Voorts kost het voor de consument steeds meer om zijn of haar privacy op te geven: men verliest opties bij verzekeringen, men verliest werkgelegenheid, men verliest vriendschappen en zal gepest of aangesproken worden. Typisch zijn oudere mensen dan ook meer gesteld op hun privacy. Ze verkopen hun privacy steeds duurder. Hun ongeletterdheid in technologie ontwijkt dit nog even; maar iedereen weet dat dat van korte duur is.

Dit geeft dat er twee vectoren zijn die de privacy-currency in inflatie doet gaan: de markt maakt een sensor minder veel waard uit efficiëntieoverweging, en de consument maakt een sensor minder wenselijk door een kleine maar niet onbestaande vergroting van kennis in technologie (en haar kwalen).

Bedrijven die hun waarde in de vermeerdering van privacy-currency leggen, zullen op middellange termijn failliet gaan. Want zelfs geld is een betere focus. De financiële sector heeft het traditioneel dan ook goed.

MVVM, Model View ViewModel, with Qt and QML

In the XAML world it’s very common to use the MVVM pattern. I will explain how to use the technique in a similar way with Qt and QML.

The idea is to not have too much code in the view component. Instead we have declarative bindings and move most if not all of our view code to a so called ViewModel. The ViewModel will sit in between the actual model and the view. The ViewModel typically has one to one properties for everything that the view displays. Manipulating the properties of the ViewModel alters the view through bindings. You typically don’t alter the view directly.

In our example we have two list-models, two texts and one button: available-items, accepted-items, available-count, accepted-count and a button. Pressing the button moves stuff from available to accepted. Should be a simple example.

First the ViewModel.h file. The class will have a property for ~ everything the view displays:

#ifndef VIEWMODEL_H
#define VIEWMODEL_H

#include <QAbstractListModel>
#include <QObject>

class ViewModel : public QObject
{
	Q_OBJECT

	Q_PROPERTY(QAbstractListModel* availableItems READ availableItems NOTIFY availableItemsChanged )
	Q_PROPERTY(QAbstractListModel* acceptedItems READ acceptedItems NOTIFY acceptedItemsChanged )
	Q_PROPERTY(int available READ available NOTIFY availableChanged )
	Q_PROPERTY(int accepted READ accepted NOTIFY acceptedChanged )
public:

	ViewModel( QObject *parent = 0 );
	~ViewModel() { }

	QAbstractListModel* availableItems()
		{ return m_availableItems; }

	QAbstractListModel* acceptedItems()
		{ return m_acceptedItems; }

	int available ()
		{ return m_availableItems->rowCount(); }

	int accepted ()
		{ return m_acceptedItems->rowCount(); }

	Q_INVOKABLE void onButtonClicked( int availableRow );

signals:
	void availableItemsChanged();
	void acceptedItemsChanged();
	void availableChanged();
	void acceptedChanged();

private:
	QAbstractListModel* m_availableItems;
	QAbstractListModel* m_acceptedItems;
};

#endif

The ViewModel.cpp implementation of the ViewModel. This is of course a simple example. The idea is that ViewModels can be quite complicated while the view.qml remains simple:

#include <QStringListModel>

#include "ViewModel.h"

ViewModel::ViewModel( QObject *parent ) : QObject ( parent )
{
	QStringList available;
	QStringList accepted;

	available << "Two" << "Three" << "Four" << "Five";
	accepted << "One";

	m_availableItems = new QStringListModel( available, this );
	emit availableItemsChanged();

	m_acceptedItems = new QStringListModel( accepted, this );
	emit acceptedItemsChanged();
}

void ViewModel::onButtonClicked(int availableRow)
{
	QModelIndex availableIndex = m_availableItems->index( availableRow, 0, QModelIndex() );
	QVariant availableItem = m_availableItems->data( availableIndex, Qt::DisplayRole );

	int acceptedRow = m_acceptedItems->rowCount();

	m_acceptedItems->insertRows( acceptedRow, 1 );

	QModelIndex acceptedIndex = m_acceptedItems->index( acceptedRow, 0, QModelIndex() );
	m_acceptedItems->setData( acceptedIndex, availableItem );
	emit acceptedChanged();

	m_availableItems->removeRows ( availableRow, 1, QModelIndex() );
	emit availableChanged();
}

The view.qml. We’ll try to have as few JavaScript code as possible; the idea is that coding itself is done in the ViewModel. The view should only be view code (styling, UI, animations, etc). The import url and version are defined by the use of qmlRegisterType in the main.cpp file, lower:

import QtQuick 2.0
import QtQuick.Controls 1.2

import be.codeminded.ViewModelExample 1.0

Rectangle {
    id: root
    width: 640; height: 320

	property var viewModel: ViewModel { }

	Rectangle {
		id: left
		anchors.left: parent.left
		anchors.top: parent.top
		anchors.bottom: button.top
		width: parent.width / 2
		ListView {
		    id: leftView
			anchors.left: parent.left
			anchors.right: parent.right
			anchors.top: parent.top
			anchors.bottom: leftText.top

			delegate: rowDelegate
		        model: viewModel.availableItems
		}
		Text {
			id: leftText
			anchors.left: parent.left
			anchors.right: parent.right
			anchors.bottom: parent.bottom
			height: 20
			text: viewModel.available
		}
	}

	Rectangle {
		id: right
		anchors.left: left.right
		anchors.right: parent.right
		anchors.top: parent.top
		anchors.bottom: button.top
		ListView {
		    id: rightView
			anchors.left: parent.left
			anchors.right: parent.right
			anchors.top: parent.top
			anchors.bottom: rightText.top

			delegate: rowDelegate
		        model: viewModel.acceptedItems
		}
		Text {
			id: rightText
			anchors.left: parent.left
			anchors.right: parent.right
			anchors.bottom: parent.bottom
			height: 20
			text: viewModel.accepted
		}
	}

	Component {
		id: rowDelegate
		Rectangle {
			width: parent.width
			height: 20
			color: ListView.view.currentIndex == index ? "red" : "white"
			Text { text: 'Name:' + display }
			MouseArea {
				anchors.fill: parent
				onClicked: parent.ListView.view.currentIndex = index
			}
		}
	}

	Button {
		id: button
		anchors.left: parent.left
		anchors.right: parent.right
		anchors.bottom: parent.bottom
		height: 20
	        text: "Accept item"
		onClicked: viewModel.onButtonClicked( leftView.currentIndex );
	}
}

A main.cpp example. The qmlRegisterType defines the url to import in the view.qml file:

#include <QGuiApplication>
#include <QQuickView>
#include <QtQml>
#include <QAbstractListModel>

#include "ViewModel.h"

int main(int argc, char *argv[])
{
	QGuiApplication app(argc, argv);
	QQuickView view;
	qRegisterMetaType<QAbstractListModel*>("QAbstractListModel*");
	qmlRegisterType<ViewModel>("be.codeminded.ViewModelExample", 1, 0, "ViewModel");
	view.setSource(QUrl("qrc:/view.qml"));
	view.show();
	return app.exec();
}

A project.pro file. Obviously should you use cmake nowadays. But oh well:

TEMPLATE += app
QT += quick
SOURCES += ViewModel.cpp main.cpp
HEADERS += ViewModel.h
RESOURCES += project.qrc

And a project.qrc file:

<!DOCTYPE RCC>
<RCC version="1.0">
<qresource prefix="/">
    <file>view.qml</file>
</qresource>
</RCC>

Geef vorm

We zijn goed. We tonen dat door ons respect voor privacy en veiligheid te combineren. Kennis is daar onontbeerlijk voor. Ik pleit voor investeren in techneuten die de twee beheersen.

Onze overheid moet niet alles investeren in miljoenen voor het bestrijden van computervredebreuk; wel ook investeren in betere software.

Belgische bedrijven maken soms software. Ze moeten aangemoedig worden, gestuurd, om het goede te doen.

Ik zou graag van ons centrum cybersecurity zien dat ze bedrijven aanmoedigt om goede en dus veilige software te maken. We moeten ook inzetten op repressie. Maar we moeten net zo veel inzetten op hoge kwaliteit.

Wij denken wel eens dat, ach, wij te klein zijn. Maar dat is niet waar. Als wij beslissen dat hier, in België, de software goed moet zijn: dan creërt dat een markt die zich zal aanpassen aan wat wij willen. Het is zaak standvastig te zijn.

Wanneer wij zeggen dat a – b hier welkom is, of niet, geven we vorm aan technologie.

Ik verwacht niet minder van mijn land. Geef vorm.

QML coding conventions checker that uses QML parser’s own abstract syntax tree

My colleague Henk Van Der Laak made a interesting tool that checks your code against the QML coding conventions. It uses the internal parser’s abstract syntax tree of Qt 5.6 and a visitor design.

It has a command line, but being developers ourselves we want an API too of course. Then we can integrate it in our development environments without having to use popen!

So this is how to use that API:

// Parse the code
QQmlJS::Engine engine;
QQmlJS::Lexer lexer(&engine);
QQmlJS::Parser parser(&engine);

QFileInfo info(a_filename);
bool isJavaScript = info.suffix().toLower() == QLatin1String("js");
lexer.setCode(code,  1, !isJavaScript);
bool success = isJavaScript ? parser.parseProgram() : parser.parse();
if (success) {
    // Check the code
    QQmlJS::AST::UiProgram *program = parser.ast();
    CheckingVisitor checkingVisitor(a_filename);
    program->accept(&checkingVisitor);
    foreach (const QString &warning, checkingVisitor.getWarnings()) {
        qWarning() << qPrintable(warning);
    }
}

Item isChild of another Item in QML

Damned, QML is inconsistent! Things have a content, data or children. And apparently they can all mean the same thing. So how do we know if something is a child of something else?

After a failed stackoverflow search I gave up on copy-paste coding and invented the damn thing myself.

function isChild( a_child, a_parent ) {
	if ( a_parent === null ) {
		return false
	}

	var tmp = ( a_parent.hasOwnProperty("content") ? a_parent.content
		: ( a_parent.hasOwnProperty("children") ? a_parent.children : a_parent.data ) )

	if ( tmp === null || tmp === undefined ) {
		return false
	}

	for (var i = 0; i < tmp.length; ++i) {

		if ( tmp[i] === a_child ) {
			return true
		} else {
			if ( isChild ( a_child, tmp[i] ) ) {
				return true
			}
		}
	}
	return false
}

Composition and aggregation to choose memory types in Qt

As we all know has Qt types like QPointerQSharedPointer and we know about its object trees. So when do we use what?

Let’s first go back to school, and remember the difference between composition and aggregation. Most of you probably remember drawings like this?

It thought us when to use composition, and when to use aggregation:

  • Use composition when the user can’t exist without the dependency. For example a Human can’t exist without a Head unless it ceases to be a human. You could also model Arm, Hand, Finger and Leg as aggregates but it might not make sense in your model (for a patient in a hospital perhaps it does?)
  • Use aggregate when the user can exist without the dependency: A car without a passenger is still a car in most models.

This model in the picture will for example tell us that a car’s passenger must have ten fingers.

But what does this have to do with QPointer, QSharedPointer and Qt’s object trees?

First situation is a shared composition. Both Owner1 and Owner2 can’t survive without Shared (composition, filled up diamonds). For this situation you would typically use a QSharedPointer<Shared> at Owner1 and Owner2:

If there is no other owner, then it’s probably better to just use Qt’s object trees and setParent() instead. Note that for example QML’s GC is not very well aware of QSharedPointer, but does seem to understand Qt’s object trees.

Second situation are shared users. User1 and User2 can stay alive when Shared goes away (aggregation, empty diamonds). In this situation you typically use a QPointer<Shared> at User1 and at User2. You want to be aware when Shared goes away. QPointer<Shared>’s isNull() will become true after that happened.

Third situation is a mixed one. In this case you could at Owner use a QSharedPointer<Shared> or a parented raw QObject pointer (using setParent()), but a QPointer<Shared> at User. When Owner goes away and its destructor (due to the parenting) deletes Shared, User can check for it using the previously mentioned isNull check.

Finally if you have a typical object tree, then use QObject’s infrastructure for this.

 

 

Visitor for Klartext

Felt good about explaining my work last time. For no reason. I guess I’m happy, or I no longer feel PGO’s pressure or something. Having to be politically correct all the times, sucks. Making technically and architecturally good solutions is what drives me.

Today I explained the visitor pattern. We want to parse Klartext in such a way that we can present its structure in a editing component. It’s the same component for which I utilized a LRU last week. We want to visualize significant lines like tool changes, but also make cycles foldable like SciTe does with source code and a whole lot of other stuff that I can’t tell you because of teh secretz. Meanwile these files are, especially when generated using cad-cam software, amazingly huge.

Today I had some success with explaining visitor using the Louvre as that what is “visitable” (the AST) and a Japanese guy who wants to collect state (photos) as a visitor of fine arts. Hoping my good-taste solutions (not my words, it’s how Matthias Hasselmann describes my work at Nokia) will once again yield a certain amount of success.

ps. I made sure that all the politically correcting categories are added to this post. So if you’d have filtered away the condescending and controversial posts from my blog, you could have protected yourself from being in total shock now (because I used the sexually tinted word “sucks”, earlier). Guess you didn’t. Those categories have been in place on my blog’s infrastructure since many years. They are like the Körperwelten (Bodyworlds) exhibitions; you don’t have to visit them.

Putting an LRU in your code

For the ones who didn’t find the LRU in Tracker’s code (and for the ones who where lazy).

Let’s say we will have instances of something called a Statement. Each of those instances is relatively big. But we can recreate them relatively cheap. We will have a huge amount of them. But at any time we only need a handful of them.

The ones that are most recently used are most likely to be needed again soon.

First you make a structure that will hold some administration of the LRU:

typedef struct {
	Statement *head;
	Statement *tail;
	unsigned int size;
	unsigned int max;
} StatementLru;

Then we make the user of a Statement (a view or a model). I’ll be using a Map here. You can in Qt for example use QMap for this. Usually I want relatively fast access based on a key. You could also each time loop the stmt_lru to find the instance you want in useStatement based on something in Statement itself. That would rid yourself of the overhead of a map.

class StatementUser
{
	StatementUser();
	~StatementUser();
	void useStatement(KeyType key);
private:
	StatementLru stmt_lru;
	Map<KeyType, Statement*> stmts;
	StatementFactory stmt_factory;
}

Then we will add to the private fields of the Statement class the members prev and next: We’ll make a circular doubly linked list.

class Statement: QObject {
	Q_OBJECT
    ...
private:
	Statement *next;
	Statement *prev;
};

Next we initialize the LRU:

StatementUser::StatementUser() 
{
	stmt_lru.max = 500;
	stmt_lru.size = 0;		
}

Then we implement using the statements

void StatementUser::useStatement(KeyType key)
{
	Statement *stmt;

	if (!stmts.get (key, &stmt)) {

		stmt = stmt_factory.createStatement(key);

		stmts.insert (key, stmt);

		/* So the ring looks a bit like this: *
		 *                                    *
		 *    .--tail  .--head                *
		 *    |        |                      *
		 *  [p-n] -> [p-n] -> [p-n] -> [p-n]  *
		 *    ^                          |    *
		 *    `- [n-p] <- [n-p] <--------'    */

		if (stmt_lru.size >= stmt_lru.max) {
			Statement *new_head;

		/* We reached max-size of the LRU stmt cache. Destroy current
		 * least recently used (stmt_lru.head) and fix the ring. For
		 * that we take out the current head, and close the ring.
		 * Then we assign head->next as new head. */

			new_head = stmt_lru.head->next;
			auto to_del = stmts.find (stmt_lru.head);
			stmts.remove (to_del);
			delete stmt_lru.head;
			stmt_lru.size--;
			stmt_lru.head = new_head;
		} else {
			if (stmt_lru.size == 0) {
				stmt_lru.head = stmt;
				stmt_lru.tail = stmt;
			}
		}

	/* Set the current stmt (which is always new here) as the new tail
	 * (new most recent used). We insert current stmt between head and
	 * current tail, and we set tail to current stmt. */

		stmt_lru.size++;
		stmt->next = stmt_lru.head;
		stmt_lru.head->prev = stmt;

		stmt_lru.tail->next = stmt;
		stmt->prev = stmt_lru.tail;
		stmt_lru.tail = stmt;

	} else {
		if (stmt == stmt_lru.head) {

		/* Current stmt is least recently used, shift head and tail
		 * of the ring to efficiently make it most recently used. */

			stmt_lru.head = stmt_lru.head->next;
			stmt_lru.tail = stmt_lru.tail->next;
		} else if (stmt != stmt_lru.tail) {

		/* Current statement isn't most recently used, make it most
		 * recently used now (less efficient way than above). */

		/* Take stmt out of the list and close the ring */
			stmt->prev->next = stmt->next;
			stmt->next->prev = stmt->prev;

		/* Put stmt as tail (most recent used) */
			stmt->next = stmt_lru.head;
			stmt_lru.head->prev = stmt;
			stmt->prev = stmt_lru.tail;
			stmt_lru.tail->next = stmt;
			stmt_lru.tail = stmt;
		}

	/* if (stmt == tail), it's already the most recently used in the
	 * ring, so in this case we do nothing of course */
	}

	/* Use stmt */

	return;
}

In case StatementUser and Statement form a composition (StatementUser owns Statement, which is what makes most sense), don’t forget to delete the instances in the destructor of StatementUser. In the example’s case we used heap objects. You can loop the stmt_lru or the map here.

StatementUser::~StatementUser()
{
	Map<KeyType, Statement*>::iterator i;
    	for (i = stmts.begin(); i != stmts.end(); ++i) {
		delete i.value();
	}
}

Secretly reusing my own LRU code

Last week, I secretly reused my own LRU code in the model of the editor of a CNC machine (has truly huge files, needs a statement editor). I rewrote my own code, of course. It’s Qt based, not GLib. Wouldn’t work in original form anyway. But the same principle. Don’t tell Jürg who helped me write that, back then.

Extra points and free beer for people who can find it in Tracker’s code.

Als het goed is, zeggen we het ook

De Belgische Marechaussee heeft goed werk verricht. Het gespuis is grotendeels opgepakt. Daar zal speurwerk voor nodig geweest zijn. Toch bleken er weinig inbreuken te zijn en heeft de bevolking weinig vrijheden ingeleverd.

Met andere woorden: er is gericht werk verricht.

Hoe hoger het resultaat met hoe minder ingeleverde vrijheden, te hoger de kwaliteit van onze diensten.

We gaan dat landje hier vrij houden.

RE: Toeristen, geef alstublieft een extra stukje privacy prijs (opiniestuk CEO van Thomas Cook, De Tijd)

Toeristen, geef alstublieft een extra stukje privacy prijs, zodat we U en uw koopgedrag nog meer en beter kunnen tracken bij Thomas Cook.

We hebben de neiging minder flexibel te zijn als het om onze privacy gaat. Maar we zullen niet anders kunnen dan onze privacy voor een stuk opgeven. Voor onze eigen veiligheid, zodat de overheden kunnen screenen wie op welke vlucht zit. Die evolutie zagen we al na de aanslagen van 11 september 2001 in New York.

Hoe juist helpt het dat Thomas Cook weet wie op welke vlucht zal zitten? De veiligheidsdiensten weten dat trouwens nu al. Hoe helpt dit wanneer iemand lang voor om het even welke identiteitscontrole in de vertrekhal een bom laat afgaan? Hoe heeft dat securitytheater na 9/11 trouwens om het even welke aanslag vermeden? Welke bewijzen zijn er dat het geholpen heeft? Welke bewijzen zijn er dat de in extreme zin toegenomen surveillance helpt?

Dit ruikt sterk naar goedkope politieke recuperatie van een stuk menselijke ellende. Jan Dekeyser, CEO van Thomas Cook België, wil U en uw koopgedrag kunnen tracken. Zodat hij veel geld met uw privacy kan verdienen. Nog meer geld. Hij roept daarvoor op nu dat de mensen bang zijn en bereidwillig hun privacy op te geven. Van timing gesproken.

We moeten nu ook van de CEO van Thomas Cook onze Facebook profielen aan hem en zijn marketing afdeling geven. Dat zegt hij letterlijk in zijn opiniestuk:

Dat kan veranderen. Intussen heeft zowat iedereen een smartphone, een Facebook-profiel of een Twitter-account. Het is dus perfect mogelijk om via persoonlijke communicatie de bezorgdheid van de reizigers weg te nemen en hen rechtstreeks te informeren over hoe hun reis verder zal verlopen.

Waarschijnlijk kan je dus binnenkort geen klant meer zijn bij Thomas Cook tenzij je een Facebook profiel hebt waar hij en zijn bedrijf volledige toegang toe hebben. Zullen we de luchthaven nog wel binnenmogen tenzij hij en zijn bedrijven alles over U weten, zodoende hij U en uw koopgedrag volledig in kaart kan brengen?

Wanneer wordt het nu eindelijk eens duidelijk dat geen enkele hoeveelheid surveillance bovenop wat er nu reeds is, aanslagen zal voorkomen? In tegendeel zal de onnodige verdachtmaking onschuldige burgers net kwaad en wantrouwig tegenover hun overheid maken.

Dus neen, Jan Dekeyser CEO van Thomas Cook België, ik geef niet een extra stukje privacy aan U en uw marketing mensen prijs. Onze veiligheidsdiensten weten nu al perfect wie er op welke vlucht zit. Die databases bestaan al.

Geef de actoren verantwoordelijk voor het doorspelen van informatie naar de juiste diensten en mensen een betere opleiding, verhoog getalmatig manschappen en budgetten en werk met de informatie die er al is. M.a.w. doe als ambtenaar in een veiligheidsfunctie uw job.

Maar een Thomas Cook moet echt niet nog meer van onze privacy weten.

It never ends

Allereerst, na Brussel blijf ik hier bij:

[over encryptie] Allereerst zolang er geen nood is moet men niets doen. Want ik zie niet meteen een echte noodzaak om alle mensen hun elektronica te kunnen kraken. Dat was vroeger niet nodig; vandaag zijn er niet meer of minder gevaarlijke gekken en elektronica voegt maar weinig toe aan hun wapenarsenaal. Dus is dat nu niet nodig.

Ik sta ook hier achter:

Oh, and to our security services: well done catching those guys from Molenbeek and Vorst. Good job

Niet gestresseerd geraken. Zoals alle mensen presteer je slecht wanneer je gestresseerd bent. Hold the line. Molenbeek en Vorst was trouwens prachtig werk. Goed gedaan.

We vinden die balans wel.

Up next: PADI master diver

A year or so after my PADI rescue, my diving club has convinced me to wake up about twelve times early in the morning on Saturday, to get me trained to become a PADI master diver.

The jokers in my club told me it’s not so hard as PADI Rescue training. The only hard part is Saturday morning. We’ll see, I wonder. heh.

Oh, and to our security services: well done catching those guys from Molenbeek and Vorst. Good job!

Oh, I got invited to NLGG to talk about Tracker in Utrecht tomorrow.

RE: President Obama benadrukt noodzaak van een encryptie-backdoor

‘t ga hier over

We leggen in België al behoorlijk wat verantwoordelijkheid over onze bezittingen bij de notaris. Hij maakte de eigendomsakte van uw huis op, over de erfdienstbaarheid van uw grond, uw aandelen en de oprichtingsakte van uw bedrijf. Hij regelt ook de erfenis. Dat loopt hier vrij goed. Het zal wel eens af en toe mislopen, maar niet vaak. Volgens mij is dat omdat de deontologische code van het notariaat in België redelijk streng is. Je wordt ook niet zomaar notaris. De opleiding en examens ervoor blijken vrij moeilijk te zijn.

Allereerst zolang er geen nood is moet men niets doen. Want ik zie niet meteen een echte noodzaak om alle mensen hun elektronica te kunnen kraken. Dat was vroeger niet nodig; vandaag zijn er niet meer of minder gevaarlijke gekken en elektronica voegt maar weinig toe aan hun wapenarsenaal. Dus is dat nu niet nodig.

Maar om den Obama toch wat te helpen met de oprichting van z’n surveillancestaat, waarbij iPhones moeten kunnen gedecrypteerd worden door de overheid, zou ik een systeem of concept waarbij een soort van master key fysiek opgeslagen wordt bij de notaris willen voorstellen (je hebt dus eerst een deftig notariaat nodig, maar dat hebben we al).

De notaris krijgt een deontologische code die er op neerkomt dat hij of zij de proportionaliteit moet onderzoeken wanneer overheidsdiensten een afdruk van die master key opvragen. De afdruk van die key zou zo kunnen voorzien worden dat enkel bepaalde documenten er mee gedecrypteerd kunnen worden, i.p.v. alles.

De burger die zijn eigen keys verliest kan dan tegen een typisch notaristarief een nieuwe key laten maken a.d.h.v. de bij de notaris aanwezige key. Ik zou de overheid dat tarief ook laten betalen. Anders willen de notarissen die bevoegdheid waarschijnlijk niet (en zo’n proportionaliteitsonderzoek vraagt juridische kennis en tijd: de twee kostbaarste dingen in het leven van de notaris).

Ik denk wel dat onze cryptografen zoiets in elkaar kunnen steken.

Ge moet het vooral allemaal niet te moeilijk of complex maken: geen (extra) backdoors in de software of hardware want dan zit overmorgen de overheid van ieder land, en een hele bende criminelen ook, in al onze politici en bedrijfsleiders hun Facebook-doorgeef-luik, ik bedoel hun smartphone en tablets. Het is nu al erg genoeg wat ze er zelf achteloos en publiek op neerkwakken (terwijl velen, zeer naief, denken dat het allemaal privé is wat er in die Cloud rotzooi gebeurt).

Het Internet Der Crap

Ik heb in Belgische bedrijven al bugs gefiled waarbij een buffer afkomstig van een Angular HTTP POST sessie gewoon met memcpy in een stack buffer van 1024 bytes gekopieerd wordt, met uiteraard strlen op de origin buffer als size_t n parameter. Daar kwam zelfs ruzie van want de geniale programmeur vond dat dat geen bug was, omdat je de admin credentials nodig had om te reproduceren. Het probleem was dat ook zonder in te loggen de buffer tot aan de memcpy kon geraken.

Het is ook geen uitzondering om wanneer je met de strings tool op de binaries op vele routers losgaat, je gewoonweg backdoors en hardcoded passwords krijgt. Je komt programmeurs tegen die dat er gewoon ingestopt hebben. Dat vinden ze normaal. Ruwe anti-security arrogantie. En ze zijn nog trots op hun onprofessionalisme ook.

Deze tijd is dan ook niet de tijd van het Internet Der Dingen, maar wel van Het Internet Der Crap. Gemaakt door prutsers. Zelfs de backdoors zijn prutswerk.

Het is zeer erg gesteld. Ik voel me beschaamd om vele van mijn collega’s en wens mij te distantiëren.

Ik heb nog eens m’n steentje bijgedrage

Heb dit geyoutubed gisterenavond toen m’n duikclub was komen vlees op een rooster en gloeiende koolen verbranden. Oh met den Hans Teeuwen en de Theo Maassen zijn we ook aan’t lachen geweest. Na één uur de Geubels vond ik dat we ook eens andere komieken moeten laten zien aan de wereld. Duikers zijn een leutige bende. Een beetje zoals ons, neurdjes. Ik raad alle andere computermannekens aan om ook te gaan duiken. Toffe mensen.

https://www.youtube.com/watch?v=yi1XwrPwz1k

Dit is niet de eerste keer dat ik dit filmpje blog. Maar ik zou graag meer Astronomers willen tegenkomen zodat we misschien effectief die planeet hier kunnen opkopen. En dan een gigantisch ruimteschip maken. Samen! Brand new world order 2.0. Or, shut the fuck up.

Daarnet nog een goed idee besproken met diene dat is blijven crashen. Ik wil hier in Rillaar toch ooit eens een zwembad zetten. Misschien moet ik er ééntje maken in de vorm van een schotel? Dan kunnen de duikers bij mij komen oefenen.

Gebruik maken van verbanden tussen metadata

Ik beweerde onlangs ergens dat een systeem dat verbanden (waar, wanneer, met wie, waarom) in plaats van louter metadata (titel, datum, auteur, enz.) over content verzamelt een oplossing zou kunnen bieden voor het probleem dat gebruikers van digitale media meer en meer zullen hebben; namelijk dat ze teveel materiaal gaan verzameld hebben om er ooit nog eens iets snel genoeg in terug te vinden.

Ik denk dat verbanden meer gewicht moeten krijgen dan louter de metadata omdat het door middel van verbanden is dat wij mensen in onze hersenen informatie onthouden. Niet door middel van feiten (titel, datum, auteur, enz.) maar wel door middel van verbanden (waar, wanneer, met wie, waarom) .

Ik gaf als hypothetisch voorbeeld dat ik een video wilde vinden die ik gekeken had met Erika toen ik op vakantie was met haar en die zij als super tof had gemarkeerd.

Wat zijn de verbanden die we moeten verzamelen? Dit is een eenvoudig oefeningetje in analyse: gewoon de zelfstandige naamwoorden onderlijnen en het probleem opnieuw uitschrijven:

  • Dat ik op vakantie was toen ik hem laatst zag. Dat is een point of interest (waar)
  • Dat het een film is (wat, is een feit over mijn te vinden onderwerp en dus geen verband. Maar we nemen dit mee)
  • Met wie ik de film gekeken heb en wanneer (met wie, wanneer)
  • Dat Erika, met wie ik de film gekeken heb, de film super tof vond (waarom)

Dus laat ik deze use-case eens in RDF gieten en oplossen met SPARQL. Dit moeten we verzamelen. Ik schrijf het in pseudo TTL. Bedenk er even bij dat deze ontology helemaal bestaat:

<erika> a Person ; name "Erika" .
<vakantiePlek> a PointOfInterest ; title "De vakantieplek" .
<filmA> a Movie ; lastSeenAt <vakantiePlek> ; sharedWith <erika>; title "The movie" .
<erika> likes <filmA> .

Dit is daarna de SPARQL query:

SELECT ?m { ?v a Movie ; title ?m . ?v lastSeenAt ?p . ?p title ?pt . ?v sharedWith <erika> . <erika> likes ?v . FILTER (?pt LIKE '%vakantieplek%') }

Ik laat het als een oefening aan de lezer om dit naar de ontology Nepomuk om te zetten (volgens mij kan het deze hele use-case aan). En dan kan je dat eens op je N9 of je standaard GNOME desktop testen met de tool tracker-sparql. Wedden dat het werkt. :-)

Het grote probleem is inderdaad de data aquisitie van de verbanden. De query maken is vrij eenvoudig. De ontology vastleggen en afspreken met alle partijen al wat minder. De informatie verzamelen is dé moeilijkheid.

Oh ja. En eens verzameld, de informatie veilig bijhouden zonder dat mijn privacy geschonden wordt. Dat lijkt tegenwoordig gewoonweg onmogelijk. Helaas.

Het is in ieder geval niet nodig dat een supercomputer of zo dit centraal moet oplossen (met AI en heel de gruwelijk complexe hype zooi van vandaag).

Ieder klein toestelletje kan dit soort use-cases zelfstandig oplossen. De bovenstaande inserts en query zijn eenvoudig op te lossen. SQLite doet dit in een paar milliseconden met een gedenormalizeerd schema. Uw fancy hipster NoSQL oplossing waarschijnlijk ook.

Dat is omdat het gewicht van data aquisitie op de verbanden ligt in plaats van op de feiten.