CommunityMashup – Ein erster Überblick

[toc] Das CommuntiyMashup ist eine Integrationslösung für Daten aus sozialen Diensten. Es vereinheitlicht und verbindet Daten aus den unterschiedlichsten Quellen. Hierbei steht im Sinne des „Social Web“ die Person im Vordergrund. Eine definierte Schnittstelle mit vorgefertigen Anwendungskompenten lässt eine einfache Verwendung der Daten in verschiedensten Anwendungsszenarien zu. Diese Seite gibt einen Überblick über die dem CommunityMashup zugrundeliegenden Konzepte und vermittelt einen Einblick in seine vielfältigen Verwendungsmöglichkeiten.

Ausgangssituation

Mit dem Erfolg von Web 2.0 im privaten und Enterprise 2.0 im unternehmensweiten Bereich veränderte sich die Art und Weise wie Informationen strukturiert und kosumiert werden.

[singlepic id=220 w=618 float=center]

Auswirkungen des Erfolg von Social Software

Im Zuge des immer verbreiteteren Einsatzes von Social Software auch im Unternehmenskontext vollzieht sich eine Entwicklung von einer datenzentrischen Systemsicht hin zu einer personzentrischen Perspektive. Soziale Netzwerke wie Facebook oder Microblogging Dienste wie Twitter sind nur zwei Arten von Diensten die Einzug in unser tägliches Leben gefunden haben. Insgesamt lässt sich beoachten, dass fast jeder Nutzer inzwischen mehr als einen Dienst benutzt, sei es wegen spezieller Funktionalitäten, den Personen die über den jeweiligen Dienst erreichbar sind oder schlichtweg um private und berufliche Nutzung zu trennen. So sind wir unter anderem gezwungen den richtigen Kanal zu wählen um Informationen zu konsumieren bzw. zu verteilen. Dies nährt den Wunsch nach einer Integrationslösung, die unsere Daten aus unterschiedlichen Diensten vereint ohne dabei ein neues zentralisiertes System zu schaffen. Insbesondere muss uns die Wahl der Dienste und die Art und Weise, wie wir diese nutzen wollen offen bleiben.

Mobile und ubiquitäre Nutzung

Eine weitere Veränderung der letzten Jahre lässt sich in der Nutzung verschiedenster Geräte, mit denen wir Informationen konsumieren, festhalten. Sei es mit dem Tablet zuhause im Wohnzimmer, unterwegs per Smartphone oder klassisch im Büro mit dem Desktoprechner. Hinzukommen ubiquitäre Systeme wie interaktive Wandbildschirme, welche die letzten Lücken unserer Informationsversorgung schließen. Eine zukunftsfähige Integrationslösung muss daher dem Nutzer die Möglichkeiten der freien Geräte- und Plattformwahl offen lassen.

Nutzerzentrische Aggregation verschiedener Quellen

Der Grundgedanke des Web 2.0 beinhaltet die starke Einbeziehung aller Nutzer bei der Erstellung von Inhalten und die Möglichkeit diese mit anderen Personen zu teilen. Mit der Integration von Daten aus uterschiedlichen Diensten entsteht der Wunsch diese untereinander mit zusätzlichen Informationen zu Verknüpfen und diese wiederum mit anderen zu teilen. Hierin liegt auch ein Kritikpunkt an aktuellen Integrationssystemen, die meist nur aus einer Single-User Perspektive getrieben sind. Beispielsweise ist die Verteilung der Information innerhalb einer Gruppe, wer welche Artikel zu einem gemeinsamen Interessensgebiet gelesen hat, aus dieser Perspektive unmöglich. Wobei die Artikel natürlich aus verschiedensten Quellen stammen können. Zusammen mit der personenzentrischen Sicht auf Daten, der Vielzahl verschiedenster genutzer Dienste und der Verwendung unterschiedlichster Geräte führt dies zum Wunsch einer neuen Integrationslösung für die wir im folgenden die Konzepte und Lösungsansätze vorstellen.

Grundidee

Das CommunityMashup verbindet die Inhalte aus verschiedensten sozialen Diensten. Dazu zählen beispielsweise Soziale Netzwerke wie facebook, Microblogging Dienste wie twitter oder Bild-Dienste wie flickr, aber auch spezielere wie beispielsweise der Referenzmanagement-Dienst Mendeley für wissenschaftliche Veröffentlichungen. Die Daten aus diesen Diensten werden über die Schnittstellen der Services abgerufen und über spezielle Adapter vereinheitlicht, so dass sie miteinander vermischt und verbunden werden können („mashup“). Die vereinheitlichten Daten werden anschließen wieder über spezielle Schnittstellen bereitgestellt. Hierbei wird auf unterschiedliche Anwendungsszenarien und deren spezielle Anforderung eingegangen, die insbesondere durch verschiedene Geräte und Plattformen beeinflusst sind. Wir unterscheiden ganz allgemein zwischen Web-Anwendungen, Desktop-Anwendungen und Anwendungen für mobile Geräte. Die folgende Grafik visualisiert diese Zusammenhänge noch einmal grafisch. Hierbei ist vorallem zu beachten, dass Daten nicht nur von den angebunden Diensten zu den Endbenutzer Anwendungen fließen, sondern auch in umgekehrter Richtung.
[singlepic id=603 w=618 float=center]

Model Driven Approach

Ausgehend von der Grundidee einer Integrationslösung für soziale Dienste, die Daten vereinheitlicht und über spezielle Schnittstellen wieder bereitstellt, stellt sich die Frage nach dem passenden Entwicklungsansatz. Erfahrungen haben gezeigt, dass Internetdienste sowie ihre ggf. vorhandenen Schnittstellen einer permanenten Änderung und Weiterentwicklung unterworfen sind. Dienste kommen und gehen bzw. sind populären oder unpopulärer ebenso verhält es sich mit ihren Funktionen und Schnittstellen. Um flexibel auf diesen kontinuierlichen Wandel reagieren zu können und dabei eine stetige Evolution der Integrationslösung zu ermöglichen, schlagen wir einen modellgetriebenen Ansatz vor. Dieser basiert auf einem dafür konzipierten personenzentrischen Datenmodell, das die Zusammenhänge in sozialen Diensten wiedergibt. Dieses Datenmodell und die darauf aufbauenden Anwendungskomponenten stellen wir im weiteren Verlauf näher vor.

Datenmodell

Untenstehende Abbildung zeigt die Kernelemente des personenzentrischen CommunityMashup-Datenmodells. Es enthält die drei Kernelmente Person, Organisation und Inhalt (Content). Organisationen wie auch Inhalte können hierarchisch strukturiert werden. Inhalte werden über eine Autor-Beziehung mit Personen verknüpft, diese wiederum können über Organisationen gruppiert werden. Personen-Objekte spiegeln jeweils reale Menschen wieder, d. h. für eine Person wird nicht ein eigenes Element für je benutzten Dienst erzeugt werden, vielmehr bilden alle verteilten Profile zusammen eine digitale Identität ab. Das Selbe gilt auch für die Profile von Organisationen. Jeder weitere Dienst trägt seine zusätzlichen Profilinformationen über Erweiterungs-Objekte (Extensions) bei. So bleibt auch der Bezug zur ursprünglichen Quelle erhalten.
[singlepic id=600 w=618 float=center]

Ein Kernkonzept des Datenmodells ist die bewusst offene Verwendung von Tags für Metainformationen, um ein Minimum von zusätzlichen Attributen für die einzelnen Daten-Objekte fix speichern zu müssen. Beispielsweise erhält eine Person nicht mehr zwei Attribute für die private und die berufliche E-Mail-Adresse, sondern Referenzen zu zwei E-Mail Objekten getaggt mit privat bzw. beruflich. Ein E-Mail Objekt lässt sich dann beispielsweise noch facebook taggen um so deren Verwendung auszuzeichnen. Dieses Verfahren wird auf alle Objekte des Datenmodells angewandt und erlaubt sehr flexible Such- und Filtermethoden und ermöglicht dadurch letztlich eine nutzungsoffene Verwendung der Integrationslösung.

Anwendungskomponenten

Mit der aus dem Datenmodell hervorgehend Abbildungsvorschrift, die es erlaubt Daten aus sozialen Diensten zu vereinheitlichen und miteinander zu verbinden, stellt sich die Frage, welche Teile einer konkreten Anwendung direkt vom vorliegenden Datenmodell abängen und somit ebenfalls automatisch aus dem Modell generiert werden können. Um eine nachhaltige und erweiterbare Lösung zu ermöglichen, ist es quasi ein Muss, dass alle diese direkt ableitbaren Teile automatisch bzw. zumindest semi-automatisch generiert werden. Die folgende Grafik gibt einen Überblick über die für das CommunityMashup relevanten, automatisch generierbaren Anwendungskomponenten:
[singlepic id=604 w=618 float=center]

Viele UML-Werkzeuge unterstützen mittlerweile die automatische Erzeugung einer (Java) Schnittstelle mit zugehörigen leeren Klassen und Methoden. Für eine durchgängige Lösung wird allerdings ausführbare Code mit einer Laufzeitumgebung (RunTime) benötigt. Diese kümmert sich beispielsweise um die Erzeugung von Objekten bzw. um die Bereitstellung von Methoden zur Manipulation solcher Instanzen. Ein zusätzlicher Event-Mechanismus erlaubt das Verfolgen dieser Änderungen. Eine weitere wichtige Anwendungskomponente stellt die Persistierung dar. Diese wird beispielsweise für Caching benötigt. Für die Persistierung von Daten ist eine Serialisierung und Deserialisierung der Objekte notwendig. Diese wird ebenfalls für den Datenaustaustausch über Web-Schnittstellen im XML-Format benötigt. Im Rahmen des CommunityMashup-Projektes wird aktuell eine durchgängige Werkzeugkette aufgebaut, die die automatische Erstellung dieser Komponenten ermöglicht. Wir wenden den gleichen modellgetrieben Ansatz auch auf ein Meta-Modell an, das die möglichen Konfigurationen des CommunityMashup beschreibt. Hierfür werden viele identische Komponenten benötigt, allerdings jeweils bezogen auf ein anderes Modell. Die Verwendung des Meta-Modells erlaubt es, Konfigurationen speichern und laden zu lassen (Persitierung) und beispielsweise aus Gründen der Fernwartung auch über eine Web-Schnittstelle abfragen und verändern zu lassen.

Service-Orientierte-Architektur

Alleine durch die oben beschrieben, aus einem Modell erzeugbaren Komponenten lässt sich noch keine gesamte Integrationslösung erstellen. Ziel des CommunityMashups ist nicht nur ein flexibles Entwicklungskonzept das durch den modellgetriebenen Ansatz erreicht wird, sondern auch eine flexible Systemarchitektur die aufgrund von Anforderungen wie Skalierbarkeit, Performance und Ausfallsicherheit eine Verteilung von Systemkomponenten zulässt. Diese Service-Orientierte-Architektur, muss sich dadurch auszeichnen, dass definierte Systemkomponenten als eigenständige Services mit definierten Schnittstellen realisiert werden. So lassen sich selbst zur Laufzeit einzelne Komponenten aktualisieren bzw. austauschen ohne die Verfügbarkeit des Gesamtsystems zu beeinflussen. Nachfolgende Abbildung zeigt ein exemplarisches verteiltes Szenario mit Client- und Server Komponenten.
[singlepic id=601 w=618 float=center]

Die Verbindung der Daten aus den eizelnen Quelldiensten (Source 1 bis Source n) wird auf einem Server durchgeführt und durch eine Konfiguration gesteuert. Jede dieser Quellkomponenten wird als eigener Service realisiert, der sich sich einzeln aktualiseren lässt, beispielsweise um auf die Änderung einer entfernten Schnittstelle zu reagieren.Java Intern überführen die dargestellten Quellkomponenten Daten der externen Dienste in das dem personenzentrische CommunityMashup-Datenmodell und tragen diese hierdurch sukzessive zu einem gemeinsamen Datensatz zusammen. Die zentrale CommunityMashup-Komponente stellt diesen Datensatz (ggf. je nach Bedarf gefiltert) wieder über eine Java Schnittstelle bereit. Darauf aufbauend lässt sich eine REST Schnittstelle hinzufügen, die die aggregierten und gefilterten Daten (zugriffsbeschränkt) über das Web verfügbar macht. Spezielle Anwendungskomponenten lassen nun eine Verwendung der Daten auf Client-Seite über eine identische Java API zu. Die je nach Client-Typ (im oben abgebildeten Beispiel eine klassische Desktop Anwendung in Kombination mit einem Android Mobile Device) speziell ausgeprägten Anwendungskomponenten kümmern sich im Hintergrund transparent um den Datenaustausch und verlagern je nach Client rechenintensive Aufgaben auf den Server.

CommunityMashup REST-Schnittstelle

[toc] Das CommunityMashup stellt Anwendungen eine auf Web2.0-Inhalte spezialisierte und auf einem personenzentrischen Datenmodell basierende Datenbasis zur Verfügung. Um Anwendern/Entwicklern generische Zugriffsmöglichkeiten auf diese Datenbasis zu ermöglichen, wurde im Rahmen einer Masterarbeit eine REST-Schnittstelle für das CommunityMashup entwickelt, die nachfolgend kurz vorgestellt wird

Problemstellung

Zu Beginn der Entwicklung des CommunityMashups wurde der Zugriff auf die Daten des Frameworks lediglich über eine Java-Schnittstelle ermöglicht, d.h. eine es nutzende Anwendung musste in Java implementiert sein und auf der gleichen Maschine wie das CommunityMashup laufen.Eine auf verschiedene Geräte oder Architekturen verteilte Nutzung wurde somit starkt erschwert (vgl. Abbildung links).

[singlepic id=582 h=270 float=left] [singlepic id=583 h=270 float=left]

Um diesem Problem zu begegnen, wurde das CommunityMashup im Rahmen einer Masterarbeit um eine REST-Schnittstelle erweitert. Mit Hilfe dieser Schnittstelle können verschiedenste Arten von Anwendungen (z.B. normale Anwendungen, Smartphone-Apps oder Widgets) auf unterschiedlichen Geräten auf die Daten eines oder mehrerer CommunityMashups zugreifen und diese verwenden sowie manipulieren (vgl. Abbildung rechts).

Verwendung der Schnittstelle

Die Schnittstelle kann prinzipiell von jeder Anwendung verwendet werden, die entsprechend der Schnittstellen-Dokumentation erstellt/konfiguriert wurde:

[singlepic id=581 w=518]

Da die Kommunikation mit der REST-Schnittstelle über das HTTP-Protokoll und damit potentiell dem gesamten Internet geschehen kann, ist die Anwendungsentwicklung sowohl was den Ort als auch die Architektur des Zielsystems betrifft vom CommunityMashup unabhängig.

Die REST-Schnittstelle wird vom CommunityMashup in Form eines Java-Servlets bereitgestellt, welches ebenfalls die Dokumentation der Schnittstelle enthält.

Beide können über die URL des CommunityMashup-REST-Services erreicht werden, der eine selbsterklärende Beschreibung der angebotenen Dienste bereithält. Unter anderem kann die Syntax der REST-Anfragen nachgeschlagen werden und die Anfragen können im Browser getestet werden, was bei der Entwicklung kompatibler Anwendungen hilft.

[singlepic id=595 w=618 float=center]

[singlepic id=584 w=618 float=center]

Technische Umsetzung

Um die REST-Schnittstelle mit der modellgetriebenen Entwicklung des CommunityMashups[ref]Vgl. https://soziotech.org/communitymashup/model-driven-approach/.[/ref] im Einklang zu halten, werden die dynamischen (vom Datenmodell des CommunityMashups anhängigen) Methoden und Funktionen mit Hilfe angepasster JET-Templates automatisch aus dem Modell generiert, was eine spätere manuelle Anpassung der Schnittstelle an Änderungen des CommunityMashups überflüssig macht:

[singlepic id=589 w=618 float=center]

Um den unauthorisierten Zugriff auf das CommunityMashup einzuschränken, wurde ein Sicherheitssystem entwickelt, das nur registrierten Anwendungen den Zugriff auf die Daten und Funktionen des CommunityMashups gestattet. Die Absicherung der REST-Anfragen geschieht durch eine Signatur, welche die Anfrage vor einer Manipulation schützt und den Absender der Anfrage eindeutig identifiziert.

Sicherheitssystem der Schnittstelle

Die Sicherheit der Daten des CommunityMashups wird durch die Verwendung sogenannter Message Authentication Codes (MAC) sichergestellt, welche auch bei anderen (REST)-Schnittstellen namhafter Online-Dienstanbieter wie Amazon, GoogleMaps oder Flickr verwendet wird. Dabeiwird neben der eigentlichen Anfrage der Hashcode der Anfrage und eines geheimen Schlüssels übermittelt, wodurch zum einen die Integrität der Nachricht und zum anderen die Identität des Absenders sichergestellt sind.

REST-Zugriff

Die folgenden Prozessdiagramme liefern einen kurzen Überblick über die Zugriffsmöglichkeiten auf das CommunityMashup über die REST-Schnittstelle, darunter auch über den Ablauf einer gesicherten REST-Anfrage:

[nggtags gallery=REST+Zugriff]

Quellenangaben und Fußnoten für NextGEN Gallery

[toc]

NextGen Gallery[ref]Downloaddes Plugins im WordPress-Repository unter http://wordpress.org/extend/plugins/nextgen-gallery/[/ref] ist meiner Meinung nach eine der sinnvollsten und am besten durchdachten Erweiterungen für WordPress. Das Plugin ermöglicht eine galerie- und albumbasierte Verwaltung von Bilder aller Art und darüber hinaus die Zuordnung von Schlagwörtern / Tags zur zusätzlichen (flachen) Strukturierung. Hierdurch wird es möglich, Bilder in Artikeln mithilfe des nggtags-Shortcodes[ref]Dokumentation unter http://nextgen-gallery.com/gallery-tags/.[/ref] dynamisch einzubinden, d.h. statt einer festen Referenz auf eine Auswahl von Bildern wird nur noch festgelegt, welche Schlagwortkombinationen für eine bestimmte Artikelstelle relevant sind. Beispielsweise würden mit folgendem Shortcode alle Bilder als Thumbnails angezeigt, die mit „Auto“ (Groß- und Kleinschreibung egal) verschlagwortet wurden[ref]Achtung: Die Leerzeichen innerhalb der eckigen Klammern müssen nach einem Copy & Paste entfernt werden, damit der Shortcode von WordPress ausgeführt wird.[/ref]

[ nggtags gallery=Auto ]

Das Ganze hat meiner Meinung nach drei entscheidende Vorteile:

  1. Kommen weitere Bilder mit den entsprechenden Tags in irgendeiner Galerie hinzu, werden sie automatisch im Artikel mit angezeigt.
  2. In der Galerie angegebene Metadaten, wie Titel und Beschreibung werden automatisch übernommen und müssen so im Vergleich zur Nutzung der WordPress Mediathek nicht redundant gepflegt werden – v.a. dann nicht, wenn sie sich nachträglich ändern.
  3. Der Tagging-Mechanismus funktioniert galerieübergreifend, d.h. neben der in NextGEN vorhandenen intuitiven Strukturierung in verschiedene Galerien (z.B. zu einem bestimmten Ereignis wie „Doktorandenseminare“ oder einer bestimmten Bilderkategorie wie „WordPress Screenshots“), lassen sich sehr einfach übergreifende Selektionen vornehmen[ref]Beispielsweise würden mithilfe des Shortcodes [ nggtags gallery=Referenzverwaltung ] alle Bilder angezeigt werden, die mit „Referenzverwaltung“ verschalgwortet wurden, sowohl aus der Galerie „Doktorandenseminare“ als auch aus der Galerie „WordPress Screenshots“ (sowie allen ggf. vorhandenen weiteren Galerien).[/ref].

Problem bei externen Bildquellen

Ein „Problem“ mit dem Plugin ergibt sich dann, wenn man Bilder z.B. im wissenschaftlichen Kontext von anderen Quellen referenzieren und dennoch auf den Komfort des Plugins nicht verzichten möchte. Aktuell bietet NextGEN Gallery keine Möglichkeit, Bildquellen oder Ähnliches direkt anzugeben. Natürlich könnte man dafür das Beschreibungsfeld nutzen bzw. zweckentfremden und die entsprechende Quelle einfach als Text dort mit aufnehmen. Für den Fall, dass man die Anzeige der Quelle allerdings gezielter steuern möchte, ist diese Möglichkeit nicht geeignet. Auch widerspräche das Vorgehen klar dem Atomaritätsprinzip bzw. der semantischen Bedeutung des Beschreibungsfeldes. Prinzipiell bietet NextGEN auch hierfür einen eingebauten Mechanismus zur Angabe weiterer Metadaten, allerdings ist dieser in neueren Versionen des Plugins nur sehr umständlich erreichbar und wird v.a. nicht in den Übersichten angezeigt.

Lösungsschritte

Nachdem bis zu einer sinnvoll nutzbaren Lösung zur Quellangabe einige Schritte erforderlich waren, halte ich das hier kurz fest.

1. Zusätzliches Feld zur Quellenangabe bei jedem Bild

Zur Bereitstellung des benötigten Metadatenfeldes im Backend von NextGEN hilft das Plugin NextGEN Custom Fields, mit dem nach erfolgter Installation über den neuen Menüpunkt „NGG Custom Fields“ sehr einfach ein neues  Image Custom Field mit  Bezeichnung „Source“ für Quellenangaben angelegt werden kann. Die Eingabe erfolgt anschließend wie gewohnt über den Punkt „Galerie verwalten“, wie im folgenden Screenshot auf der rechten Seite zu sehen.

[singlepic id=245 w=614 h= float=]

2. Anpassen des Galerie-Templates

Damit das neu erstellte Feld auch in Thumbnail-Übersichten oder bei Einzelbildern im Frontend angezeigt wird, muss es entsprechend eingebunden werden. Mein erster Ansatz war, ein eigenes NextGEN Gallery Template für die Ausgabe zu nutzen, allerdings funktioniert der folgende Shortcode leider nicht, da NextGEN seltsamerweise bei tagbasierten Galerien bisher keine Tamplates unterstützt.

[ nggtags gallery=Auto template=source]

Dieser Missstand ließe sich zwar entsprechend http://wordpress.org/support/topic/plugin-nextgen-gallery-nggtags-caption beseitigen, allerdings müssten hierzu die Funktion nggShowGalleryTags in der nggfunctions.php und die Funktion show_tags in der shortcode.php von NextGEN entsprechend angepasst werden, was logischerweise nicht update-sicher und damit wenig sinnvoll ist. Hier heißt es also abwarten, ob diese durchaus sinnvollen Erweiterungen für nggtags irgendwann durch den Autor Alex Rabe ihren Weg in das Plugin finden, wovon ich fest ausgehe.

Somit blieb nichts anderes, als direkt das gallery.php Template entsprechend anzupassen. Nachdem wir hier im Blog allerdings sowieso ein einheitliches Galerieformat verwenden, ist dem auch nichts entgegenzusetzen – insbesondere da es so (ohne den zusätzlichen template-Parameter im Shortcode) noch einfacher ist, später Galerien in Blogartikeln einzufügen.

Um sicherzustellen, das die Templates nicht bei einem Plugin-Update direkt wieder überschrieben werden, sollten die folgenden Anpassungen ausschließlich (!) in einem zu erstellenden Unterordner „nggallery“ des verwendeten Themes durchgeführt werden:

  1. Kopieren der gallery.php und der singlepic.php aus /wp-content/plugins/nextgen-gallery/view/ nach wp-content/themes/AKTUELLES-THEME/nggallery/.
  2. Einfügen von $image->ngg_custom_fields[„Source“] an der gewünschten Stelle, z.B. hinter echo $image->caption.

Problem hierbei ist, dass die Quellangaben (zumindest in unserem Fall) meist URLs sind, die i.d.R. eine Länge haben, durch welche die schön gefloateten Thumbnail-Übersichten unruhig würden oder falscch umbrechen, sicher aber schlecht lesbar wären (s. Screenshot):

[singlepic id=246 w=614 h= float=]

3. Fußnoten für Quellenangaben

Da wir hier im Blog ein Plugin zur Erzeugung von Fußnoten für zusätzliche Anmerkungen oder wissenschaftliche Quellenangaben verwenden, war es naheliegend, dieses Plugin auch für die Galeriebilder zu nutzen. In unserem Fall handelt es sich um das Plugin Simple Footnotes, das sich durch eine sehr einfache Handhabung sowie Multisite- und WP 3.1-Kompatibilität auszeichnet. Im Prinzip sollten die folgenden Schritte aber auch auf andere Plugins übertragbar sein.

Statt der Einbindung der Quellangabe direkt in der Caption, muss hierzu das Source-Field von oben lediglich mit der entsprechenden Shortcode-Funktion das Simple Footnotes Plugins „gewrappt“ werden. Da das Gallery-Template das Plugin allerdings nicht kennt, ist es erforderlich, zunächst eine entsprechende lokale Instanz zu erzeugen:

n
$footnotes->shortcode('', "Bildquelle: " . imagesourcelink($image->ngg_custom_fields["Source"]) . "."));

Damit die Fußnoten nur dann erzeugt werden, wenn auch tatsächlich eine Quellenangabe vorhanden ist, sollte zusätzlich noch folgende Abfrage integriert werden:

if ($image->ngg_custom_fields["Source"]){
	echo ($footnotes->shortcode('', "Bildquelle: " . imagesourcelink($image->ngg_custom_fields["Source"]) . "."));
}

Mit diesem Code wurden die Fußnoten auch erzeugt, allerdings leider für jedes Bild wieder bei 1 beginnend, da bei jedem Aufruf innerhalb der Bilderschleife des Gallery-Templates eine neue Instanz des Footnote-Plugins erstellt wurde. Abhilfe schafft hier das Auslagern der Instanzerzeugung außerhalb der Schleife und verwenden von $footnotes als globale Variable. Wichtig: Ähnlich wie bei einem Singleton[ref]Informatiker mögen mir die unsaubere Verwendung an dieser Stelle verzeihen.[/ref] sollte die globale Plugin-Referenz nur initialisiert werden, sofern sie noch null ist:

global $footnotes;
if (!$footnotes){
	$footnotes = new nacin_footnotes();
}

Resultat sind wie gewünscht in Fußnoten ausgelagerte Quellenangaben der Bildergalerie. Allerdings tritt das Problem doppelter Fußnoten weiterhin auf, sofern auf einer Seite, wie in diesem Beitrag, normale (textbasierte) Fußnoten und Bildergalerien gleichzeitig verwendet werden. Das liegt daran, dass das Plugin Simple Footnotes seinen Content Filter so angelegt hat, dass es sich selbst bzw. besser gesagt eine Instanz von sich selbst dem Filter übergibt:

add_filter( 'the_content', array( &$this, 'the_content' ), 12 );

Durch den WordPress-Filter-Registrierumgsmechanismus[ref] Siehe dazu auch Diskussion auf http://stackoverflow.com/questions/1524925/howto-use-the-has-filter-wordpress-function-with-an-object-based-callback.[/ref] wird bei jeder neuen Instanz von nacin_footnotes() auch jeweils ein entsprechender Content-Filter eingehängt, was a) inperformant ist und b) dazu führt, dass der Fußnotenblock in seiner Gesamtheit mehrfach am Ende eines Posts angezeigt werden kann. Leider habe ich für dieses Problem keine Optimallösung parat, so dass nur die Anpassung des der Datei simple-footnotes.php des Plugins bleibt. Hier muss ganz am Ende der Datei folgende Änderung durchgeführt werden:

//new nacin_footnotes();
global $footnotes;
$footnotes = new nacin_footnotes();

Hierdurch wird sichergestellt, dass das Plugin nur einmal erzeugt wird, egal ob direkt oder über das Gallery-Template. Zusätzlich ist es ggf. noch erforderlich, die folgende Änderung an der shortcode-Funktion des Plugins vorzunehmen. Hierdurch wird sichergestellt, dass die Fußnoten immer korrekt durchgezählt werden und bei 1 beginnen:

//FO we have to check if the footnote text is already present, otherwise the gallery plugin mechanism will not work (don't know why)
/*
if ( ! isset( $this->footnotes[$id] ) )
	$this->footnotes[$id] = array( 0 => false );
$this->footnotes[$id][] = $content;
$note = count( $this->footnotes[$id] ) - 1;
*/
if (!in_array($content,$this->footnotes[$id])){
	$this->footnotes[$id][] = $content;
	$note = count( $this->footnotes[$id] ) - 1;
}
else{
	$note =  array_search($content,$this->footnotes[$id]);
}

Ersetzt man nun noch den von NextGEN für die Bildunterschriften verwendeten span-Tag im Gallery-Template nun noch durch den von WordPress standardmäßig genutzten p-Tag der Klasse wp-caption-text und fügt dem ngg-gallery-thumbnail-Container die Klasse wp-caption hinzu, erhält man das folgende „fertige“ Gallery-Tempalte:

<?php
/**
Template Page for the gallery overview

Follow variables are useable :

	$gallery     : Contain all about the gallery
	$images      : Contain all images, path, title
	$pagination  : Contain the pagination content

 You can check the content when you insert the tag <?php var_dump($variable) ?>
 If you would like to show the timestamp of the image ,you can use <?php echo $exif['created_timestamp'] ?>
**/

// FO: muss global erzeugt werden, da sonst die Nummerierung für jede Galerie neu beginnt
global $footnotes;
if (!$footnotes){
	$footnotes = new nacin_footnotes();
}
if (!function_exists('imagesourcelink')) {
	function imagesourcelink($text){
		// text starts with http://
		if (strpos($text, "http://") === 0){
			return '<a href="' . $text . '" title="Go to external Source" >' .$text . '</a>';
		}
		else{
			return $text;
		}
	}
}

/*	FO: Da $gallery->ID als Group-ID für jQuery Colorbox / Slimbox nur dann funktioniert,
	wenn echte Gallerien verwendet werden, nicht aber bei nggtags (Tag-basierter Auswahl)
	muss hier noch einmal gesondert mitgezählt werden
*/
global $lightboxgroup;
if (!$lightboxgroup){
	$lightboxgroup = 0;
}

?>
<?php if (!defined ('ABSPATH')) die ('No direct access allowed'); ?><?php if (!empty ($gallery)) : ?>

<div id="<?php echo $gallery->anchor . $lightboxgroup ?>">

<?php if ($gallery->show_slideshow) { ?>
	<!-- Slideshow link -->
	<div>
		<a href="<?php echo $gallery->slideshow_link ?>">
			<?php echo $gallery->slideshow_link_text ?>
		</a>
	</div>
<?php } ?>

<?php if ($gallery->show_piclens) { ?>
	<!-- Piclense link -->
	<div>
		<a href="<?php echo $gallery->piclens_link ?>">
			<?php _e('[View with PicLens]','nggallery'); ?>
		</a>
	</div>
<?php } ?>

	<!-- Thumbnails -->
	<?php foreach ( $images as $image ) : ?>

	<div id="ngg-image-<?php echo $image->pid ?>" <?php echo $image->style ?> >
		<div >
			<a rel="lightbox-<?php echo $lightboxgroup ?>" href="<?php echo $image->imageURL ?>" title="
			<?php
			echo $image->description;
			if ($image->ngg_custom_fields["Source"]){
				echo ', Quelle: ' . $image->ngg_custom_fields["Source"] . ".";
			}
			?>
			" <?php echo $image->thumbcode ?> >
				<?php if ( !$image->hidden ) { ?>
				<img alt="<?php echo $image->description ?>" src="<?php echo $image->thumbnailURL ?>" <?php echo $image->size ?> />
				<?php } ?>
			</a>
			<p-caption-text><?php 

			echo $image->alttext;

			if ($image->ngg_custom_fields["Source"]){
				echo ($footnotes->shortcode('', "Bildquelle: " . imagesourcelink($image->ngg_custom_fields["Source"]) . "."));
			}

			?></p>
		</div>
	</div>
	<?php if ( $image->hidden ) continue; ?>
	<?php if ( $gallery->columns > 0 && ++$i % $gallery->columns == 0 ) { ?>
	<br style="clear: both" />
	<?php }
	endforeach;
	$lightboxgroup++;
	?>

	<!-- Pagination -->
 	<?php echo $pagination ?>

</div>

<?php endif; ?>

Zusätzlich zu den hier beschriebenen Punkten ist in diesem Template von Zeile 32-39 auch eine Zählervariable für Bildergruppen in Lightboxen, wie beispielsweise Slimbox oder Colorbox enthalten, die es auch bei tagbasierten Galerien ermöglicht, Bilder einer Galerie nacheinander durchzuklicken. Außerdem enthält das Template die Funktion imagesourcelink (Zeile 20-30), die im Source-Feld eingetragene URLs in den Fußnoten automatisch verlinkt.

Endergebnis

Das Ergebnis der Bemühungen sieht anschließend wie folgt aus:

[singlepic id=247 w=614 h= float=]

Für den Fall, dass noch kein CSS für die Galerie-Darstellung existiert, sind ggf. noch folgende ergänzenden CSS-Angaben erforderlich, um die Darstellung der Thumbnails gleichmäßig über die Seite zu verteilen. Die Größenangaben basieren hierbei auf einer in NextGEN eingestellten Thumbnail-Größe von 126x100px. Die Pixeldifferenz zu 146px Breite rührt von den CSS-Einstellungen des hier verwendeten Twentyten Child-Themes bzw. den dort vorgegebenen Paddings:

.ngg-gallery-thumbnail{
	width: 146px;
	height: 160px;
	overflow: hidden;
}

Die ggf. erforderlichen Änderungen an der singlepic.php zur Darstellung von Einzelbildern erfolgen analog.

Placeboard – Jeder Ort ein Schwarzes Brett

Das Berliner Startup placeboard (http://www.placeboard.com) versucht das Prinzip des Schwarzen Bretts in der Nachbarschaft ins Internet zu übertragen.

[singlepic id=9 w=400 h=280 mode=web20 float=]

Im Gegensatz zu anderen Internet-basierten Kleinanzeigen-Plattformen steht hier der Ortsbezug einer Mitteilung und die Filterung nach dem Ort im Vordergrund.

Neben einer recht nett gemachten Web-Schnittstellen erlauben die placeboard-Macher auch eine einfache Erweiterung der Plattform in die reale Welt: Selbst erstelle Nachrichten können mit einem QR-Code ausgedruckt werden und so an reale Schwarze Bretter geheftet werden ohne den Bezug zur digitalen Version des Aushangs zu verlieren.

Meiner Meinung nach schreit das Ganze nach einer CommunityMirror-Schnittstelle (und natürlich nach mobilen Apps dafür).

Verwandte Dienste (ausserhalb von Deutschland): BlockChalk (http://blockchalk.com)

[nggtags gallery=placeboard]

Microsoft Exchange Toolboxcenter konnte nicht alle Tools anzeigen

Man lernt ja nicht aus. Heute bin ich zufällig über einen relativ seltsamen Fehler in unserer Microsoft Exchange 2007 Installation gestolpert. Durch ein automatisch per Windows Update installiertes Update Rollup 1 für Exchange 2007 SP2 meldete die Exchange-Verwaltungskonsole bei jedem Zugriff auf die Toolbox folgende Fehler:

--------------------------------------------------------
Microsoft Exchange Fehler
--------------------------------------------------------
Das Toolboxcenter konnte nicht alle Tools anzeigen.

ExTRA-DRM
Fehler
Fehler:
Fehler des Tools beim Laden, weil das Tool ungültig ist. Beheben Sie die folgenden Ursachen des Fehlers:
'Datenbankwiederherstellungs-Verwaltung' ist kein zulässiges Tool.

ExTRA-MailFlow
Fehler
Fehler:
Fehler des Tools beim Laden, weil das Tool ungültig ist. Beheben Sie die folgenden Ursachen des Fehlers:
'Nachrichtenübermittlungs-Problembehandlung' ist kein zulässiges Tool.

ExTRA-MDBMount
Fehler
Fehler:
Fehler des Tools beim Laden, weil das Tool ungültig ist. Beheben Sie die folgenden Ursachen des Fehlers:
'Datenbank-Problembehandlung' ist kein zulässiges Tool.

ExTRA-MsgTrack
Fehler
Fehler:
Fehler des Tools beim Laden, weil das Tool ungültig ist. Beheben Sie die folgenden Ursachen des Fehlers:
'Nachrichtenverfolgung' ist kein zulässiges Tool.

ExTRA-Perf
Fehler
Fehler:
Fehler des Tools beim Laden, weil das Tool ungültig ist. Beheben Sie die folgenden Ursachen des Fehlers:
'Leistungsproblembehandlung' ist kein zulässiges Tool.

--------------------------------------------------------
OK
--------------------------------------------------------

Die entsprechenden Tools

  • ExTRA-DRM: Datenbankwiederherstellungs-Verwaltung,
  • ExTRA-MailFlow: Nachrichtenübermittlungs-Problembehandlung,
  • ExTRA-MDBMount: Datenbank-Problembehandlung,
  • ExTRA-MsgTrack: Nachrichtenverfolgung und
  • ExTRA-Perf: Leistungsproblembehandlung

wurden nicht geladen.

Die Ursache des Problems ist relativ einfach. Microsoft hatte im Zuge des Updates die Namen der Tools von deutschen Bezeichnungen auf Englisch geändert, allerdings ohne entsprechende Updates für bereits bestehende Registry-Einträge zur Verfügung zu stellen. Manche Dinge muss man wohl nicht verstehen …

Beheben lässt sich das Problem relativ einfach, in dem man die deutschen Namen im Registry-Pfad HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Exchange\v8.0\AdminTools\Toolbox\ durch ihre nachfolgenden englischen Pendants aus der Dokumentation ersetzt:

  • ExTRA-DRM: Database Recovery Management,
  • ExTRA-MailFlow: Mail Flow Troubleshooter,
  • ExTRA-MDBMount: Database Troubleshooter,
  • ExTRA-MsgTrack: Message Tracking und
  • ExTRA-Perf: Performance Troubleshooter

Als Registry-File sähe das dann so aus:

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Exchange\v8.0\AdminTools\Toolbox\ExTRA-DRM]
@=""
"Name"="Database Recovery Management"

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Exchange\v8.0\AdminTools\Toolbox\ExTRA-MailFlow]
@=""
"Name"="Mail Flow Troubleshooter"

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Exchange\v8.0\AdminTools\Toolbox\ExTRA-MDBMount]
@=""
"Name"="Database Troubleshooter"

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Exchange\v8.0\AdminTools\Toolbox\ExTRA-MsgTrack]
@=""
"Name"="Message Tracking"

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Exchange\v8.0\AdminTools\Toolbox\ExTRA-Perf]
@=""
"Name"="Performance Troubleshooter"

Apache2 SSL-Zertifikat vom DFN

[toc]

Wie viele andere wissenschaftliche Einrichtungen nutzen wir in der Foschungsgruppe Kooperationssysteme die Möglichkeit, unsere SSL-Serverzertifikate durch die Zertifizierungsstelle (CA) des Deutschen Forschungsnetzes (DFN) zertifizieren zu lassen. Die Zertifizierung findet durch die lokale Zwischenzertifizierungsstelle innerhalb der DFN Public Key Infrastruktur (PKI), unsere Universität der Bundeswehr München (UniBwM), statt . Großer Vorteil ist, dass die CA des DFN-Vereins („DFN-Verein PCA Global – G01“) als Root-Zertifikat das in gängigen Browsern enthaltene „Deutsche Telekom Root CA 2“ des T-TeleSec Trust Center der Deutschen Telekom AG für seine Zertifizierung verwendet. Somit wird der Zertifizierungspfad der ausgestellten Zertifikate ohne Zusatzinstallation eines Root-Zertifikats validiert.

Beantragen eines Serverzertifikats

Zur Zertifizierung lässt man sich unter ausführlicher Prüfung der persönlichen Daten und der Zugehörigkeit zur jeweils ausstellenden Einrichtung sowie der Sicherheit des zu zertifizierdenden Systems für einen ausgewählten Hostnamen ein Apache-taugliches PEM-Zertifikat generieren. Dabei handelt es sich um ein Base64-kodiertes X.509 Zertifikat im Format:

-----BEGIN CERTIFICATE-----

Zertifkatinhalt

-----END CERTIFICATE-----

Einbinden in die Apache-Konfiguration

Dieses Zertifikat kann anschließend in die Webserver-Konfiguration integriert werden. Bisher haben wir hierzu das Zertifikat sowie den von Apache benötigten privaten Schlüssel (Private Key) auf folgende einfache und der Standard-Dokumentation entsprechende Art in die Konfiguration des jeweiligen vHosts unter /etc/apache2/sites-enabled eingebunden:

SSLEngine on
SSLCertificateFile /etc/ssl/certs/ZERTIFIKATSNAME.pem
SSLCertificateKeyFile /etc/ssl/private/PRIVATE_KEY.key

Hierzu ist natürlich das Apache2 SSL-Modul erforderlich, das sich bei Bedarf über

a2enmod ssl

aktivieren lässt.

Anschließend muss Apache neu gestartet werden:

/etc/init.d/apache2 restart

Probleme bei der bisherigen Nutzung

In gängigen Browsern, wie Firefox, Internet Explorer, Chrome oder Safari hatten wir damit nie Probleme und das Zertifikat wurde immer als gültig angezeigt. Dies ist darauf zurückzuführen, dass diese Browser beim Validieren des Zertifikats im lokalen Cache nach den verschiedenen in der Zertifikatskette enthaltenen Authority-Zertifikaten suchen und sie – sofern vorhanden – für die Validierung verwenden. Allerdings gelten in größeren Unternehmen oder bestimmten öffentlichen Einrichtungen häufig erhöhte Sicherheitsrichtlinien. Dort werden häufig Web-Proxies eingesetzt, die bei der Validierung des Zertifizierungspfades nicht auf einen lokalen Zertifikats-Cache zurückgreifen können (oder sollen), sondern für die alle Informationen direkt über den Webserver erreichbar sein müssen. In unserem Fall hat dies auf einigen Verwaltungsrechnern dazu geführt, dass bestimmte SSL-verschlüsselte Login-Seiten über den genutzten Web-Proxy nicht erreichbar waren, da die Verbindung als nicht sicher angezeigt wurde.

Zertifikat-Validierung mit openSSL

Grundsätzlich lassen sich ausgestellte Zertifikate mit dem Linux-Programm openSSL relativ einfach validieren. Hierzu verwendet man einfach den s_client mit der entsprechenden Adresse des Apache vHosts:

openssl s_client -connect vhost-adresse.de:443

Resultat sollte bei gültigen Zertifikaten ein

Verify return code: 0 (ok)

sein. In unserem Fall bekamen wir allerdings trotz der Gültigkeitsanzeige in Brwosern von openSSL ein

Verify return code: 21 (unable to verify the first certificate)

weshalb das Zertifikat auch vom Web-Proxy abgelehnt wurde.

Korrektur durch Einfügen eines SLCACertificateFile

Beseitigen ließ sich das Problem schließlich durch Nutzung eines SLCACertificateFile in der Apache-Konfiguration. Nachdem der Weg dorthin allerdings etwas steinig war, hier ein paar kurze Erläuterungen.

Zunächst muss das „Chain-File“ der jeweils genutzten DFN-Zwischenzertifizierungsstelle heruntergeladen werden, das die CA-Zertifikate aller Zwischenzertifizierungsstellen sowie der Root-CA in einem File enthält. Die jeweilige Datei ist auf den öffentlich zugänglichen Servern des DFN-Vereins verfügbar. In unserem Fall beispielsweise unter dem Link https://pki.pca.dfn.de/uni-bundeswehr-muenchen-ca/pub/cacert/chain.txt.

Diese Datei muss mit der Endung PEM (streng genommen spielt die Endung in Linux keine Rolle) in den Zertifikatsordner auf den Server (in Debian- und Ubuntu-basierten Distributionen i.d.R. /etc/ssl/certs) geladen und in der vHost-Konfiguration mittels SSLCertificateChainFile entsprechend ergänzt werden. Außerdem war es in unserem Fall erforderlich, Apache den Pfad, in dem die CA-Zertifikate zu finden sind, ebenfalls mitzuteilen:

SSLCertificateChainFile /etc/ssl/certs/CHAIN-FILE.pem
SSLCACertificatePath /etc/ssl/certs

Anschließend muss Apache wieder neu gestartet werden:

/etc/init.d/apache2 restart

Erneute Validierung

Interessant ist das Ergebnis der erneuten Validierung, denn hier liefert openSSL im Falle eines DFN-Zertifikats:

Verify return code: 19 (self signed certificate in certificate chain)

oder in anderen Worten, dass ein selbst-signiertes Zertifikat im Zertifizierungspfad gefunden wurde. Dies ist darauf zurückzuführen, dass das openssl nichts vom oben bereits erwähnten Root-CA-Zertifikat („Deutsche Telekom Root CA 2“) weiß. Durch Anhängen des CAfile-Parameters lässt sich das Zertifikat allerdings doch noch validieren:

openssl s_client -connect vhost-adresse.de:443 -CAfile /etc/ssl/certs/deutsche-telekom-root-ca2.pem

Das Resultat ist nun wie gewünscht ein

Verify return code: 0 (ok)

Auch von Clients, die den Web-Proxy nutzen, ließ sich die Seite damit problemlos validieren.