By Martin Scharm on April 10, 2012 at 5:56 pm
I’m currently developing some GUI stuff and was wondering how to let a JScrollPane scroll automatically if it’s already on the bottom and the size of it’s content increases.
For example if you use a JTextArea to display some log or whatever, than it would be nice if the scroll bars move down while there are messages produced, but it shouldn’t scroll down when the user just scrolled up to read a specific line.
To scroll down to the end of a JTextArea can be done with just setting the carret to the end of the text:
1 2 3 4 5 6 7 8 9
| JTextArea log = new JTextArea (20, 20);
log.setEditable (false);
JScrollPane scroller = new JScrollPane ();
scroller.setViewportView (output);
// [...]
log.append ("your message");
log.setCaretPosition (log.getDocument ().getLength ()); |
But we first want to check whether the scroll bar is already at the bottom, and only if that’s the case it should automatically scroll down to the new bottom if another message is inserted.
To obtain the position data of the vertical scroll bar on can use the following code:
1 2 3 4 5 6 7 8 9 10 11 12
| JScrollBar vbar = scroller.getVerticalScrollBar ();
// get the current position
int currentPosition = vbar.getValue ();
// getMaximum () gives maximum + extent.
int maxPosition = vbar.getMaximum () - vbar.getVisibleAmount ();
if (currentPosition == maxPosition)
{
// in this case we want to scroll after the new text is appended
} |
Unfortunately log.append ("some msg") won’t append the text in place, so the size of the text area will not necessarily change before we ask for the new maximum position. To avoid a wrong max value one can also schedule the scroll event:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| private void logText (String text)
{
final JScrollBar vbar = scroller.getVerticalScrollBar ();
// is the scroll bar at the bottom?
boolean end = vbar.getMaximum () == vbar.getValue () + vbar.getVisibleAmount ();
// append some new text to the text area
// (or do something else that increases the contents of the JScrollPane)
log.append (text + "\n");
// if scroll bar already was at the bottom we schedule
// a new scroll event to again scroll to the bottom
if (end)
{
EventQueue.invokeLater (new Runnable ()
{
public void run ()
{
EventQueue.invokeLater (new Runnable ()
{
public void run ()
{
vbar.setValue (vbar.getMaximum ());
}
});
}
});
}
} |
As you can see, here a new event is put in the EventQueue, and this event is told to put another event in the queue that will do the scroll event. Correct, that’s a bit strange, but the swing stuff is very lazy and it might take a while until the new maximum position of the scroll bar is calculated after the whole GUI stuff is re-validated. So let’s be sure that our event definitely happens when all dependent swing events are processed.
Posted in Java, Media, Software
Tagged explained, Java, Programming, trick, user interaction
By Martin Scharm on April 5, 2012 at 5:32 am
Some days ago I discovered galternatives, a GNOME tool to manage the alternatives system of Debian/Ubuntu. It’s really smart I think.
For example to update the default editor for your system you need to update the alternatives system via command line:
1
| update-alternatives --set editor /usr/bin/vim |
or use the interactive version:
1
| update-alternatives --config editor |
To see available browsers you need to run
1
| update-alternatives --list x-www-browser |
The alternatives system is a nice idea I think, but it’s a bit confusing sometimes. Adding a new entry to this system is also a bit complicated and not easy to remember.

Figure 1: galternatives
With
galternatives you’ll get a graphical interface to manage all these things. That really brings light into the dark! Just install it via
1
| aptitude install galternatives |
You’ll be astonished if you give it a try! ;-)
Posted in Debian, Media, Software
Tagged aptitude, Debian, simplification, trick, Ubuntu, user interaction
By Martin Scharm on April 2, 2012 at 4:57 am
I submitted a new version of the YOURLS Firefox extension.
It just contains some minor changes, but I want to inform my loyal readers!
The add-on is currently in the review queue, hopefully this time I’ll get a complete review by the AMO-team ;-)
If you’re crazy you can try the new version, it’s available on SourceForge and on AMO.
UPDATE:
I just received a fully review, so my add-on is finally stable!!
Posted in JavaScript, Media, Network, Web
Tagged Firefox, Iceweasel, Media, Network, Programming, user interaction
By Martin Scharm on November 28, 2011 at 9:41 am
Some days ago IonHunter came into the world!
IonHunter is the tool I’m actually developing to receive one of these diplomas. It’s is a software to identify biomarkers in a huge number of LC/MS runs. IonHunter is able to preprocess mass spectrometry data, to merge multiple runs of the same sample and also to correct retention time shifts to align various experiments.
The whole software is modularly designed and easy to extend with further plugins. So developers feel free to join my development!
Currently it isn’t published, but since it’s written in Java it will run on nearly all operating systems. We focused on usability and comfort for mass spec scientists, who will use the tool.
This is just a small announcement for the recently launched website, you might want to take a look at it!? (-;

IonHunter screen shot
Small hint for my faithful readers: Subscribe to IonHunters newsletter to stay informed and miss no release!
Posted in Bioinformatics, Java, Operating system, Private, Software, University, Web
Tagged Bioinformatics, crazy, Java, MS, Programming, University
By Martin Scharm on November 25, 2011 at 7:57 pm
Yesterday I attended a presentation of a colleague, but unfortunately during his speech the PDF viewer on his laptop crashed.
His supervisor told him to use pdf_presenter_console. Don’t know whether you’ve already heard about this tool? It’s able to display the current slide on the beamer-screen while you can see the next slide on your real screen. Generally a nice idea, but the software seemed to be a bit unstable ;-)
Anyway, I always wanted to find a solution to see some notes for a single slide while the slide is active, and today I set to work.
I searched for tools that are able to open two different PDF’s at once, I tried impressive, some vnc hacks, and so on, until I realized that there is already a smart solution on my laptop using the lightweight PDF viewer XPDF!
XPDF has a nice remote feature, if you run it like
1
| xpdf -remote SOMEID presentation.pdf & |
you can use your terminal to send some commands to the viewer. For example to go to the next slide try the following (see the COMMANDS section of XPDFs man page):
1
| xpdf -remote SOMEID -exec nextPage |
Great, isn’t it!? (if you receive the error error: "nextPage" file not found scroll down to XPDF is buggy)
I think the rest is clear, open two different XPDF-instances, one for the notes and one for the presentation itself:
1 2
| usr@srv % xpdf -remote NOTES notes.pdf &
usr@srv % xpdf -remote PRESENTATION presentation.pdf & |
and define some keys to scroll through the PDFs. You could use xbindkeys to bind the keys to the commands, for example I use F9 to go to the next slide and added the following to my ~/.xbindkeysrc:
1 2
| "xpdf -remote PRESENTATION -exec nextPage && xpdf -remote NOTES -exec nextPage"
m:0x10 + c:75 |
After running
1
| xbindkeys -f ~/.xbindkeysrc |
I’m able to go to the next slide by pressing F9. To find the keycodes for some keys you may use xbindkeys -k or xev. Take a look at the documentation for more information (GER).
Of course presentation.pdf and notes.pdf should have the same number of pages ;-)
XPDF is buggy
The -exec flag didn’t work for me, returning the following error:
1 2
| usr@srv % xpdf -remote SOMEID -exec nextPage
error: "nextPage" file not found |
I tried version 3.02 and also 3.03. The problem is located in the XPDF wrapper script, located in /usr/bin/xpdf. If you take a look at the contents you’ll find the following lines (in my case it’s 25ff):
1 2 3 4 5 6 7
| while [ "$#" -gt "0" ]; do
case "$1" in
-z|-g|-geometry|-remote|-rgb|-papercolor|-eucjp|-t1lib|-ps|-paperw|-paperh|-upw)
cmd="$cmd $1 "$2"" && shift ;;
-title)
title="$2" && shift ;;
-m) |
They simply forgot to define the -exec parameter to take an argument. So nextPage is not seen as argument for -exec and XPDF tries to find a file called nextPage that is obviously not present. To patch this you just need to add -exec like:
1 2 3 4 5 6 7
| while [ "$#" -gt "0" ]; do
case "$1" in
-z|-g|-geometry|-remote|-rgb|-papercolor|-eucjp|-t1lib|-ps|-paperw|-paperh|-upw|-exec)
cmd="$cmd $1 "$2"" && shift ;;
-title)
title="$2" && shift ;;
-m) |
or just use xpdf.real directly and skip the wrapper:
1
| usr@srv % xpdf.real -remote SOMEID -exec nextPage |
Since modifying files in /usr/bin isn’t a good idea I recommend to just substitute xpdf for xpdf.real in your ~/.xbindkeysrc.
That’s it for the moment, I wish you a nice presentation ;-)
Posted in Linux/Unix, Media, Software, University, Unix
Tagged keyboard, Media, Notebook, Rumpel, trick, University, X
By Martin Scharm on November 14, 2011 at 3:46 am
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 using the user script
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.
Posted in JavaScript, Media, Software, Web
Tagged CSS, Firefox, Google, Iceweasel, Media, Network, Programming, trick, userscript
By Martin Scharm on November 13, 2011 at 4:27 am
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.

Figure 1: Share wifi connection diagram
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.

Figure 2: Edit connections
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.

Figure 3: Add wired connection
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.

Figure 4: Configure new connection
Last but not least open a terminal and add a new entry to the nat-table:
1
| 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.
Posted in Linux/Unix, Network, Private, Software, Unix, Web
Tagged Debian, Network, Notebook, trick, Ubuntu
By Martin Scharm on August 9, 2011 at 4:45 pm
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.

Bild 1: Havag Widget
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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| 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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
| #!/usr/bin/perl -w
###############################
#
# Havag departure scheduler
#
# written by Martin Scharm
# see http://binfalse.de
#
###############################
use warnings;
use strict;
use Encode;
require LWP::UserAgent;
# adresse an die die anfrage geht
my $SERVER = "http://83.221.237.42:20010/init/rtpi";
# zeichen vor der haltestelle
my @SENDPRE = ('63','00','01','6d','00','14','67','65','74','44','65','70','61','72','74','75','72','65','73','46','6f','72','53','74','6f','70','53','00');
# zeichen nach der haltestelle
my @SENDPOST = ('7A');
# regex um bahnen zu trennen
my @BSPLIT = ('56','74','00','07','5C','5B','73','74','72','69','6E','67','6C','00','00','00','0D','53','00','2E');
my @WSPLIT = ('53','00','2E');
my $script = $0;
my $stop = "@ARGV";
usage ($script, "keine Haltestelle angegeben!") if (!$stop);
usage ($script) if ($stop =~ /^-?-h/);
print "Frage $SERVER nach geplanten Stops für '$stop'...\n\n";
my $content = string_from_hex (@SENDPRE) . sprintf('%c', length (decode("utf8", $stop))) . $stop . string_from_hex (@SENDPOST);
my $ua = LWP::UserAgent->new;
$ua->timeout(10);
$ua->agent('binfalse-client/1.0 (binfalse.de)');
my $request = HTTP::Request->new('POST', $SERVER);
$request->content($content);
my $response = $ua->request ($request);
# kam 200 OK zurück?
if ($response->is_success)
{
my %entries = ();
my $linienlen = length "Linie";
my $stationslen = length "Richtung";
my $datelen = length "Zeit";
# response in bahnen splitten
my $splitter = string_from_hex(@BSPLIT);
my @bahnen = split (/$splitter/s, $response->content);
$splitter = string_from_hex (@WSPLIT);
foreach my $b (@bahnen)
{
# bahn informationen extrahieren
my @w = split(/$splitter/s, $b);
if (@w > 3)
{
my @datum = split (/[.:]/, $w[2]);
$linienlen = length $w[0] if (length $w[0] > $linienlen);
$stationslen = length $w[1] if (length $w[1] > $stationslen);
$datelen = length $datum[3].":".$datum[4] if (length $datum[3].":".$datum[4] > $datelen);
$entries{$w[2].$w[0].$w[1]} = [$w[0], $w[1], $datum[3].":".$datum[4]];
}
}
# in tabellenform ausgeben
printf "%".$datelen."s %".$linienlen."s %-".$stationslen."s\n", "Zeit", "Linie", "Richtung";
foreach my $e (sort keys %entries)
{
printf "%".$datelen."s %".$linienlen."s %-".$stationslen."s\n", $entries{$e}[2], $entries{$e}[0], $entries{$e}[1];
}
}
else
{
# da lief wohl etwas schief
print $response->content . "\n";
die $response->status_line;
}
# ähm, usage...
sub usage
{
my $script = shift;
my $msg = shift;
print $msg."\n" if $msg;
print "USAGE: $script HALTESTELLE\n";
exit 1;
}
# einen string aus hex codes zusammen zaubern
sub string_from_hex
{
my @code = @_;
my $string = "";
foreach my $c (@code)
{
$string .= sprintf('%c',hex($c));
}
return $string;
} |
Als Argument einfach die gewünschte Haltestelle angeben:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| 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:
1
| [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:
1
| cx00x01mx00x14getDeparturesForStopx53x00x0dRennbahnkreuzx7a |
und komplett Hexadezimal-kodiert:
1
| 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:
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:
1 2
| 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
Posted in Java, Media, Network, Perl, Software, Web
Tagged analyzed, crazy, debug, explained, hacked, Halle, Java, Media, Network, Programming, simplification, trick
By Martin Scharm on August 3, 2011 at 11:46 am
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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| library(RMySQL)
require(wordcloud)
require(RColorBrewer)
# special chars we want to delete
sent=c(",", "\\.", ";", "=", ":", "\\?", "!", "-", "\\(", "\\)", "\\*", "&", "%", "$", "\\+", "'", "<", ">", "\\[", "\\]", "\\{", "\\}", "\\/")
# wordpress bb-codes, also delete!
bbcd=c("\\[cc.+?/cci?\\]", "\\[latex.+?/latex\\]", "\\[caption.+?/caption\\]")
# and of course delet HTML tags
tags=c("a", "b", "abbr", "strong", "em", "i", "p", "more", "td", "table", "tr", "th", "script", "h1", "h2", "h3", "h4", "h5", "h6", "div", "span", "small","img")
tags=paste("</?", tags, "[^>]*>", sep="")
# combine all purge-regex'
repl=c(tags, bbcd, sent)
# connect to your DB
con <- dbConnect(MySQL(), user="USER", password="PASSPHRASE", dbname="DB", host="HOST")
# select all published articles
res <- dbGetQuery(con, "SELECT post_content, post_title FROM wp_posts WHERE post_status='publish'")
#combine them in a text
text=paste(as.matrix(res), collapse=" ")
dbDisconnect(con)
# replace all unwanted stuff
tmp=sapply(repl, function (r) text<<-gsub(r, " ", text))
# here are our words:
words=table(strsplit(tolower(text), "\\s+"))
# remove words with _bad_ chars (non utf-8 stuff)
words=words[nchar(names(words), "c")==nchar(names(words), "b")]
# remove words shorter then 4 chars
words=words[nchar(names(words), "c")>3]
# remove words occuring less than 5 times
words=words[words>4]
# create the image
png("/tmp/cloud.png", width=580, height=580)
pal2 <- brewer.pal(8,"Set2")
wordcloud(names(words), words, scale=c(9,.1),min.freq=3, max.words=Inf, random.order=F, rot.per=.3, colors=pal2)
dev.off() |
Enough code, here is the result for my slight blog:

WordPress WordCloud with R
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 with for example rApache.
Posted in Media, Private, R, Software, Wordpress
Tagged Blog, GNU, Media, Programming, trick, Wordpress
By Martin Scharm on August 1, 2011 at 1:08 am
I just installed a new server from HP, a ProLiant DL180 G6. Here are some notes about the setup.
To check the hardware status you need to install the ProLiant Support Package. Running a Debian/Ubuntu you should import the HP PSP mirror in your sources.list. It can be found here, you might include something like:
1
| deb http://downloads.linux.hp.com/SDR/downloads/proliantsupportpack/Debian stable current/non-free |
After an aptitude update you’ll find some new packages. I recommend to install hpaclui to speak to your raid-controllers and hp-health to interact with your hardware.
With hpaclui you can ask the raid-controllers for some information:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| usr@srv % hpacucli ctrl all show status
Smart Array P123 in Slot 1
Controller Status: OK
Cache Status: OK
Battery/Capacitor Status: OK
usr@srv % hpacucli ctrl slot=1 show config
Smart Array P123 in Slot 1 (sn: SOMESN )
array A (SAS, Unused Space: 0 MB)
logicaldrive 1 (99.99 GB, RAID 1, OK)
physicaldrive 1I:1:1 (port 1I:box 1:bay 1, SAS, 99 GB, OK)
physicaldrive 1I:1:2 (port 1I:box 1:bay 2, SAS, 99 GB, OK)
[...]
array B (SAS, Unused Space: 0 MB)
logicaldrive 2 (99.99 TB, RAID 5, OK)
physicaldrive 1I:1:3 (port 1I:box 1:bay 3, SAS, 99 TB, OK)
physicaldrive 1I:1:4 (port 1I:box 1:bay 4, SAS, 99 TB, OK)
[...]
Expander 250 (WWID: SOMESN, Port: 1I, Box: 1)
Enclosure SEP (Vendor ID HP, Model SOMEMD) 248 (WWID: SOMESN, Port: 1I, Box: 1)
SEP (Vendor ID SOMEVNDR, Model SOMEMD) 249 (WWID: SOMESN) |
So you get an idea of your storage.
The hp-health packages comes with a tool called hpasmcli. It’s used to query all the hardware states:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| usr@srv % hpasmcli -s "SHOW"
Invalid Arguments
SHOW ASR
SHOW DIMM
SHOW FANS
SHOW HT
SHOW NAME
SHOW PORTMAP
SHOW POWERMETER
SHOW POWERSUPPLY
SHOW SEL
SHOW SERVER
SHOW TEMP
SHOW TPM
SHOW UID
usr@srv % hpasmcli -s "SHOW POWERSUPPLY"
Power supply #1
Present : Yes
Redundant: Yes
Condition: Ok
Hotplug : Not supported
Power supply #2
Present : Yes
Redundant: Yes
Condition: Ok
Hotplug : Not supported |
Both tools are very easy to use and give a great overview about the health. So I immediately developed a monitoring plugin that parses the output of those runs. I came to the point, that I wasn’t able to find some documentation about the hpasmcli tool. Most of its output was clear, but I don’t know what happens if a fan breaks. The output with working fans looks like:
1 2 3 4 5 6 7 8 9 10 11 12
| usr@srv % hpasmcli -s "SHOW FANS"
Fan Location Present Speed of max Redundant Partner Hot-pluggable
--- -------- ------- ----- ------ --------- ------- -------------
#1 SYSTEM Yes NORMAL 45% Yes 0 No
#2 SYSTEM Yes NORMAL 43% Yes 0 No
#3 SYSTEM Yes HIGH 100% Yes 0 No
#4 SYSTEM Yes HIGH 100% Yes 0 No
#5 SYSTEM Yes NORMAL 22% Yes 0 No
#6 SYSTEM Yes NORMAL 21% Yes 0 No
#7 SYSTEM Yes NORMAL 47% Yes 0 No
#8 SYSTEM Yes NORMAL 46% Yes 0 No |
So what if a fan is broken? Is it still Present and the Speed-string just changes to NONE or something like that? I send a support request to HP, but all they respond was a premium-rate number to call. Seems that my understanding of service differs from theirs. Since I don’t know how the output looks like in an error case (I don’t want to stick pencils into new machines) the plugin can’t decide whether the fans are OK. If you want to use my plugin you need to skip fan-checks until HP publishes a document with possible values.
IMHO a public tool should be open source, so I can get those information on my own, or at least well documented!
Btw. HP if you read this, please include some permanent links to your web interface ;-)
Posted in Hardware, Software, University
Tagged aptitude, Debian, University
By Martin Scharm on July 10, 2011 at 11:47 pm
Today a lot of great mails arrived at my inbox. In one of them I was reading I’ve just added your feed to the site.
Where did this mail come from?
The sender of the email was Tal Galili. He is a researcher in BioStatistics at the Tel Aviv University, very active around the internet. He also originated R-Bloggers and in this email he told me that I’m recruited ;-)
What is R-Bloggers
R-Bloggers is an aggregation of more than 200 bloggers writing about GNU’s R and some statistics/math/hacks that can be done using R. If you didn’t heard about R-Bloggers I strongly recommend to take a look at their website. I’m following this project since a while, it’s a great fusion of brainiacs! So I’m proud to have my modest R-related articles listed between them.
Btw. if you like R-Bloggers and/or have some R experiences yet you should also take a look at the ‘R’ programming Wikibook. Contributing your knowledge is greatly appreciated!
Let’s see what the future brings, happy hacking!
Posted in R, Software, Web
Tagged Bioinformatics, Blog, GNU, Network
By Martin Scharm on July 8, 2011 at 6:48 pm
…sts (of course!). Yesterday I just installed a rating plugin, inspired by these stackexchange platforms.
Searching through the WordPress plugin directory didn’t make me happy. All existing plugins lack of desired features. After some tests I decided to modify UpDownUpDown of Dave Konopka. It’s a nice plugin, but still didn’t match my criteria. For example guests were not allowed to vote, there were some XHTML bugs and I didn’t like the style. So I created a patch (it’s attached..) and sent it to Dave (I don’t yet have a github account). He told me that he’ll take a look at it and might apply it to the official plugin, so if you also want to use this rating plugin with my additional features just keep the URL in mind and watch out for a new version.
The special version I’m using here right now has of course some more slight changes, to have it perfectly matched to my own blog.
So you are now able to vote for articles, positive or negative, to give me a hint what my visitors like to read ;-)
I additionally installed a further page that lists my articles sorted by votes: top. So you can get a smart overview of best/worst content.
With this in mind: Happy voting! ;-)
Posted in HTML, JavaScript, Media, PHP, Software, Website, Wordpress
Tagged Ajax, Blog, hacked, Network, Programming, user interaction, Wordpress
By Martin Scharm on July 7, 2011 at 11:47 am
Ever worried about these disgusting packets leaving your network interface!? Why not creating your own packets?
Of course it’s more than nonsense creating all packets on your own, but sometimes there might be a reason making you wish you could..
For ex. for my last article I searched for a possibility to modify some contents of a packet. First I thought about using iptables, but than I found a nice tool: scapy!
With scapy you can create your own packets, IP/TCP/UDP whatever! It is very heavy but comes with an user-friendly interface. Using Debian/Ubuntu you need to install python-scapy:
1
| aptitude install python-scapy |
To open the interface just run scapy. You can easily create an IP packet by typing something like this:
1 2 3 4 5
| >>> ippacket=IP()
>>> ippacket.dst='binfalse.de'
>>> ippacket.ttl=12
>>> ippacket
<IP ttl=12 dst=Net('binfalse.de') |> |
So an IP packet is stored in the variable ippacket. This packet will be send to binfalse.de and has a ttl of 12 (if there are more than 12 network nodes between your machine and the target it will disappear and never arrive at the target).
Let’s create some TCP stuff:
1 2 3 4 5
| >>> tcpcrap=TCP()
>>> tcpcrap.sport=1337
>>> tcpcrap.dport=80
>>> tcpcrap
<TCP sport=1337 dport=www |> |
We stored some TCP information in tcpcrap. This packet will be send through your port 1337 and hopefully arrive at port 80 (in general a webserver is listening on port 80).
That’s it for the networking part. Last but not least we will create some data to send:
1 2 3
| >>> data='GET / HTTP/1.1 \nHost: binfalse.de\n\n'
>>> data
'GET / HTTP/1.1 \nHost: binfalse.de\n\n' |
Combining all parts we’ll get a very nice packet, sending it will trigger my webserver to send the main page of my website (Sending exactly this packet won’t ever result in any website from my webserver. Why? Just think about…):
1 2 3 4 5 6
| >>> whole=ippacket/tcpcrap/data
>>> whole
<IP frag=0 ttl=12 proto=tcp dst=Net('binfalse.de') |<TCP sport=1337 dport=www |<Raw load='GET / HTTP/1.1 \nHost: binfalse.de\n\n' |>>>
>>> send(whole)
.
Sent 1 packets. |
Well done!
Ok, that’s very much to do. But fortunately it’s just that much code for explanation, you can send the same packet in a single line:
1 2 3
| >>> send(IP(ttl=12,dst='binfalse.de')/TCP(sport=1337,dport=80)/'GET / HTTP/1.1 \nHost: binfalse.de\n\n')
.
Sent 1 packets. |
Very smart, isn’t it? You can also sniff whooshing packets! But something like this I won’t explain, find out by yourself ;-)
Posted in Network, Programming, Software, Web
Tagged analyzed, aptitude, crazy, Debian, explained, hacked, Network, remote, trick