I Did Opt Out of Facebook

About a week or two ago I did opt out of Facebook. I went to my user settings, downloaded an archive of my current content and requested a deletion of my accout afterwards. Usually postings like this one contain a particular level of drama. There is no real drama this time. I quit because other things are more important to me and Facebook continuesly got in the way of them.

At first I was quite unsure if I would miss something. People are often talking about “digital suicide”. Many people are afaraid of killing their personal social life by quitting an online social network. But in the end I have to say, the decision was great for me. Since left the network I:

I am still using Twitter, Xing and LinkedIN for professional contacts. This is quite ok for me. Some kind of humble and not that disattracting in the end. In the and the reads I catch on twitter are times more interesting to me than I ever received by the same people via other networks. Quite interesting btw!

Returning as a Duty

Thanks to really successfull platforms like Github or Stackoverflow, it feels like the zenith of coding culture to me. It was never such an ease to find usefull information and code right away within minutes. That is awesome! Thanks so far! Sadly, I still recognize a large apathy when it comes to engagement and involvement inside and outside the developer’s scene.

The successfull people of today, mostly did build their personal and intelectual wealth, on top of the open minded sharing culture. Not only the developers! The open source movement did release a lot of usefull “products”, everybody benefits from in one way or another. The blooming success of Linux, Apache, PHP and MySQL, enabled hosters to build a well scaleable business model for professional webhosting. Which results in many successfull PHP based software projects. Take Wordpress for example. When there haven’t been a Wordpress boom, the last few years, many of you freelance designers wouldn’t have been able to generate money that easy, building websites based on Wordpress.

When was the last time you did contribute to an opensource project in one way or another? When was the last time you held a talk or lend a motivated newcomer the helping hand of a professional? The answer here, for the most of you, is most likely something between never or not yet.

Shame. On. You!

Well, even if you haven’t recognized it yet: in the very moment, you’ve decided to join the open source and netizen community, you decided to aggree in a culture of free software and free information.

Sharing is caring!

If you care, as half as much, for the future of free information/technology, as you care for your personal wealth, everything will be fine. It isn’t really that difficult to contribute. You dont have to maintain a project or release your secret intelectual property.

If you are a single person volunteer in a project or field, you feel attached to. You could be a coach in the OpenTechSchool for example and teach teens and grown ups how to code. If you don’t feel like coaching or doing talks that’s ok. You can contribute in many different ways. Connecting people is awesome and won’t cost you more than just a few calls or emails.

If you are a company, you can contribute by speding some money to projects or organizations, you build on. Share your rooms for meetings and workshops of usergroups. Better: organize meetups!

I could continue this for another twenty paragraphs. But I think my plea is clear: Involve yourselves! Contribute to open knowledge and open technology. It is your social duty, to thank the society and culture you build your personal success up on, by returning just a bit of time, expertise or even resources. Monetary or whatever!

Coding Music:
Nightmares on Wax Boiler Room DJ Set

Why I Blog in English

Even if my name might say different: I am not a native speaker!

I was born and grew up in germany. During junior highschool my english wasn’t better than the english of any other kid of my age. Over the time, many of my friends asked my, why I would write nearly everything on the internet in english?

When I started this blog, I decided to go for english. This has several reasons.

English as online Esperanto

Well, english IS the language of the internet. It might be something similiar to the Esperanto of the digital age. There are probably more chinese speaking people on the net than englisch speaking people, but the language the most people have in common nowadays is (surprise surprise) english! In germany, many people still have mediocre to bad english reading skills. That is quite a pitty, because some of the BEST resources on any topic out there, are written in english.

I like to learn

I want to improve my personal english skills. Beside reading english books and watching my movies in english language, I start writing in english, to get better.

My german is ways better

I like to write to communicate. Key to successfull communication is a simple, straight and understandable phrase. The fact, that I am not as good with writing english as I am with writing german, keeps me to stick to simplicity. Which on the other hand is a good training for becoming a better writer in general.

Cyberleiber Festival:
Science-Fiction Indeed?

Some days ago I had a talk I originally created for the screening of “A Scanner Darkly” during the “Uebermorgen Filmfestival”, 2008 in Dortmund.

The talk is named “Science-Fiction Indeed” and compares the current state of technology with szenarios and elements from the science fiction culture. Movies as well as literature.

Based on popular demand, here is the link to the slides

Hash Is Bad, Mkay? At Least With NSString.

The Issue

During a current customer’s project, I stumbled over a noteable reliability issue of [NSString hash]. I was using a modified version of RNCachingURLProtocol for realizing a cross platform configurator, which is also available offline.

When my web-application was in online mode and the data dropped in live, everything ran perfect. But everytime the CacheWebView ran in offline mode, (all files were retrieved from cache only), my web-application encountered very unreliable behaviours. Some of the assets went totally nuts. Two different products to be shown, were displayed with totally inpropriate assets. Like product A was displayed with the appearance of product B. While product B itself was displayed perfectly.

I started analyzing cache storage methods of RNCachingURLProtocol. The URLs were valid and unique all the time. I ran NSLog with the absolute URL and the corresponding cache filename, to ensure that every file would be stored correctly. After building a spreadsheet with URL and cache filenames, I ordered the rows by filename and discovered a behaviour I wouldn’t have excepted:

[NSString hash] does produce identical hash values for non identical strings.

The Conditions

At least there are special circumstances for which this unreliability kicks in.

Comparing [a hash] and [b hash] of two different NSString is safe when:

Otherwise every difference between the first and the middle 32 chars, as well as every difference between the middle and the last 32 characters, are not used while producing the [NSString hash] value.

But why should one bother about this behaviour, when it only occours in with such a complicated scenario?

Well, common developers’s knowledge of hashes is, that one could make use of them, when creating a short and unique representation of data. For instance while using it in lookup tables. Many developers absolutely rely on this principle. So you should at least be aware of the side effects. Or even better: avoid to use [NSString hash] when in doubt.

Me myself, trampled two times into this “hash-trap”. Every time while handling URLs. First time recently (but just did fix the symptoms) while keeping async NSURLConnection in a lookup-table. The other time while using long URLs in with the local cache. It is relativly typical for URLs to be structured some kind of symmetric.

http://www.customer.com/catalog-app/assets/images/product/lovely_line/orange_chair.jpg?cacheToken=AEF453ASDF
http://www.customer.com/catalog-app/assets/images/product/lovely_line/yellow_chair.jpg?cacheToken=AEF453ASDF

You may blame it on the naming. But as long as you rely on [NSString hash] to generate a hopefully unique identifier of an instance, this side effect can bubble up one day and crash your projects too. Then probably, out of the sudden and you won’t have the slightest idea of what the source of the problem might be. Because you believe in the ultimate uniqueness of the hash. But it is not.

The Proof

When I found out about the hash equality issue, I consulted the official Apple developer documentation, cool like a rock and then paniced.

If two string objects are equal (as determined by the isEqualToString: method), **they must have the same hash value**. The abstract implementation of this method fulfills this requirement, so subclasses of NSString shouldn’t override it.

You should not rely on this method returning the same hash value across releases of OS X.

It says, that in order to resolve YES from [NSString isEqual], the hashes have to be the same/equal. But as discovered earlier, the hashes are also equal when while the strings are not. That would be a diseaster! So I fired up Xcode:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
    NSString *testA = @"http://www.customer.com/catalog-app/assets/images/product/lovely_line/orange_chair.jpg?cacheToken=AEF453ASDF";
    NSString *testB = @"http://www.customer.com/catalog-app/assets/images/product/lovely_line/yellow_chair.jpg?cacheToken=AEF453ASDF";

    // For better understanding of the pattern test this
//    testA = @"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!!!!!!!bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb!!!!!!!cccccccccccccccccccccccccccccccc";
//    testB = @"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa???????bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb???????cccccccccccccccccccccccccccccccc";

    NSLog(@"A-Count: %i / A-Hash: %x", [testA length], [testA hash]);
    // A-Count: 108 / A-Hash: 445db5cd
    NSLog(@"B-Count: %i / B-Hash: %x", [testB length], [testB hash]);
    // B-Count: 108 / B-Hash: 445db5cd

    NSLog(@"[A isEqual:B] %i", [testA isEqual:testB]);
    // [A isEqual:B] 0
    NSLog(@"[B isEqual:A] %i", [testB isEqual:testA]);
    // [B isEqual:A] 0
    NSLog(@"[A isEqualToString:B] %i", [testA isEqualToString:testB]);
    // [A isEqualToString:B] 0
    NSLog(@"[B isEqualToString:A] %i", [testB isEqualToString:testA]);
    // [B isEqualToString:A] 0

Lucky us! The documentation was wrong: isEqual as well as isEqualToString obviously don’t dominantely rely on [NSString hash] to test equality.

Some time after I reversed and tested the pattern, I stumbled over an posting, which linked to the opensource CFString.c that contains the hashing functions used by [NSString hash] Here it is getting obvious, why [NSString hash] does behave that way.

[Extract of CFString.c]link
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/* This is meant to be called from NSString or subclassers only. It is an error for this to be called without the ObjC runtime or an argument which is not an NSString or subclass. It can be called with NSCFString, although that would be inefficient (causing indirection) and won't normally happen anyway, as NSCFString overrides hash.
*/
CFHashCode CFStringHashNSString(CFStringRef str) {
    UniChar buffer[HashEverythingLimit];
    CFIndex bufLen;      // Number of characters in the buffer for hashing
    CFIndex len = 0;  // Actual length of the string

    CF_OBJC_CALL0(CFIndex, len, str, "length");
   if (len <= HashEverythingLimit) {
        CF_OBJC_VOIDCALL2(str, "getCharacters:range:", buffer, CFRangeMake(0, len));
        bufLen = len;
    } else {
        CF_OBJC_VOIDCALL2(str, "getCharacters:range:", buffer, CFRangeMake(0, 32));
        CF_OBJC_VOIDCALL2(str, "getCharacters:range:", buffer+32, CFRangeMake((len >> 1) - 16, 32));
        CF_OBJC_VOIDCALL2(str, "getCharacters:range:", buffer+64, CFRangeMake(len - 32, 32));
        bufLen = HashEverythingLimit;
    }
    return __CFStrHashCharacters(buffer, bufLen, len);
}

Solution

For my case, the solution was pretty easy. I made use of a sha1 hash, which produced a fingerprint from the whole string instead of pieces only. I got mine inspired by the SHA1 method of Saurabh Sharma

SHA1link
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
- (NSString *)sha1
{
    NSData *data = [self dataUsingEncoding:NSUTF8StringEncoding];
    uint8_t digest[CC_SHA1_DIGEST_LENGTH];

    CC_SHA1(data.bytes, data.length, digest);

    NSMutableString *output = [NSMutableString stringWithCapacity:CC_SHA1_DIGEST_LENGTH * 2];

    for (int i = 0; i < CC_SHA1_DIGEST_LENGTH; i++) {
        [output appendFormat:@"%02x", digest[i]];
    }

    return output;
}

The SHA1 was for the name of a cached file, generated by giving the complete URL of the resource to be cached. Works perfect. I already filed a pull request for RNCachingURLProtocol.