Compress Google's Reader

If you are using Google’s Reader to aggregate news feeds you might have recognized that Google re-engineered its feed-reader to fit into the styles of other Google-services.

The new interface slimmed a bit and is more lightweight, but I’m arguing about the large white-spaces! Too much space is unused and to less information is presented. Such disadvantages are also discussed at other places.

First I thought I’ll get used to it, but now I decided to change it on my own. So I created a small user script for the Firefox extension Greasemonkey. Here you see the difference (click the images for larger versions):

Reader w/o modification
Reader w/o modification
Reader w/ modification
Reader w/ modification

So you see, there is less space at the top of the page and single entries got closer together. The script is available in the download section, all you need is the browser Firefox and its extension Greasemonkey. If you have both installed just click the following link to the download and Greasemonky will ask you to install my short script. That’s it for the moment ;-)

Update 22.11.2011: Updated the UserScript to support googles new layout.

Download: JavaScript: Google Reader Whitespace Remover (Please take a look at the man-page. Browse bugs and feature requests.)

Sharing a Wifi connection

Due to different circumstances I had to figure out how to share a wireless connection with some wired clients. And what should I say, that’s a very simple task ;-)

The scenario

With your notbook you are able to connect to an AP with access to the internet, but other machines within your network infrastructure don’t have access to the outside world, and you want your local machines to also use this wireless connection of your notebook. Figure 1 visualizes this use case.

The setup

First of all I have to admit I don’t know which software needs to be installed. Since I previously did some network hacks with this notebook I didn’t have to install something that wasn’t actually present, but I think you’ll need something like network-manager-gnome , dnsmasq-base and dnsmasq-utils . And of course you also need a Linux notebook (e.g. with a Debian or an Ubuntu) with wifi hardware, an AP with internet connection and a RJ45 Ethernet port on the notebook for the wired connection to other PC’s.

The first thing you should do is to connect to the AP, so your notebook will be able to access the WWW.

The next step is to connect another machine to your notebook using a network cable. This machine needs to be configured as a DHCP-client. (Since this might be any operating system of your choice I don’t describe the configuration, but most systems should already be configured correctly)

Now you have to setup a shared connection on your notebook. Right-click the network indicator icon in your systems panel (next to your clock) and choose Edit Connections…, compare to figure 2.

This will open a new window with connections you still configured. In the Wired tab click Add to install a new shared connection, see figure 3.

You’ll see another window to configure this new connection. Just give it a name like share and choose the method Shared to other computers in the IPv4 Settings tab, as shown in figure 4.

Last but not least open a terminal and add a new entry to the nat-table:

sudo iptables -t nat -A POSTROUTING -j MASQUERADE

That’s it, using this newly created connection you’re able to connect your clients behind your notebook through your wireless connection.

They are following you!

Recently there was a discussion with the privacy officer of Hamburg. He was arguing about people using Google-Analytics, but he also tracks his visitors on his public website. So are you anonymous? Of course not! Lets have a look at the why.

What's the problem?

Many webmasters analyze their website with Google-Analytics. This is a service of Google, very easy to use. All you need to do is insert a small script somewhere into your HTML-code:

<script type="text/javascript">

  var _gaq = _gaq || [];
  _gaq.push(['_setAccount', 'SOME_ID']);
  _gaq.push(['_trackPageview']);

  (function() {
    var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
    ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
  })();

</script>

This code tells the visitors browser to download a script from http://www.google-analytics.com/. That is while you visit this website, you additionally visit Google’s website in the background. Google of course recognizes this visit and knows which website you accessed. That is of course very cool for webmasters, they’ll get very detailed statistics about their visitors without any own work. Which article is favored most, should articles be published in the morning or in the evening, where do the visitors come from, how much time do they spend on the site and so on. Visitors don’t even know that Google follows them on nearly every website they visit. So Google is able to create very extensive profiles of every web user. Where do I come from? Am I interested in technical or political topics? Which videos do I like at YouTube? How frequently do I visit YouPorn? Based on my clicks it’s easy to guess my gender (shoes or cars?), my age (SpongeBob or cure), my professional (stock market news or music)… Do you have an account at Twitter? Google-Analytics also tracks user generated content. Together with some personal sites at Xing or LinkedIn or a blog at bloggers.com it’s easy to get a comprehensive profile of a single web user.

So Google is the bastard?

Oh not in the slightest! There are a lot of these companies. The previous mentioned privacy officer for examples tracks it’s users with IVW. The IVW uses a similar technique, you add a small image, a so called web bug, to your site:

<img id="ivw_pixel" src="http://heise.ivwbox.de/cgi-bin/ivw/SOMEID">

Since it is exactly 1 pixel it is not visible to the user, but your browser nevertheless loads it from ivwbox.de and so they get notified if you visit this specific website. Prominent customers are also Heise, Playboy, Xing, Ebay, Bild.de and a lot more (click the links to get some statistics). So IVW also creates extensive profiles of you! Do you really want to connect you professional Xing profile with Bild.de or Playboy? ;-)

But not enough, you know these funny pictures:

How often did you see one of these buttons today? Do you know a website that doesn’t have a like button (except mine)? Lets have a look to the HTML code:

<iframe src="https://plusone.google.com/u/0/_/+1/SOMESTUFF" allowtransparency="true" hspace="0" id="SOMEID" marginheight="0" marginwidth="0" name="SOMENAME" style="STYLE" tabindex="-1" vspace="0" scrolling="no" width="100%" frameborder="0"></iframe>
[...]
<iframe src="http://platform.twitter.com/widgets/tweet_button.html#_=ID" title="TITLE" style="STYLE" class="CLASS" allowtransparency="true" scrolling="no" frameborder="0"></iframe><script type="text/javascript" src="http://platform.twitter.com/widgets.js"></script>
[...]
<iframe src="http://www.facebook.com/plugins/like.php?href=ID" style="STYLE" allowtransparency="true" scrolling="no" frameborder="0"></iframe>
[...]
<script src="http://www.stumbleupon.com/hostedbadge.php?s=1"></script><iframe src="http://www.stumbleupon.com/badge/embed/1/?url=ID" style="STYLE" allowtransparency="true" scrolling="no" frameborder="0"></iframe>

Wow, while we visit one single website, our browser notifies Google, Twitter, Facebook and StumbleUpon about our short visit. Crazy, isn’t it? And there are much more networks that offer such buttons. Or have a look at this picture:

Each button is loaded from foreign webservers. I hardly can see any benefit for the user or the webmaster!?

How to defend?

There is no protection, power off all your electronics and go back to the stone age! (Or get amish) Ok, that’s hard and somewhat impossible these days. But there are some possibilities to minimize the tracking.

For example some Firefox extensions like NoScript prevent your browser loading scripts from foreign servers (see Google-Analytics). But you’ll also load these buttons and iframes, because this is simple HTML. Here you need another extension like AdBlockPlus. This allows you to define rules for blocking specific content, e.g. everything that comes from facebook. But keep in mind that these companies own different domains, like facebook.com, facebook.net or fbcdn.net. And even if you think you got all of them, there are a lot more. There is also a filter list for social media stuff available at Chrome Adblock (yes, comes from Google, but does its job…). If you are not running Firefox or you don’t want to install a bunch of plugins, you can also send these request to nirvana. For example unix-guys might add lines like this to their /etc/hosts :

192.168.23.23 facebook.com

Every time your browser wants to load a script from facebook.com he sends a request to 192.168.23.23 , which hopefully doesn’t exists. Do the same for all the other profiler.

Fear?

Don’t be frightened now, but be aware! You should carefully decide what to publish about yourself and others around you. And of course take care of your privacy. Some days ago we went to Berlin for a meeting, when a colleague received a message via facebook on his BlackBerry from a friend asking what he’s doing in Berlin!? Looks like his smart-phone told facebook its GPS position without his approval!? That’s scary, isn’t it!

So think twice while exploring the world wide web ;-)

Hacking Havag

Ihr kennt vielleicht die Havag (Hallesche Verkehrs-AG)? Das ist das Verkehrsunternehmen in Halle, befördert uns zu maximalen Preisen bei dürftiger Qualität. Wie auch immer.

Das Unternehmen bietet seinen Kunden ein Widget an, mit dem man vom Wohnzimmer das Eintreffen der Bahnen an der nächstgelegenen Haltestelle monitoren kann. Das ganze nennt sich mobile@home (siehe Bild 1) und ist in Java geschrieben. Ist eigentlich eine feine Sache, man muss nicht mehr nach Bauchgefühl das Haus verlassen, wenn ja doch gerade keine Bahn kommt. Das Fenster nervt jedoch tierisch. Ich hab seit langen auf meinem Schedule einen Eintrag, der mich daran erinnert eine bessere Lösung zu finden. Heute Nacht hab ich mich nun endlich an die Arbeit gemacht.

Das Problem ist wie üblich eine geschlossene Software, keine Dokumentation für jemanden wie mich. Ja es ist Java, also wäre es ein Leichtes die Binaries zu dekompilieren, deren Projekt besteht jedoch aus >1000 Klassen (öhm overhead!) und über den rechtlichen Aspekt bin ich mir da auch nicht sicher. Aber was wird das Tool wohl machen? Es wird einen zentralen Server nach den nächsten Stopps an einer von mir gewählten Haltestelle fragen. Der Server wird dann sicherlich mit den jeweiligen Bahnen antworten. Soweit Client und Server kein kryptisches Protokoll sprechen kann ich also einfach den Netzwerkverkehr der über meine Interfaces geht mitschneiden und nachbauen. Also fix den Sniffer meines Vertrauens und das tolle Tool gestartet. Schnell wurde klar um welchen Server es sich handelt: 83.221.237.42 auf Port 20010 . Und die Sache war auch schon so gut wie gegessen als ich folgende Pakete an mir vorbei rauschen sah:

usr@srv % tcpdump -A -n src 83.221.237.42 or dst 83.221.237.42 and tcp port 20010
[...]
03:19:29.177630 IP 192.168.9.55.39453 > 83.221.237.42.20010: Flags [P.], seq 231:443, ack 108, win 35, options [nop,nop,TS val 28628068 ecr 367433884], length 212
E....2@.@.....  7S..*..N*..["..:~...#.......
...d....POST /init/rtpi HTTP/1.1
Content-Type: text/xml
User-Agent: Java/1.6.0_26
Host: 83.221.237.42:20010
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
Connection: keep-alive
Content-Length: 47


03:19:29.177676 IP 192.168.9.55.39453 > 83.221.237.42.20010: Flags [P.], seq 443:490, ack 108, win 35, options [nop,nop,TS val 28628068 ecr 367433884], length 47
E..c.3@.@..z..  7S..*..N*..[...:~...#.=.....
...d....c..m..getDeparturesForStopS..An der Feuerwachez
03:19:29.229795 IP 83.221.237.42.20010 > 192.168.9.55.39453: Flags [.], ack 490, win 65488, options [nop,nop,TS val 367433990 ecr 28628068], length 0
E..4..@.r.}.S..*..      7N*....:~..\\%....s......
.......d
03:19:29.234736 IP 83.221.237.42.20010 > 192.168.9.55.39453: Flags [.], seq 108:1556, ack 490, win 65535, options [nop,nop,TS val 367433992 ecr 28628068], length 1448
E.....@.r.x1S..*..      7N*....:~..\\%....h......
.......dHTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Length: 1869
Date: Tue, 09 Aug 2011 01:19:29 GMT

S..9S..Soltauer Stra..eS..2011.08.09.03:46:00S..2011.08.09.03:46:00S..trueS..38150S..651S..falseS..falseS..38150:12840S..A FeuerwacheS..falseS..falsezVt..[stringl...l...ingl...
[...]

An der Feuerwache ist die Haltestelle, für die meine Anfrage raus ging, und ein POST -connect mit den Daten ...d....c..m..getDeparturesForStopS..An der Feuerwachez sieht stark nach dem aus, was ich gesucht habe. Kurz darauf kommt auch gleich die Antwort S..9S..Soltauer Stra..eS..2011.08.09.03:46:00S..2011.08.09.03:46:00S..true[..] , und tatsächlich fährt eine Linie 9 in kürze zur Soltauer Straße . Dedüm!! Der Rest ist simpel. Nur noch mit ‘nem Hexeditor (ich empfehle hexcurse) in die Pakete hinein geschaut um zu sehen was genau übermittelt werden muss (die . zwischen den Daten stehen für Zeichen, die in meinem Terminal nicht für mich sichtbar dargestellt werden können. Deren Hexadezimal-Code gibt aber Aufschluss über ihren Wert). Mit ein wenig Trial&Error ist die Geschichte vom Tisch.

Natürlich ist meine Alternative zu dem Widget für jedermann verfügbar:

Als Argument einfach die gewünschte Haltestelle angeben:

usr@srv % ./havag.pl Straßburger Weg
Frage http://83.221.237.42:20010/init/rtpi nach geplanten Stops für 'Straßburger Weg'...

 Zeit   Linie   Richtung
15:33       4   Kröllwitz
15:36       5   Bad Dürrenberg
15:42       5   Kröllwitz
15:44       S   Sonderfahrt
15:45       4   Hauptbahnhof
15:48       4   Kröllwitz
15:51       5   Ammendorf
15:57       5   Kröllwitz
16:00       4   Hauptbahnhof
16:03       4   Kröllwitz
16:06       5   Bad Dürrenberg
16:12       5   Kröllwitz
16:15       4   Hauptbahnhof
16:18       4   Kröllwitz
16:21       5   Ammendorf
16:27       5   Kröllwitz
16:30       4   Hauptbahnhof

Das Protokoll

Vielleicht hat ja jemand Lust weitere Tools zu schreiben, die die “Serverschnittstelle” der Havag benutzen. Daher hier eine kurze Dokumentation des inoffiziellen Protokolls, das mit dem Server gesprochen werden kann.

Eine Anfrage an den Server muss via HTTP-POST an 83.221.237.42:20010/init/rtpi geschehen und die folgenden Inhalte liefern:

[COMMAND]x00[LEN][FUNCTION]x00[LEN][FUNCTIONNAME]x53x00[LEN][ARGUMENT]x7A

Hierbei ist xAB das Zeichen für den Hexwert AB , LEN ist die Länge der darauf folgenden Zeichenkette. Um den Server nach den nächsten Stopps am Rennbahnkreuz zu fragen sendet man als Kommando ein c , als Funktion ein m , und die Funktion heißt getDeparturesForStop . Als Argument wird dann die Haltestelle erwartet. Die Anfrage in HalbHex sieht also wie folgt aus:

cx00x01mx00x14getDeparturesForStopx53x00x0dRennbahnkreuzx7a

und komplett Hexadezimal-kodiert:

x63x00x01x6dx00x14x67x65x74x44x65x70x61x72x74x75x72x65x73x46x6fx72x53x74x6fx70x53x00x0dx52x65x6ex6ex62x61x68x6ex6bx72x65x75x7ax7a

Als Antwort bekommt man die Abfahrtszeiten in den nächsten 60 min. Die Antwort beginnt mit einer Zeichenkette die ich nicht verstehe und vorerst nur verwerfe. Ein Eintrag für eine Bahn startet mit den Hexadezimalwerten x56x74x00x07x5Cx5Bx73x74x72x69x6Ex67x6Cx00x00x00x0D . Darauf folgen die einzelnen Informationen zu dieser Bahn. Eine einzelne Information ist wie folgt kodiert:

x53x00[LEN][INFO]

LEN gibt hier wieder die Länge der folgenden Information an, die Information selbst ist ASCII Klartext. Ein Bahneintrag wird abgeschlossen mit einem x7a (z). Folgende Daten werden übermittelt:

Linie   Endstation      Ankunft                 ???                     N       ???     ???     ???     ???     ???             Angefragte Haltestelle  ???     ???  z
91      Am Steintor     2011.08.09.02:42:35     2011.08.09.01:13:00     false   18824   0       false   false   18824:90120     An der Feuerwache       false   falsez

Das boolsche N gibt an, ob es sich um eine Niederflur-Straßenbahn handelt. Die mit ??? gekennzeichneten Felder verstehe ich (noch) nicht. Vielleicht etwas wie Wagennummer/Typ, ob es eine Verspätung gibt etc. Kann man sicher auch herausbekommen, da sie aber für mich vorerst nicht wichtig sind habe ich mich nicht weiter darum gekümmert.

Meine Beschreibungen sind natürlich alles andere als komplett, für die Korrektheit kann ich auch nicht garantieren. Vielleicht gehört das x00 vor der Längen-Kodierung auch mit zur Längenangabe und ist bei den kurzen Zeichenketten nur immer 0? Wer weiß, in der Praxis funktioniert mein Gehacktes aber (mindestens für mich) ;-)

Update: Wird getDeparturesForStop ohne Argumente gesendet, bekommt man eine Antwort mit allen Verfügbaren Stopps. (via @michas)

Damit ist also der Weg für coole neue Apps geebnet. Vielleicht hat ja jemand von euch eines dieser Smartphones (oder es findet sich ein Sponsor der mir eines zur Verfügung stellt)?

Übrigens flogen auch hin und wieder Pakete mit Inhalten wie diesem vorbei: Apache Tomcat/5.5.17 - Error report . Spricht nicht gerade für das Widget. :-P

Download: Perl: havag.pl (Please take a look at the man-page. Browse bugs and feature requests.)

WordPress WordCloud with R

These days one can frequently read about wordclouds created with R, initiated by the release of the wordcloud package by Ian Fellows on July 23rd. So here I am to put in my two cents.

I thought about creating a wordcloud of a complete blog history, so I build a script that connects to a MySQL database and grabs all published posts and pages. All articles are combined in an huge text, that, when purged from tags and special chars, is visualized as a wordcloud:

[cc lang=”rsplus” lines=”-1” file=”pipapo/R/wordpress-wordcloud.R”][/cc]

Enough code, here is the result for my slight blog:

Smart image, isn’t it? Unfortunately it takes about 30 secs to generate it, otherwise it would be cool to create such a cloud live, for example using rApache.

Download: R: wordpress-wordcloud.R (Please take a look at the man-page. Browse bugs and feature requests.)


Martin Scharm

stuff. just for the records.

Do you like this page?
You can actively support me!