Month: January 2017

Mit antispambot() gegen Emailharvester

Harvest

Emailadressen, welche frei verfügbar auf einer Webseite herum fliegen, werden regelmäßig von Bots gefressen, in Spamdatenbanken gepumpt und schon wird die Adresse zugespammt. Dennoch müssen immer wieder Emailadressen zugänglich auf der Webseite sein. Jede⋅r hat irgendwo seine Kontaktemail hinterlegt. Manchmal wird statt der Adresse ein Bild dargestellt oder das @ durch ein [at] ersetzt, um sich gegen die Harvester zur Wehr zu setzen.

Auch WordPress verfügt über eine Gegenmaßnahme und kommt mit einer kleinen, aber äußerst nützlichen Funktion daher: antispambot(). Diese wandelt etliche der Zeichen einer Emailadresse in Hex-Zeichen um, wie in diesem Beispiel zu sehen ist:

Welche der Zeichen umgewandelt werden ist dabei einem Zufallsgenerator überlassen und ändert sich (sofern man kein Caching nutzt) jedes Mal. Doch warum diese Umwandlung? Die meisten Email-Harvester-Bots sind relativ “dumm”. Sie prüfen den HTML-Code einer Seite, ob sich irgendwelche Emailadressen dort befinden. Meist geschieht dies über einen einfachen regulären Ausdruck, der nach Email-konformen Strings sucht. Hex-codierte Emailadressen sind erst einmal nicht konform mit dem Email-Format und werden deshalb gerne übersehen. Browser hingegen wandeln diese Emailadressen in normal lesbaren Text um.

Auf der Codex-Seite wird diese Funktion auch gleich für einen Shortcode aufbereitet, den man sich schnell in ein kleines Plugin stecken kann:

Gibt man nun [email]max.mustermann@example.com[/email] ein, so wandelt dieser Shortcode die Adresse in einen Email-Link und die Adresse in eine hexformatierte Adresse um.

Und das hilft?

Es wird wohl nicht gegen jeden Adress-Harvester schützen, aber doch gegen die Meisten. So wie auch ein [at] von einigen Bots wohl übersetzt werden kann und Bilder mit OCR-Methoden ausgelesen werden können, so ist es technisch natürlich auch möglich einen Bot zu bauen, der diese Adressen erkennt. Aber neben einem grundsätzlichen Schutz bietet diese Funktion gegenüber anderen Methoden den Vorteil, dass sie im Zusammenhang mit mailto: verwendet werden kann und damit den Besucher⋅innen einer Seite maximalen Komfort bietet.

Möchtest Du also auf Deiner Seite Emailadressen für Besucher⋅innen zugänglich präsentieren, aber vor Bots verbergen lohnt sich ein Blick auf antispambot(). Kanntest Du diese Funktion schon? Setzt Du sie erfolgreich ein oder welche Maßnahmen triffst Du gegen Email-Harvester?

Starter Content für Themes

Kennt Ihr das auch? Ihr sucht nach einem neuen Theme und flaniert durch verschiedene Showcases, schaut Euch Livedemos und Vorschaubilder an, die Euch das Theme auf verschiedenen Auflösungsstufen, für Desktop, Tablet und Mobile zeigen. Dann habt Ihr Euch endlich entschieden, ladet das Theme herunter, haut es auf Eure frische WordPress Installation und irgendwie sieht nichts so aus, wie erwartet?

Jetzt beginnt ein ewiges Herumfrickeln, bis über den Customizer oder gar die Theme Optionen die Einstellungen so getroffen sind, dass alles passt. Neue Seiten müssen angelegt werden, um die entsprechenen Page Templates zu testen und Widgets müssen konfiguriert werden. Je nachdem wie umständlich das Ganze wird verfliegt da schnell das anfängliche Hochgefühl, endlich das Theme gefunden zu haben und Frust stellt sich ein.

Manche Themeentwickler⋅innen legen ihren Meisterwerken deshalb Dummydaten bei, welche über den WordPress Importer auf die nagelneue WordPress Installation geladen werden können und so zumindest ein wenig Arbeit abnehmen. Das war zumindest immer eine nette Geste, aber bis WordPress 4.7 fehlte einfach ein ordentlicher Workflow für dieses Problem. Doch jetzt gibt es ein neues Feature, das zwischen all dem Jubel um PDF-Vorschaubilder, REST-API, Shortcuts und ich weiß nicht was, ein bißchen untergegangen ist: Starter Content. STARTER CONTENT! 🎉

Wenn Ihr mit einer frischen WordPress Installation in den Customizer geht, um Twentyseventeen zu konfigurieren, dann werdet Ihr nicht einfach einen leeren Blog mit einem “Hallo Welt”-Beitrag vorfinden. Vielmehr findet Ihr eine vollständig konfigurierte WordPress Installation vor. Es gibt ein Menü, eine Frontpage, eine About-Seite, einen Blog und eine Kontaktseite. Die Sidebar ist schon komplett konfiguriert und es gibt ein “Find us”-Textwidget, die Suche und ein Widget “About this site”. Sogar das Hauptmenü und das Socialmenü im Footer sind schon konfiguriert.

2017 Starter Content im Customizer
2017 Starter Content im Customizer

Ein⋅e Anwender⋅in kann nun einfach durch den Customizer spazieren gehen, die Widgets anpassen, raushauen, ersetzen, die Menüs abändern und schließlich mit “Speichern” die Einstellungen speichern. Der Theme-Installations-Workflow ist also komplett in den Customizer integriert.

Bisher funktioniert dies allerdings nur mit frischen Installationen, auf denen noch keine Seiten, Beiträge, Widgets oder sonstige Inhalte angelegt wurden. Es gibt allerdings schon Planungen, wie das Konzept am Besten auf alte Seiten übertragen werden kann.

Wie bereite ich “Starter Content” für mein Theme auf?

Der ganze Zaubertrick hängt nun natürlich an den Entwickler⋅innen von WordPress Themes. Sie müssen den Starter Content bereitstellen und die Konfiguration übernehmen. Dieser Beitrag gibt eine Übersicht, wie das zu bewerkstelligen ist.

Alles spielt sich dabei in der Aktion after_setup_theme ab. Hier kann die Unterstützung von starter-content mit Hilfe von add_theme_support() deklariert werden. Das Interessante ist nun der Konfigurationsarray, welcher mit dieser Deklaration übergeben wird.

Wir können Widgets, Posts, Attachments, Navigations-Menüs, Optionen und Theme-Mods in diesem Array übergeben. Wenden wir uns den einzelnen Möglichkeiten nach und nach zu:

Widgets

WordPress liefert schon eine ganze Reihe vorkonfigurierter Widgets mit. Sagen wir, in unserem Theme gibt es eine Sidebar mit der ID sidebar-1 und wir wollen in dieser das Suchwidget und ein Textwidget mit Öffnungszeiten darstellen, so können wir das wie folgt erreichen:

Im widgets-Bereich unseres Konfigurationsarrays sagen wir also: In der sidebar-1 sollen diese beiden Widgets auftauchen. Dies sind die vorformatierten Widgets, welche der WordPress Core bereitstellt:

  • text_business_info
  • text_about
  • archives
  • calendar
  • categories
  • meta
  • recent-comments
  • recent-posts
  • search

Sagen wir aber, Du möchtest einen individuellen Text in ein Textwidget einpflegen, wie würde das gehen? Statt einem einfachen Textstring übergeben wir nun einen Array. Das erste Element des Arrays enthält den Widget-Identifikator (die sogenannte id_base), hier text, der zweite Array enthält alle Informationen, welche das Widget über die $instance zum Rendern des Widgets benötigt:

Dies funktioniert dann natürlich nicht nur mit den schon im WordPress Core vorhandenen Widgets wie dem Archiv oder ähnlichen, sondern auch mit Widgets, welche über Plugins oder (eventuell) über das Theme bereitgestellt werden. Sehen wir uns dazu folgendes Beispiel an:

Wir registrieren hier zunächst unser Widget Mein_Widget() mit der Base ID meine-base-id. Und in der Methode widget() lassen wir uns im Wesentlichen einfach die $instance ausgeben. Schließlich weisen wir in unserer Content-Starter-Deklaration noch die Inhalte diesem Widget zu und schon wird dieses Widget mit den Inhalten angezeigt.

Posts

Um Beiträge, Seiten oder andere Inhalte für die Vorschau zu erstellen, könnt Ihr wie folgt vorgehen:

Wir legen hier eine Seite mit dem Identifikator test an. Wir weisen diesem Inhalt den Posttype page zu, einen Titel und einen Inhalt. Dieser Array wird schließlich als Übergabeparameter an wp_insert_post() genutzt, da diese Starter-Beiträge mit dem Status auto-draft in der Datenbank hinterlegt werden. So können natürlich auch benutzerdefinierte Felder mit übergeben werden, indem der Array um ein meta_input erweitert wird. Wenn Du einer Seite ein bestimmtes Seitentemplate zuweisen möchtest, kannst Du dies so tun:

'template' => 'sample-page-template.php'

Der WordPress Customizer liefert allerdings auch schon vorgefertigte Seiten, wie das folgende Listing darstellt:

Mit diesen sechs vorgefertigten Seiten erspart sich der/die Entwickler⋅in dann einiges an Konfigurationsarbeit.

Attachments

Attachments sind formal gesehen natürlich nichts anderes als ein besonderer Posttype. Allerdings gibt es bei Anhängen noch Dateien, welche mit bedacht werden müssen und diese machen es notwendig, Attachments separat zu konfigurieren. Dann sind sie allerdings eine wirklich interessante Angelegenheit:

Hier registrieren wir zunächst das Attachment featured-image-logo. Dieses steht uns dann zur Verfügung, um es beispielsweise mit Hilfe von {{featured-image-logo}} an einen Beitrag als benutzerdefiniertes Bild anzuhängen.

Unser besonderes Interesse gilt in diesem Listing natürlich dem file-Wert. Verknüpfte Mediendateien müssen im Theme selbst zu finden sein. Der Pfad zur Mediendatei kann entweder absolut oder aber relativ zum Theme-Verzeichnis angegeben werden. Im hier skizzierten Fall läge die Datei also hier:

http://example.com/wp-content/themes/theme-slug/assets/images/featured-logo.jpg

Dem ein oder anderem mag aufgefallen sein, dass wir den “About”-Beitrag, der ja ein WordPress Standard-Eintrag ist, hier mit einem Array registrieren. Wir können sämtliche Standard-Einträge nehmen und die Eigenschaften dieser Beiträge mit Hilfe solcher Arrays erweitern.

Die Navigation

Kommen wir zur Navigation. Sehen wir uns zunächst kurz das Listing an:

Wir erstellen zwei Seiten und machen uns dann daran, unser Menü zu konstruieren. In nav_menus bezeichnen die Array-Keys (hier beispielsweise top) die Menülocation, welche wir zuvor in unserem Theme registriert haben müssen. Mit name übergeben wir den Namen des Menüs und in items schließlich die einzelnen Menüitems. Das erste Item, welches wir übergeben ist page_home, ein WordPress Standard, welcher auf die Standardseite home verweist, welche wir oben registriert haben. Danach haben wir ein Array. Grundsätzlich gibt es zwei Navigationsitem-Typen, welche wir anlegen können: Objekte und Links. Objekte verweisen auf ein registriertes Objekt, in unserem Fall auf die Testseite, welche wir zunächst angelegt haben und dann über object_id mit {{test}} referenzieren. Auch object und type müssen dabei angegeben werden.

Darunter registrieren wir dann einen externen Link als Menüitem. Hierfür muss einfach eine URL in url und ein Titel in title übergeben werden.

Optionen und Theme Mods

Um Optionen oder Theme Mods anzulegen, wird options beziehungsweise theme_mods bereitgestellt. Diese Bereiche sind Schlüssel-Wert-basiert, wie das folgende Listing zeigt:

Hier sagen wir, dass wir auf der Startseite eine einzelne Seite anzeigen lassen wollen, und zwar die von uns angelegte home und dass wir als Blogseite unsere test-Seite verwenden wollen. Außerdem hinterlegen wir in den Theme Mods hinter dem Schlüssel color den (Farb-)Wert #f00.

Die Konfiguration filtern

Der Filter get_theme_starter_content kann diese Konfiguration dann noch einmal filtern. Dies ist vor allem dann nützlich, wenn ein Plugin sich einhaken möchte, um sein eigenes Widget in der einer Sidebar gleich mit zu präsentieren.

Schluss

So, ich hoffe, dieser kleine Überblick über das “Starter-Content”-Feature in WordPress 4.7 konnte Euch ein wenig weiterhelfen. Dieses Feature ist natürlich vor allem für Themeentwickler⋅innen interessant, welche ihre Themes einem größeren Publikum zur Verfügung stellen möchten. Es ermöglicht Euren Benutzer⋅innen einen möglichst schnellen und schmerzlosen Start mit dem von Euch entwickelten Theme.

Was hälst Du vom neuen “Starter-Content”-Feature? Hast Du es schon einmal eingesetzt oder ist es Dir als Anwender⋅in schon einmal aufgefallen?

Schlicht – Das neue WordPress Theme für meinen Blog

Das Schlicht Theme

Beginnen wir erst einmal damit, das Alte zu Grabe zu tragen: Ich glaube, ich hatte jetzt zwei oder drei Jahre hier im Blog immer das gleiche Theme laufen: Gumbo. Ich kann auch überhaupt nichts Schlechtes über das von Themato Soup erstellte Theme sagen; Es ist immer noch ein schickes Blogdesign. Eines der wenigen im Repository, welches hält was es verspricht und tatsächlich etwas verspricht. Zwar heißt es dort mittlerweile, dass es seit über zwei Jahren nicht mehr aktualisiert worden ist, da es aber wirklich ein solide gearbeitetes Theme ist, läuft das nach wie vor und ich glaube, es wird auch noch einige Zeit laufen.

Aber nach so langer Zeit wurde ich einfach etwas müde, auf meinen Blog zu schauen. Nur konnte ich mich nie aufraffen, mal ein anderes Design auszuwählen oder gar selbst aufzusetzen. Meine Fähigkeiten in dies Richtung sind auch eher beschränkt. Ich hatte schon ein bisschen mit Hannover geliebäugelt. Florian Brinkmann hat da einfach ein Händchen für schöne Blogdesigns. Aber so richtig durchringen konnte ich mich nicht.

Dann flog vor einiger Zeit ein Tweet über meine Timeline und ich wusste, wie mein Blog in Zukunft aussehen würde:

https://twitter.com/FloBrinkmann/status/804350472391888896

Schlicht hat eigentlich schon alles im Namen. Es kommt in einem schlichten und zurückhaltenden Design und ist überwiegend in Grautönen gehalten. Ich hätte ja nicht gedacht, dass ich einmal mit einer Serifenschrift im Block enden würde, aber das von Florian gewählte Sorts Mill Goudy hat es mir tatsächlich angetan und mit einer guten Schriftart fängt eigentlich jedes gute Blogdesign an.

Über den Customizer kann man zwischen zwei Grundlayouts wählen. Das erste Layout könnt Ihr in meinem Blog sehen, dass Zweite finde ich aber auch sehr schick. Die Überschrift findet sich dann links mit den ganzen Metadaten wie Autoren, Datum und so weiter und rechts dann der Beitrag. Ich hätte das zweite Layout gewählt, wenn ich nicht meine Sidebar dadurch verlieren würde, mit der ich Euch (jetzt in rot) auf mein Buch aufmerksam machen möchte. Beides zusammen ging leider nicht und so habe ich mich für die erste Variante entschieden.

Darüber hinaus kann man auch Initiale einschalten, wie man es aus Zeitungen oder Büchern kennt. Hier weiß ich noch nicht so recht und habe diese erst einmal nicht aktiviert. Neben der Sidebar gibt es noch einen Widgetbereich im Footer und man kann auch zwei Menüs einrichten. Für diesen Blog habe ich einfach schnell im Footer ein Menü für Impressum und dieses Zeug eingerichtet.

Schlicht ist Florian Brinkmanns erstes kommerzielles Theme und man kann es für 15 Euro direkt auf seiner Seite erwerben. Wenn man es herunterlädt kommt es gleich mit einem Child Theme zusammen, was einem die Mühe erspart, da selbst erst wieder eines zusammenzustöpseln. Das ist auf jeden Fall top. Darüber hinaus gibt es einen Updater, so dass ihr das Theme selbst ganz bequem über das Backend aktualisieren könnt, wie jedes Design, welches ihr über das WordPress Repository beziehen würdet.

Ja, ich habe ein neues Theme 🎉. Gefällt es Euch auch so sehr wie mir?

Nonces in der REST API

Wenn Du einfach mal schnell ein Nonce in der REST API von WordPress validieren möchtest kann es passieren, dass Du auf ein kleines Hindernis stößt. Ich hatte letztens ein kleines Script geschrieben, welches entweder über die admin-ajax.php läuft, wenn die REST API nicht vorhanden ist, ober aber über die REST API.

Schauen wir uns folgendes Script an, um das folgende Problem zu verdeutlichen:

Wir registrieren also die Ajax Action für admin-ajax.php und eine neue Rest Route. Der Callback ajax_nonce_test() bereitet im Wesentlichen die Daten auf und führt dann auf nonce_test(), die Funktion, welche auch von der Rest Route /rest-api-nonces/v1/nonce-test aufgerufen wird.

Am Ende registrieren wir noch einen Shortcode, der uns nur schnell die Test-URLs ausgibt.

Soweit der Überblick. Zentral ist nun, was in nonce_test() passiert. Hier wird geprüft, ob das in $request['testnonce'] übergebene Nonce gültig ist. Wenn nicht wird “FALSE” zurückgegeben, oder aber “TRUE”.

Jetzt zum Witz. Loggen wir uns ein, gehen auf die Seite und rufen die admin-ajax.php auf, so werden wir "TRUE" erhalten, über die REST API "FALSE". Whaaaat? Mehrere Sachen sollten hier beachtet werden:

  1. Die REST-API authentifiziert eine⋅n Benutzer⋅in anders als die admin-ajax.php.
  2. Um ein Nonce zu erstellen und zu verifizieren wird die User-ID herangezogen.

Ob ein⋅e Benutzer⋅in eingeloggt ist oder nicht, darüber entscheidet ein Cookie, welcher beim Einloggen hinterlegt wird. Passt der Cookie, sind wir eingeloggt. Geht die Nutzer⋅in auf die admin-ajax.php so ist er oder sie eingeloggt. Die REST API allerdings verwendet eine etwas umfangreichere Cookie-Authentifizierung. Hier genügt nicht ein einfaches Cookie, sondern dieses muss zusammen mit einem – Ironie der Geschichte – gültigen Nonce übergeben werden.

Basics der Authentifizierung in der REST API

In der WP_REST_Server gibt es eine check_authentication Methode, die eigentlich nur aus dem Filter rest_authentication_errors besteht. Wird über diesen Filter ein WP_Error-Objekt übergeben gilt eine Authentifizierung als gescheitert und wir erhalten ein “Du bist nicht berechtigt”-Response zurück. Über diesen Filter können also User-Authentifizierungen stattfinden.

Von Haus aus bringt WordPress die sogenannte “Cookie-Authentifizierung” mit, welche in der rest_cookie_check_errors() stattfindet. Wenn der Prozess in diese Funktion rennt sind wir noch immer – über unseren Cookie – eingeloggt. Doch wenn das entsprechende Nonce nicht gefunden wird, werden wir zunächst ausgeloggt, bevor es – jetzt eben nicht mehr eingeloggt – weiter geht. Wird ein Nonce gefunden, welches allerdings den falschen Wert enthält, so wird ein WP_Error zurückgegeben und der Zugriff ganz geblockt.

Wenn wir also mit dem Codesnippet von oben schließlich in unserem nonce_test()-Callback ankommen, haben wir keine User-ID mehr, die es allerdings braucht, da das Nonce mit einer solchen ID erstellt wurde.

Wie funktioniert Cookie Authentifizierung in der REST API?

Statt also irgendwie willkürlich ein Nonce zu übergeben, welches dann im Callback geprüft wird (es mag Gründe dafür geben, aber in meinem Fall brauchte ich es nicht noch einmal), sollte also ein spezielles Nonce übergeben werden: wp_create_nonce( 'wp_rest' );. Und natürlich muss auch der Parameter stimmen. Das wp_rest Nonce kann entweder über den Parameter _wpnonce oder aber über den Request Header X-WP-Nonce. übergeben werden. Eine gute Einführung dazu findest Du auf der API Dokumentation.

Zurück zu meinem Beispiel

Für meine Zwecke genügte es also, über den _wpnonce Parameter zu gehen. Da das Nonce in der REST API automatisch schon geprüft wird, verschiebe ich die Nonce-Validierung in die Ajax-Funktion. So sieht mein überarbeiteter Code aus:

Fazit

Wenn Du also irgendwo in Deinem Rest API Callback Nonces brauchst, achte darauf dass der Loginstatus der Nutzer⋅innen mit dem im Frontend überein stimmt. Vermutlich erledigt sich damit auch schon die Notwendigkeit für Dich, ein Nonce überhaupt zu benutzen, aber es mag Umstände geben, in denen es Sinn machen kann, auch im Callback Nonces zu validieren.