In diesem Blog habe ich ja schon öfters über rsslounge geschrieben. Vor einiger Zeit habe ich einen webbasierten RSS Reader entwickelt, der auf PHP und MySQL aufsetzt und als Open Source Projekt jedem frei zur Verfügung steht.

Screenshot rsslounge

Die letzten Monate habe ich den Reader nun auf Herz und Nieren getestet und selbst jeden Tag verwendet. Zudem habe ich Feedback gesammelt und den Reader im Detail verbessert. So kann er jetzt beispielsweise auch fehlerhaftes HTML in Feed Einträgen verarbeiten und korrigieren. Die permanente Nutzung über die letzten Monate hat gezeigt, dass der Reader stabil ist und einwandfrei arbeitet. Daher habe ich mich entschlossen den aktuellen Stand als Version 1.0 zu veröffentlichen.

Ihr könnt die aktuelle Version jederzeit auf der Projektseite http://rsslounge.aditu.de herunterladen. Wer skeptisch ist, oder rsslounge noch nicht kennt, findet dort natürlich auch eine Demo Installation und kann alles erst einmal testen. Interessierte können auch die Entwicklung verfolgen oder einen Blick auf den Quellcode werfen. Hierfür gibt es eine Projektseite auf Google Code.

Feedback, Bugmeldungen oder Anmerkungen sind jederzeit willkommen. Ihr könnt hier kommentieren, das Kontaktforumlar auf http://rsslounge.aditu.de oder das Tracking System von Google Code verwenden.

Schon vor einiger Zeit bin ich auf eine sehr schöne Lösung gestoßen, mit der sich ein sicherer Login mit Einmalpassworte realisieren lässt. Dabei wird ein Hardware USB Dongle verwendet, welcher nach einem Druck auf einen Taster ein Einmalpasswort generiert. Die serverseitige Prüfung kann aus einer beliebigen Sprache heraus passieren. Für mich bietet sich hier natürlich PHP an. In meinem Fall verwende ich für die Applikation das Zend Framework, aber die hier vorgestellte Lösung ist allgemein verwendbar und unabhängig vom restlichen Backend.

Was ist ein Einmalpasswort?

Wie der Name bereits sagt, kann ein Einmalpasswort nur für einen Login verwendet werden. Dann erlischt die Gültigkeit und ein neues Einmalpasswort wird benötigt. Ein solches Passwort wird durch eine spezielle Hardware (hier OpenKubus Stick) erzeugt. Eine genaue Definition findet ihr auch in Wikipedia, wo auch verschiedene Algorithmen vorgestellt werden. Der englischsprachige Begriff ist One Time Passwort und hierzu findet man auch auf dem internationalen Wikipedia eine interessante Beschreibung.

Vorteile Einmalpasswörter

Zu Beginn stellt sich die Frage, welche Vorteile ein Login mit Einmalpasswörter mit sich bringt. Hier macht es Sinn, sich der Problemstellung von Seite der Bedrohungen aus zu nähern und zu analysieren, ob ein solches System für den eigenen Anwendungsfall eine sinnvolle Maßnahme ist oder nicht. Mögliche Bedrohungen, gegen die ein Einmalpasswort eine risikominimierende Wirkung hat sind:

  • an erster Stelle natürlich eine sichere Authentifikation: nur wer den Stick besitzt kann sich auch in das System einloggen
  • ungeeigneter Umgang mit Passwörter: es kann nicht sichergestellt werden, dass Benutzer unsichere Passwörter verwenden
  • Abhören von Leitungen/Ausspähen des Passwortes: es kann passieren, dass in einer unsicheren Umgebung die eigenen Zugangsdaten abgehört werden. Hier wäre auch eine verschlüsselte Verbindung eine empfehlenswerte Gegenmaßnahme, aber auch ein Einmalpasswort bietet hier einen geeigneten Schutz, da dieses nur für einen Login gültig ist.
  • systematisches Ausprobieren von Passwörter: es kann passieren, dass ein Brute Force Angriff auf das System durchgeführt wird. Ein Einmalpasswort ist in der Regel sehr lange und somit schwerer zu knacken
  • Trojanische Pferde: am Clientrechner könnte ein Schadprogramm installiert sein, welches die Zugangsdaten ausspäht

Natürlich ist ein Einmalpasswort kein Allheilmittel. So schützt es nicht vor Pishing Angriffen, oder Man in the Middle Attacken, wo die Logindaten abgefangen und erst garnicht an den Server gesendet werden.

Komponenten

An dieser Stelle will ich zuerst die verschiedenen Komponenten vorstellen, die für die Lösung verwendet wurden. Natürlich ist alles OpenSource und frei verfügbar. Auch der Hardwaredongle ist frei und recht günstig zu erstehen.

OpenKubus

OpenKubus

Der OpenKubus ist ein kleiner, handlicher USB Stick (der Problemlos an den Schlüsselbund passt), dessen Hardwarelayout frei verfügbar ist und der frei programmiert werden kann. Wird der Stick an einem Rechner angesteckt, so wird er als Tastatur erkannt. Ein Druck auf einen Taster führt dazu, dass der Stick ein neues Einmalpasswort generiert und als Tastatureingabe an den Rechner sendet. Es reicht also, den Cursor auf das Eingabefeld im Login Formular zu setzen und der Stick schießt sein Passwort hinein. Dabei ist der Stick kompatibel zu nahezu allen Systemen, weil er als einfache Tastatur arbeitet.

Der Stick kostet 24,95 Euro und kann im embedded projects Shop bestellt werden. Beispielprogramme und die nötige Software um den Stick zu programmieren (was unter Linux recht leicht möglich ist), sind auf der google code Projektseite zu finden. Dort gibt es auch Anleitungen und ein Beispielserver in Perl. Der OpenKubus kann auch für einen sicheren Linux Login (PAM) verwendet werden.

phpseclib

phpseclib

Um das Passwort zu entschlüsseln (AES), benötigt man eine passende Bibliothek. phpseclib bietet eine komfortable und objektorientierte Lösung, die auf keine PHP Extensions oder ähnliches angewiesen ist. Diese Bibliothek ist in PHP geschrieben, entwickelt man in einer anderen Sprache, so benötigt man irgendwie eine Möglichkeit mit AES Verschlüsselung zu arbeiten.

phpseclib ist aus meiner Sicht für Verschlüsselung allgemein ein Tipp. Es stehen Klassen für die verschiedensten Algorithmen zur Verfügung (z.B. RSA, SSH, DES, 3DES, AES uvm.). Die Bibliothek ist OpenSource und steht unter der LGPL Lizenz.

Ablauf

Um die unten stehende Implementierung zu verstehen, muss man zuerst den gesamten Ablauf kennen. Dieser ist recht simpel. Zuerst muss der Stick einmalig vorbereitet werden. Der Authentifizierungsprozess kann dann beliebig oft durchgeführt werden.

Initialisierung

Der Stick muss mit dem AES Schlüssel und einem zufälligen Datenblock beschrieben werden. Dies funktioniert recht einfach unter Linux:

sudo ./stick-write -p AESKeyundDatenblock

Wobei AESKeyundDatenblock ein 46 Byte langer String ist, der zuerst aus dem AES Key (32 Bytes lang) und dann dem Datenblock (14 Bytes lang) besteht. Der AES Schlüssel und der Datenblock müssen auch dem Server bekannt sein. Zudem muss auf dem Server der Zähler auf 0 gesetzt werden (=das nächste Einmalpasswort ist das erste).

Authentifizierung

Client:

  1. Der Stick wird am Client eingesteckt und das Loginformular wird aufgerufen. Nun gibt der Benutzer seinen Benutzernamen ein, setzt den Cursor auf das Einmalpasswort-Feld und drückt auf den Taster am Stick.
  2. Der Stick erzeugt nun das Einmalpasswort: Ein interner Zählwert wird mit dem Datenblock verknüpft und mit dem angegebenen Schlüssel (key) AES verschlüsselt. Anschließend erhöht der Stick seinen internen Zähler um eins.
  3. Das so generierte Einmalpasswort wird base64 kodiert, so dass es durch gewöhnliche (ASCII) Zeichen darstellbar ist.
  4. Der Stick sendet das so generierte, base64 kodierte Einmalpasswort als Tasteneingabe und befüllt so das selektierte Feld. Ein Klick auf “Login” sendet das HTML Formular wie bei einem gewöhnlichen Login an den Server.

Server:

  1. Der Server nimmt die Anfrage entgegen und lädt seinen eigenen, zum Stick passenden AES Schlüssel und Datenblock.
  2. Dann wird der durch den Client übermittelte base64 String erst einmal korrigiert: ein z am Anfang kennzeichnet ob ein amerikanisches Tastaturlayout vorliegt (entsprechend müssen alle z durch y und alle y durch z ersetzt werden). Zudem werden einige Sonderzeichen ersetzt.
  3. Anschließend wird das noch verschlüsselte Einmalpasswort von base64 wieder in einen Bytevektor dekodiert.
  4. Nun wird das Einmalpasswort mit AES entschlüsselt.
  5. der Zählstand wird ausgelesen und der Datenblock entnommen.
  6. Der Login ist erfolgreich wenn der gegebene Zählstand größer dem Zählstand am Server ist und der gegebene Datenblock mit dem intern gespeicherten übereinstimmt.
  7. War der Login erfolgreich, so wird am Server der Zählstand des Sticks übernommen: es werden nur Einmalpasswörter akzeptiert, die einen höheren Zählstand haben (alte funktionieren also nicht mehr).

Auch wenn sich alles nun nach einer Menge Arbeit anhört, ist die Implementierung übersichtlich. Ich habe dazu in meiner Applikation einen Action Helper verwendet (in Zend Framework Applikationen eine Hilfsklasse, die in allen Controller zur Verfügung steht). An dieser Stelle eine PHP Funktion, welche nur von phpseclib abhängt und alle Schritte durchführt, die oben unter Server gelistet sind. Jeder Schritt wird nochmal als Kommentar erklärt.


/**
 * @param string $givenOtp Einmalpasswort, dass geprueft werden soll
 * @param string $aesKey der AES Schluessel und Datenteil
 * @param int $number aktueller Zaehlstand des Servers
 */
function otp($givenOtp, $aesKey, $number) {
	// AES Schluessel besteht aus
	// erste 32 Byte: AES Key
	// restliche 14 Byte: Datenblock
	$key  = substr($aesKey, 0, 32);
	$data = substr($aesKey, 32, 14);

	// base64 Kodierung des Sticks korrigieren
	$givenOtp = rtrim($givenOtp);

	// Sonderzeichen in korrekte Sonderzeichen umwandeln
	// (diese werden vom Stick anders vorgegeben, um von
	// unterschiedl. Tastaturlayouts unabhängig zu werden)
	for($i = 0; $i < strlen($givenOtp); $i++) {
		if($givenOtp[$i] == " ") { $givenOtp[$i] = "/"; }
		elseif($givenOtp[$i] == ".") { $givenOtp[$i] = "="; }
		elseif($givenOtp[$i] == "-") { $givenOtp[$i] = "+"; }
	}

	// erstes Zeichen pruefen ob z oder y
	// abhaengig davon alle y durch z ersetzen und umgekehrt
	$z = $givenOtp[0];
	$crypted = substr($givenOtp, 1);

	if($z == "y" or $z == "Y") {
		for($i = 0; $i < strlen($crypted); $i++) {
		  if	($crypted[$i] == 'y') { $crypted[$i] = "z"; }
		  elseif($crypted[$i] == 'Y') { $crypted[$i] = "Z"; }
		  elseif($crypted[$i] == 'z') { $crypted[$i] = "y"; }
		  elseif($crypted[$i] == 'Z') { $crypted[$i] = "Y"; }
		}
	}

	if($z == "Y" or $z == "Z") {
		for($i = 0; $i < strlen($crypted); $i++) {
			if(ctype_upper($crypted[$i])) {
				$crypted[$i] = strtolower($crypted[$i]);
			} else {
				$crypted[$i] = strtoupper($crypted[$i]);
			}
		}
	}

	// base64 String nun in binary dekodieren
	$crypted = base64_decode($crypted);

	// gegebenes One Time Passwort mit AES entschluesseln
	$aes = new Crypt_AES();
	$aes->disablePadding();
	$aes->setKey($key);
	$plain = $aes->decrypt($crypted);

	// entschluesseltes Passwort aufteilen in

	// aktueller Zaehlstand
	$i	 = substr($plain, 0,1);
	$j	 = substr($plain, 1,1);
	$n	 = ord($i) + (ord($j) << 8);

	// und Datenblock
	$plain = substr($plain, 2, strlen($plain)-2);

	// wenn Datenblock korrekt und Laufnummer nach aktueller Nummer:
	// aktuelle Nummer zurueckgeben (Login korrekt)
	if(($plain == $data) and ($n > $number)) {
		return $n;
	} else {
		return false;
	}
}

Natürlich kann das Entschlüsseln auch mit der mcrypt Erweiterung von PHP durchgeführt werden. So benötigt man keine zusätzliche Bibliothek wie phpseclib. Um das Passwort mit mcrypt zu entschlüsseln, muss der Codeteil


$aes = new Crypt_AES();
$aes->disablePadding();
$aes->setKey($key);
$plain = $aes->decrypt($crypted);

durch die entsprechenden mcrypt Aufrufe ersetzt werden:


$td = mcrypt_module_open("rijndael-128", "", "ecb", "");
$iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_DEV_RANDOM);
mcrypt_generic_init($td, $key, $iv);
$plain = mdecrypt_generic($td, $crypted);

Fazit

Ich bin mit der Lösung sehr zufrieden. Die AES Schlüssel/Datenblöcke lassen sich komfortabel in der Datenbank ablegen und auch leicht ändern, falls der Stick verloren geht. Besonders wenn man oft in unsicheren Netzen unterwegs ist (z.B. in der Firma oder an der Uni, in Internet Cafes usw.) ist die Lösung praktisch. Es müssen keine langen Einmalpasswörter von einem Display abgeschrieben werden und der Stick läuft gleichermaßen unter Linux und Windows. Die Integration in die eigene Applikation ist denkbar einfach.

Einziger Nachteil: der Stick hat keine Zeitkomponente, d.h. jemand könnte das Passwort abgreifen und dann die Netzverbindung kappen. Erst wenn sich der Besitzer einloggt, wird das zuvor abgepishte Passwort ungültig. Ebenso lassen sich mehrere Passwörter auslesen: so lange der Besitzer sich nicht einloggt, bleiben sie alle gültig.

Erweiterbarkeit ist eine zentrale Anforderung an nahezu jede Applikation. Dabei stellt man relativ schnell fest, dass dies auf verschiedenen Ebenen einer Anwendung passieren kann. Auf einer elementaren Ebene spiegelt sich die Erweiterbarkeit in der grundlegenden Architektur wieder, kann aber auch sehr hoch angesiedelt werden. Beispielsweise in einer Pluginschnittstelle für externe Programmierer.

Ralf beschreibt in seinem Buch eine gute Möglichkeit eine auf dem Zend Framework basierende Applikation modular zu strukturieren (mit Teilmodule, die nach belieben eingefügt oder ausgehängt werden können). Häufig ist aber auch das zu weit gefasst und eine viel klarere und schmalere Schnittstelle reicht vollkommen aus. Gesucht ist also ein Mechanismus, der Teilfunktionen dynamisch nachlädt und in die Gesamtapplikation einbindet.

Ein Beispiel: mein webbasierter RSS Reader rsslounge kann verschiedene Quellen verfolgen und verarbeiten. So liest er gewöhnliche RSS Feeds. Aber weiterführend kann er auch RSS Feeds als Quelle für Bilder verarbeiten (und extrahiert aus diesen RSS Feeds nur die Bilder). Möglich ist aber auch deviantArt als Datenquelle. Sprich jede mögliche Datenquelle ist denkbar. Nicht nur RSS Feeds, sondern auch normale HTML Seiten (die in irgend einer Weise geparst werden) oder auch der Zugriff auf einen Email Account wäre denkbar. Es macht also Sinn hier eine Abstraktionsebene einzubauen und die Möglichkeit zu schaffen einfach neue Datenquellen hinzuzufügen.

Die Vorgehensweise, welche ich für rsslounge gewählt habe ist simpel: jede Datenquelle ist eine Klasse, welche eine fest vorgegebene abstrakte Basisklasse (rsslounge_source) implementieren muss. Diese abstrakte Basisklasse gibt die Methoden vor, die unbedingt angeboten werden müssen (z.B. load() um die Datenquelle abzurufen).

abstract class rsslounge_source {
	abstract public function load($url);
	abstract public function getHtmlUrl();
	abstract public function getId();
	//...
}

Alle Datenquellen, welche die abstrakte Basisklasse implementieren, werden in einem festen Verzeichnis abgelegt. Die Gesamtapplikation durchsucht diesen Pfad nach verfügbare Datenquellen, prüft, ob sie die nötige Basisklasse implementieren und verwendet sie dann im Programm. Soll beispielsweise ein neues Feed hinzugefügt werden, so werden alle verfügbaren Datenquellen gesucht und im Dialog gelistet:

Feed hinzufügen

Angenommen ich entschließe mich ein Jahr später eine neue Datenquelle für die API von Google Analytics zu realisieren, so muss ich lediglich eine neue Klasse von rssloung_source ableiten, die entsprechenden Methoden implementieren und diese dann in das Verzeichnis ablegen.

Dieses Prinzip wird auch Hollywood Prinzip genannt: “Don’t call us, we call you”. Die Datenquelle Klasse bietet Methoden an, welche von der Gesamtapplikation im Bedarfsfall aufgerufen werden. Das Plugin muss von der Gesamtapplikation nichts wissen und ausschließlich ihre eigene Funktionalität und damit die Schnittstelle realisieren.

Die Implementierung basiert auf den Reflection Mechanismus der seit PHP 5 zur Verfügung steht. Mit Hilfe der Reflection Klassen können zur Laufzeit Klassen geladen und deren Eigenschaften ausgelesen werden. Zudem kann über diesen Weg die Klasse dann auch instanziiert werden:

$class = new ReflectionClass("plugin_rss_feed");
$baseClass = new ReflectionClass("rsslounge_source");
$class->isSubclassOf($baseClass); // true wenn plugin_rss_feed die Klasse rsslounge_source implementiert
$obj = $class->newInstance();

Sollen, wie im obigen Beispiel, alle verfügbaren Datenquellen gelistet werden, so wird das Verzeichnis mit den Datenquellen nach PHP Dateien durchsucht, geprüft ob diese von rsslounge_source abgeleitet sind und falls dies zutrifft instanziiert. Alle Objekte der so gefundenen Klassen werden in ein Array gespeichert und dann für die weitere Verarbeitung an die Gesamtapplikation übergeben (die diese Klassen dann auflistet):

$pluginLocation = "/plugins";
$pluginPrefix = "plugins_";
$plugins = array();
foreach(scandir($pluginLocation) as $file) {
	if(is_file($pluginLocation . "/" . $file)
	&& substr($file,0,1)!="."
	&& strpos($file,".php")!==false) {

		$classname = str_replace(".php","",$file);
		$class = new ReflectionClass($pluginPrefix.$classname);

		if($class->isSubclassOf(new ReflectionClass("base_plugin")))
			$plugins[$pluginPrefix.$classname] = $class->newInstance();
	}
}

Natürlich macht es hier Sinn einen Cache einzubauen, da sich die verfügbaren Klassen nicht oft ändern. Zend_Cache bietet hier eine einfache Möglichkeit so ein Array dateibasiert oder mittels memcached zu cachen.

Für meinen RSS Reader habe ich diesen Mechanismus zum Laden der Datenquellen in einen Action Helper ausgelagert. So steht diese Funktionalität in der gesamten Applikation zur Verfügung. Wer an Details interessiert ist, sei an dieser Stelle auf Google Code verwiesen, wo der Quellcode von rsslounge zu finden ist.

Die Firma Mayflower ist mir ja schon länger ein Begriff, da sie sehr im Open Source Bereich um PHP tätig ist. Um die Verbreitung des Zend Frameworks zu fördern, verschenkt Mayflower Poster mit den wichtigsten Methodenaufrufen, Argumenten und Beispielaufrufen. Einfach das Kontaktformular ausfüllen und das Poster wird einem versandkostenfrei zugeschickt.

Eine feine Sache, mein Poster ist heute angekommen und echt top:

Zend Framework Poster

Ein PHP Web Security Poster soll in Arbeit sein. Ich bin gespannt und werd jetzt einen passenden Platz für mein Poster suchen…

Frameworks und Bibliotheken zu verwenden hat viele Vorteile. Vor allem spart es aber Zeit, weil viele Funktionen so schon out of the box zur Verfügung stehen und wozu auch für jedes Projekt das Rad neu erfinden. In diesem Blogeintrag will ich alle Bibliotheken und Frameworks vorstellen, die ich für meinen aktuellen Feed Reader rsslounge verwendet habe. Die Liste ist als kleine Empfehlung zu verstehen und soll gleichzeitig einen kleinen Einblick in rsslounge geben.

Zend Framework

Zend Framework

Das Zend Framework ist ein objektorientiertes PHP Framework, das auf dem MVC Pattern basiert und viele viele Funktionen bietet. Das Zend Framework ist in diesem Blog ja ohnehin ein Thema und deshalb will ich an dieser Stelle dazu nicht schreiben. Einen ersten Überblick gebe ich hier, wobei natürlich innerhalb des letzten Jahres einiges hinzu gekommen ist.

jQuery

jQuery

Auch jQuery ist mittlerweile kein Geheimtipp mehr und wie eine Umfrage des Webstandard Blogs zeigt, auch das beliebteste JavaScript Framework. Ich kann das gut verstehen, nachdem ich bisher auf prototype und script.aculo.us gesetzt habe, hat mich jQuery sofort überzeugt.

Alle weiteren JavaScript Bibliotheken basieren auf jQuery. Die Auswahl an Plugins ist schier unendlich und es gibt eine große Zahl an hervorragenden Projekten, die auf jQuery aufsetzen.

jQuery UI

jQuery UI

Aufbauend auf jQuery gibt es jQuery UI, eine Bibliothek, die verschiedene Widgets und Funktionen bietet. Neben Widgets deckt jQuery UI das ab, was bei prototype durch script.aculo.us ergänzt wird: Drag n Drop, sortierbare Listen und animierte Effekte. In rsslounge basiert der Slider für die Priorität, das Drag n Drop der Feeds und Kategorien, sowie die Processbar für den ajaxbasierten Update auf dieser Bibliothek.

Impromptu

Impromptu

Es gibt ja eine ganze Reihe guter Lightbox Skripte. Für rsslounge habe ich aber ein LightBox Skript gesucht, das sich besonders gut für Dialoge eignet. Impromptu bietet hier eine einfache Möglichkeit Buttons zu setzen und eigene Funktionen an die verschiedenen Aktionen der Popup-Box zu binden. Lediglich bei der Positionierung der Box, die pauschal auf top:15% gesetzt ist, war ich nicht zufrieden. Allerdings hat man hier vollen Einfluss auf das CSS, so dass auch das kein echtes Problem ist. Eine sehr gute Alternative wäre die ModalBox gewesen. Diese basiert allerdings auf prototype.

Date Picker

Date Picker

Ein hervorragendes Skript für die Auswahl eines Datumbereichs ist der Date Picker von Stefan Petre. Date Picker für die Auswahl eines einzelnen Datums gibt es ja viele, so bietet jQuery UI hier auch ein grundsolides Widget. Aber wenn es darum geht einen Bereich zu wählen, wird die Auswahl plötzlich sehr klein. Der Date Picker hat ein schickes Design und kann sehr genau konfiguriert und mittels CSS gestaltet werden.

jgrowl

jGrowl

jgrowl orientiert sich an dem Benachrichtigungssystem von Growl, welches für Mac OS X verfügbar ist. Es zeigt Benachrichtigungen in einer kleinen Box am Bildschirmrand an. rsslounge nutzt dieses Skript nur recht selten, für Fehlermeldungen und wichtige Informationen ist es aber hervorragend geeignet.

Ajax Upload

Ajax Upload

Mit Hilfe dieses jQuery Plugins können bei rsslounge OPML Dateien importiert werden. So lässt sich der Dateiupload mit einem Klick auf den entsprechenden Menüpunkt starten, ohne das explizit ein neu Laden der Seite oder das Datei Eingabefeld nötig ist.

Tipsy

tipsy

Das Plugin Tipsy ermöglicht beliebige ToolTipps zu erstellen. Diese verwende ich für den Eingabedialog von neuen Feeds. Manchmal bleiben die ToolTipps noch hängen, hier muss ich also nochmal genauer testen. Der erste Eindruck ist aber sehr gut und die zusätzlichen Informationen sind für Neulinge dann doch eine gute Hilfe.

SimplePie

SimplePie

Das Herzstück von rsslounge ist die Bibliothek SimplePie. Diese PHP Bibliothek ermöglicht es sehr einfach RSS Feeds zu lesen und zu verarbeiten. Ich habe mich für SimplePie und nicht für Zend_Feed entschlossen, da es um einiges ausgereifter ist, mit keinem Feed Probleme hat und sich bereits in vielen Applikationen bewährt hat. Ein erster Test hat dann auch gleich gezeigt das SimplePie schwer zu toppen ist. rsslounge selbst ist so aufgebaut, dass sich problemlos SimplePie durch eine andere Bibliothek ersetzen lässt (oder eine zweite Bibliothek optional gewählt werden kann), bisher gab es aber keinen Grund dafür. SimplePie besteht lediglich aus einer Datei und einer Hand voll Klassen.

WideImage

WideImage

Für das Erzeugen der Thumbnails verwende ich die Bibliothek WideImage, welche sich zwar noch in Beta befindet, aber im Test super funktioniert. WideImage basiert auf der GD2 Erweiterung und kapselt alle Funktionen in eine Klasse und erlaubt es komfortabel Bilder zu laden, zu verkleinern oder anderweitig zu verändern. Ein Beispiel wie das dann aussehen kann:


wiImage::load('image.png')->resize(50, 30)->saveToFile('new-image.jpg');

Icons

An der Stelle will ich auch nicht die Icons vergessen. Diese stammen von DryIcons, welche die Sticker Icons unter einer Free Lizenz anbieten, sowie vom Smashing Magazine. Letztere erlauben eine freie Verwendung der Icons (auch für kommerzielle Zwecke, ohne Einschränkungen).

Die Liste ist ganz schön lange, aber bestätigt mich darin laufend gute Skripte zu sammeln. Besonders Funktionalitäten, die sich gut kapseln lassen, oder kompliziert zu entwickeln sind, sind für eigene Projekte eine wahre Bereicherung.

Wie bereits angekündigt, ist rsslounge jetzt für alle öffentlich verfügbar. Für alle die nicht wissen worums überhaupt geht, hier ein kleiner Überblick:

rsslounge ist ein kostenloser, webbasierter RSS Feed Reader. Der Reader ist kein gehosteter Service und muss auf dem eigenen Webserver installiert werden.

rsslounge screenshot

Features:

  • Vollständiger RSS Reader
  • Unterstützt Bilder und Fotoblogs
  • Setze Prioritäten und filtere Feeds und Einträge
  • Einfache ajaxbasierte Oberfläche
  • Unterstützt auf Ajax basierende, sowie Cronjob Updates
  • Offenes Pluginsystem zum Hinzufügen eigener Datenquellen

Also keine falsche Scheu, einfach saugen und austesten. Über Feedback, egal welcher Art, bin ich dankbar und freue mich über eure Meinungen, Gedanken, Ideen und Probleme.

Downloaden könnt ihr rsslounge hier.

Wer sich für den Quellcode interessiert, der kann sich auf der Google Code Seite informieren. Dort findet ihr ein Wiki, das SVN Repository und weitere Infos. Die Seite werde ich nach und nach mit weiteren Infos befüllen.

Vor einigen Monaten habe ich hier ein kleines Skript zur Verfügung gestellt, das als kleiner Online-Notizzettel verwendet werden kann. Mittlerweile nutze ich das Skript täglich und trotz seiner Einfachheit ist es ein unheimlich nützlicher Helfer geworden. Für alle die das Skript nicht kennen: es ist nichts anderes als ein in Web abgelegter Richt-Text-Editor, in dem beliebiger Text geschrieben und gespeichert werden kann.

Online-Notizzettel

Egal wo man ist, Zuhause, in der Arbeit, in der Uni: von überall hat man Zugriff auf dieses eine Dokument und kann dort kurze Notizen und ToDo Listen speichern.

Dieses Skript habe ich nun aktualisiert. Es basiert nun nicht mehr auf tinyMCE, sondern auf der neuesten Version vom CKEditor. Insgesamt finde ich den Editor ansprechender, schicker und auch praktischer. CKEditor war früher einmal der FCKEditor und ist in der neuesten Version wirklich rundum gelungen. Nur die Dokumentation lässt etwas zu wünschen übrig.

Das Skript ist natürlich frei verfügbar (nur die Lizenz vom CKEditor muss beachtet werden) und darf sonst frei verändert und weiterverwertet werden.

Die Installation ist simpel: einfach die Dateien der ZIP Datei hochladen und für die Datei “data” Schreibrechte setzen. Bei Bedarf mittels .htaccess einen Passwortschutz setzen, sonst kann jeder, der die Url kennt eure Notizen lesen. Mit der Tastenkombination “Alt + S”, oder dem Speichern Icon, kann das Dokument gespeichert werden.

Download: Online-Notizzettel 2.0 (692 kB)