Weil ich das Thema aber für sensibel erachte und ich einfach zu neugierig bin, habe ich auch gleich mal eine oberflächliche Prüfung der Webseiten auf Datenschutzaspekte vorgenommen. Ich bin da kein Profi also erwartet nicht zu viel. Mein Vorgehen ist recht einfach: mal schauen, was der Browser in den Entwicklungstools so für HTTP-Requests zu Dritten aufzeichnet und was für Cookies einem so angeboten werden. Wenn ihr auch mal nachschauen wollt vergesst aber nicht alle Plugins wie Adblocker und so auszuschalten, um das Ergebnis nicht zu verfälschen.
Der erste Baustein in meiner Vorsorge ist eine Vorsorgevollmacht. Damit könnt ihr einer Person eures Vertrauens weitgehende Vollmachten geben um eure Angelegenheiten zu regeln, wenn ihr dazu nicht in der Lage seit. Das ist auch in einer Ehe wichtig, es regelt sich nämlich auch dort nicht alles von alleine.
Das Bundesministerium der Justiz (BMJ) hat dazu eine Broschüre und ein PDF-Formular. So was gibt es auch wo anders, aber ich habe mich dort bedient.
Nun zu Seite. Das erste was auffällt ist ein Cookiebanner ‒ das Zeug ist allgemein wirklich die Pest. Aber es gibt zwei gleichwertige Buttons. Das ist ja schon mal was.
Nur teilt mir der Text gar nicht mit, in was ich hier eigentlich einwilligen soll. In die Nutzung von Cookies jedenfalls nicht, denn zu dem Zeitpunkt sind schon drei Cookies auf meiner Platte. Was da eigentlich gemeint ist wird klar, wenn man es mal ausprobiert: es wird dann nämlich ein Cookie gesetzt, das für das Tracking des Besuchers durch die Software Matomo genutzt wird. Gleichzeitig wird auch ein JavaScript von einer Adresse piwik.itzbund.de geladen. Piwik ist dabei der alte Name von Matomo. Bei der Informierten Einwilligung ist also noch Luft nach oben (und nein, die Datenschutzerklärung habe ich nicht gelesen).
Das Informationstechnikzentrum Bund ist übrigens so was wie der ausgelagerte IT-Dienstleister der Bundesverwaltung und eine Bundesbehörde.
Ansonsten wirkt die Webseite des BMJ aber harmlos. Ich will sogar noch positiv hervorheben, dass die Texte sogar unter eine Creative Commons gestellt sind, hätte ich ja nicht erwartet.
Nächste Anlaufstelle ist das Bundesministerium für Gesundheit. Dort habe ich mich zu einer Patientenverfügung informiert. Mit so einem Dokument könnt ihr vorab festlegen wie ihr medizinisch behandelt werden wollt, für den Fall, dass ihr euren Willen später nicht mehr äußern könnt.
Auch hier spring einen gleich ein Cookiebanner ins Gesicht. Dieses wird von der dänischen Firma Usercentrics und deren Produkt Cookiebot beigesteuert und ist ein Beispiel für Dark Patterns. Zwar ist nur das (angeblich) notwendigste vorausgewählt, aber der Button „Trotzdem alles akzeptieren“ ist farblich hervorgehoben und dort, wo üblicherweise der OK-Button positioniert wäre. Und warum braucht man überhaupt sieben Cookies für eine Informationsseite? Die Wahl eines Dienstleisters für die Verwaltung der Einwilligung ist vielleicht rechtlich in Ordnung, aber ich finde es persönlich verwerflich und hat nichts mit Datensparsamkeit zu tun..
Vom Gesundheitsministerium gelangt man zur Verbraucherzentrale die ein Online-Tool zum Erstellen einer Patientenverfügung anbieten.
Dort wartet diesmal kein Cookiebanner auf den Besucher. Auch Cookies selbst kann ich nicht feststellen. Dafür verwendet die Verbraucherzentrale einen externen Dienst um das Tool anzubieten. Es handelt sich um einen Service der Firma Bryter. Das ist allem Anschein nach eine Low-Code-Plattform, also ein Tool um zu Programmieren ohne klassische Programmiersprachen lernen zu müssen. Das impliziert eine Reihe von HTTP-Request von Servern dieser Firma und zusätzlich einem Zugriff auf eine Domain in der Amazon Cloud.
Die Verbraucherzentrale weißt auch in den Datenschutzhinweisen auf die Nutzung von Bryter hin. Allerdings scheint diese nicht ganz aktuell zu sein. Bryter hat seine deutsche Niederlassung mittlerweile in Frankfurt nicht mehr in Berlin. Wobei, so ganz kann ich nicht sagen wo die Firma sitzt. Im Impressum auf bryter.com finde ich den Firmennamen „Bryter US inc.“. In der Datenschutzerklärung von Bryter aber eine „Bryter GmbH“. Ich persönlich finde ja, dass so etwa höchstpersönliches wie eine Patientenverfügung nicht über Dritte abgewickelt werden sollte, schon gar nicht über US-Server wie die von Amazon.
Die Bundesnotarkammer erlaubt es die Unterlagen, die zuvor erstellt wurden, in einer zentralen Datenbank zu registrieren. Das hat den Zweck, dass Gerichte und Ärzte ermitteln können, ob eine Vollmacht oder Patientenverfügung vorliegt. Dabei werden nicht die Dokumente, sondern nur die Art der Dokumente und die Kontaktdaten erfasst.
Die Reservierung kann auch Online im Zentralen Vorsorgeregister erfolgen. Das Onlinetool setzt ein paar Session-Cookies, aber dankenswerterweise kein Cookiebanner und ich kann auch keine HTTP-Requests an Dritte feststellen. Als ich angefangen habe diesen Artikel zu schreiben wurden noch Schriftarten von Typekit geladen. Das wurde aber auf meinen Hinweis hin abgestellt. Ein vorbildliches Verhalten, wenn man Vertrauen wiederherstellen möchte.
]]>Als erstes die langweiligen Basics: Ein Webfont besteht aus mehreren sogenannten Schnitten die jeweils in einer Datei vorliegt. Ein Schnitt kann z.B. eine fette oder kursive (oder beides gleichzeitig) Variante sein. Weil aber ein Standard nicht genug ist gibt es für diese Dateien verschiedene Formate die in verschiedenen Browsern genutzt werden können.
Mit diesem Wissen können wir jetzt die Font-Face-Declaration in CSS nutzen um die einzelnen Schnitte/Dateien einem Namen und den gewünschten Parametern zuzuordnen. Im folgenden am Beispiel einer normalen Fette in Kursiv und „normal“
@font-face {
font-family:'Inria Serif';
src: url('InriaSerif-Italic.eot');
src: url('InriaSerif-Italic.eot?#iefix') format('embedded-opentype'),
url('InriaSerif-Italic.woff2') format('woff2'),
url('InriaSerif-Italic.woff') format('woff'),
url('InriaSerif-Italic.svg') format('svg');
font-weight: 400;
font-style: italic;
}
@font-face {
font-family:'Inria Serif';
src: url('InriaSerif-Regular.eot');
src: url('InriaSerif-Regular.eot?#iefix') format('embedded-opentype'),
url('InriaSerif-Regular.woff2') format('woff2'),
url('InriaSerif-Regular.woff') format('woff'),
url('InriaSerif-Regular.svg') format('svg');
font-weight: 400;
font-style: normal;
}
Mit font-family
kann man jetzt ganz normal auf die Schriftart unter dem gewählten Namen zugreifen.
In einem Font kann es alternative Sätze an Glyphen geben. Zum Beispiel gibt es bei der Inria Sans verschnörkeltere Großbuchstaben für besondere Gelegenheiten. Solche Gruppen an Glyphen heißen „Stylistic Sets“. In CSS aktiviert man diese Gruppen mit der Property font-feature-settings
. Die Gruppen sind durchnummeriert. So kann man den Wert für font-feature-settings
aus dem Präfix „ss“ und der zweistelligen Nummer (mit führenden Nullen) zusammensetzen:
.selektor {
font-feature-settings: 'ss01';
}
Welche Stylistic Sets es gibt unterscheidet sich in den verschiedenen Schriftfamilien, da muss man wohl immer etwas recherchieren.
Als Ligaturen bezeichnet man Glyphen die mehrere Buchstaben zusammen darstellen. Das macht man, je nach Sprache bei verschiedenen Buchstaben um ein fließenderes Schriftbild zu erhalten. In der Inria gibt es eine Reihe von Ligaturen für Kombinationen mit dem kleinen f. Um diese zu nutzen muss man gar nichts machen, bei Inria sind die Ligaturen standardmäßig aktiv. Wenn man doch Einfluss nehmen will gibt es dafür die Eigenschaft font-variant-ligatures
.
Für Nummern kann ein Schriftdesigner, ähnlich wie die Stylistic Sets, verschiedene Glyphen anbieten. Inria unterstützt Ziffern im alten Stil. Dabei werden die verschiedenen Ziffern mit etwas Unter- oder Oberlängen angezeigt.
Eine andere Darstellungsform ist für Zahlen und Beträge gedacht die untereinander angeordnet werden. Dabei haben alle Ziffern die gleiche Breite.
Beide Darstellungen kann man in CSS mit der Eigenschaft font-variant-numeric
steuern. Die relevanten Werte sind oldstyle-nums
beziehungsweise tabular-nums
.
Etwas das auch über font-variant-numeric
gesteuert wird ist die Darstellung von Brüchen. Anstatt den Zähler und Nenner mit einem Schrägstrich getrennt nebeneinander anzuzeigen kann man, ähnlich wie bei Ligaturen, ein solches Muster in eine schönere Darstellung umwandeln. Der passende Wert für die CSS-Eigenschaft ist diagonal-fractions
.
Damit das ganze nicht so trocken ist habe ich dazu Beispiele in meinem Laboratorien hinterlegt.
Andere Fonts können andere Features unterstützen, ich wünsche viel Spaß all die Vielfallt der Typographie zu erkunden.
]]>Eine etwas schmalere Lösung die wirklich nur die Zeit abruft ist mit systemd-timesyncd verfügbar. Für Raspberry Pi OS, einen Ableger von Debian für die namensgebende Platine, ist das auch der vorgesehene Weg.
Die Installation entfällt auf dem genannten Betriebssystem weil es bereits zum grundlegenden System dazu gehört. Lediglich die Konfiguration kann man noch anpassen.
Wenn man prüfen will wie der Status der Zeitsynchronisation auf dem eigenen Server ist kann man den Befehl timedatectl status
benutzen. Dieser gibt Auskunft über die Zeit und ob eine Synchronisierung mittels des Protokolls NTP vorliegt.
Es gibt drei priorisierte Arten über die der NTP-Server ermittelt werden kann. Auf Ebene der einzelnen Netzwerke (zum Beispiel des heimischen WLans) kann ein Server gesetzt sein. Wenn dies nicht der Fall ist wird eine Liste von NTP-Server herangezogen und danach eine zweite Liste von NTP-Servern (Fallback).
Der NTP-Server des Netzwerks wird nicht durch die Konfiguration von systemd-timesyncd eingestellt sondern ist Teil der manuellen oder automatischen (DHCP) Netzwerkeinstellungen.
Die beiden Listen können aber in der Konfigurationsdatei /etc/systemd/timesyncd.conf festgelegt werden. Dort kann in einer Zeile beginnend mit NTP= eine Liste von NTP-Server angegeben werden. Die Einzelnen Einträge werden mit Leerzeichen getrennt. Die zweite Liste beginnt mit FallbackNTP =. Die Einträge hier werden genutzt wenn die Server aus der ersten Liste alle nicht verfügbar sind.
Nach Änderungen kann man diese wirksam werden lassen in dem man timesyncd neu startet:
sudo systemctl restart systemd-timesyncd
Mittels timedatectl show-timesync --all
kann man sich ausgeben lassen welche NTP-Server in allen drei Prioritätsstufen konfiguriert sind und welcher aktuelle genutzt wird.
Die einfache Nutzung von timedatectl status
habe ich ja oben schon angesprochen. Mit timedatectl timesync-status
bekommt zusätzliche Informationen aus dem technischen Unterbau des NTP.
Wenn man eine Fritzbox als Router benutzt kann diese auch als NTP-Server für alle Computer im Netzwerk fungieren. Im Webinterface der Fritzbox links auf Heimnetz und dann auf Netzwerk klicken. Im rechten Bereich anschließend den Tab Netzwerkeinstellungen öffnen und dort im Abschnitt Zeitsynchronisation die gewünschten, externen Server angeben und einen Hacken setzen. Den Namen fritz.box von allen Fritzboxen muss dann wie oben beschrieben in der Konfiguration angeben.
Als externen Zeitserver für die Fritzbox würde ich das NTP Pool Project empfehlen.
]]>Mit BackstopJS kann man Screenshots einer Webseite machen um diese mit einer Referenz zu vergleichen. Sollten einzelne Pixel voneinander Abweichen bemerkt das Tool dies und schlägt Alarm.
Die Installation ist über NPM einfach durchgeführt.
npm install --save-dev backstopjs
Ich gehe dabei davon aus das es sich um ein Projekt handelt dessen Dependency Management mit NPM gemacht wird. Anderenfalls müsste man BackstopJS global installieren. Anschließend kann man das Tool für sein eigenes Projekt initialisieren. Dabei wird eine Konfigurationsdatei backstop.json erzeugt.
npx backstop init
Grundsätzlich wäre Backstop jetzt schon einsetzbar. Allerdings simuliert das Tool einen Browser. Damit wird auch ein Server benötigt von dem BackstopJS die Anwendung abrufen kann. Je nach dem um was es geht gibt es verschiedene Applikationsserver die man nutzen kann. Ich brauche für meinen Bedarf nur einen einfachen Webserver. Ich habe mich dabei ohne besonderen Grund für http-server entschieden.
npm install --save-dev http-server
Um später sowohl den Server als auch BackstopJS automatisiert nutzen zu können setze ich auch noch Concurrently ein. Dazu weiter unten mehr.
npm install --save-dev concurrently
Die zuvor erstellte Konfigurationsdatei enthält drei Bereiche: Viewports, Szenarien und Einstellungen.
Mit Viewports kann man die Maße des Browserfensters festlegen wenn die Screenshots durch BackstopJS angefertigt werden. Dabei sind mehrere Größenangaben möglich. Die Testfälle werden dann für jede dieser Größen durchgeführt. So kann man Tests für verschiedene Displaygrößen, z.B. von Smartphones und Desktops, durchführen.
Mit Szenarien beschreibt man die einzelnen Testfälle. Jedes Szenario wird primär durch einen Namen (label) und zwei URLs beschrieben. Die Referenz-URL (referenceUrl) wird aufgerufen wenn BackstopJS die Screenshots mit dem Soll-Zustand erzeugt. Damit werden dann Screenshots verglichen die von der Seite hinter der Test-URL (url) angefertigt werden.
Durch die zwei verschiedenen URLs lässt sich das Referenzmaterial z.B. von einem produktiven System anfertigen. Die Test-Screenshots möchte ich natürlich vom Entwicklungsstand und damit von http-server beziehen.
Wenn auf der Testseite Dinge sind die nicht relevant für den Test sind kann ich mittels der Angabe selectors eine Liste von CSS-Selektoren angeben. Anschließend beschränkt sich der jeweilige Screenshot auf die Elemente die diesen Selektoren entsprechen.
Wenn es darum geht dynamische Inhalte zu testen muss ich irgendwie die Interaktion des Nutzers simulieren. Um das zu ermöglichen setze Backstop auf Puppeteer. Puppeteer zu erklären würde den Artikel sprengen. Nur soviel: Mit onReadyScript lässt sich ein Script angeben das ausgeführt wird sobald die Testseite geladen wurde.
Alles was nicht Viewport oder Szenario ist fasse ich mal unter Einstellungen zusammen. Hauptsächlich geht es um Speicherorte für die Screenshots und die Testergebnisses und -berichte. Dazu kommen Parameter für den Browser und Puppeteer.
Eine Wert der später noch wichtig wird ist die Angabe der Art der Ausgabe des Testergebnisses. Mit report lässt sich festlegen ob ein menschen lesbarer HTML-Report eine JUnit XML- oder eine JSON-Datei (oder alles gleichzeitig) erzeugt werden soll.
Für die folgenden Schritte braucht man eine aufrufbare Fassung der zu testenden Webseite. Genau dafür habe ich vorher http-server installiert. In einer Shell kann ich den Server mit npx http-server -p 3001 -c-1
starten. In einer zweiten Shell kann ich dann die unten stehenden Befehle ausführen.
Das Arbeiten mit BackstopJS vollzieht sich in drei Phasen. Alles beginnt mit dem anfertigen der Referenzbilder: Von einer validen Fassung der zu testenden Webseite oder -app.
npx backstop reference
Nach der Entwicklung einer neuen Version folgt dann der Test. Erneut werden Screenshots erzeugt, mit den Referenzbildern verglichen und ein Report erzeugt.
npx backstop test
Anhand des Reports geht es dann an die Bewertung der Abweichungen. Solange etwas nicht zufriedenstellend ist wiederholt sich der Zyklus aus Entwicklung und Test. Sobald ich nichts mehr zu bemängeln habe wird die dritte Phase abgeschlossen indem die Referenzen aktualisiert werden.
npx backstop approve
Wie ich eben ausgeführt habe werden des öfteren Screenshots angefertigt. Da diese als Dateien gespeichert werden muss ich im Zusammenspiel mit Git ein paar Besonderheiten berücksichtigen. Git ist nicht besonderst gut darin Binärdaten zu managen. Damit das nicht zum Problem wird gibt es Git LFS. Damit werden Binärdateien im Git-Repository durch Pointer ersetzt während die Dateien außerhalb abgelegt werden.
Zuerst muss ich es für meine Git-Benutzereinstellungen herrichten, etwas das auf jedem Endgerät wiederholt werden muss:
git lfs install
Anschließend muss ich dem Git-Repository noch mitteilen für welche Dateien LFS zuständig sein soll. Im vorliegenden Fall wären das alle Bilddateien aus dem Ordner mit den Referenzbildern.
git lfs track "backstop_data/bitmaps_reference/*"
Der Befehl führt zu einer Eintragung in der Datei .gitattributes. Diese habe ich sinnvollerweise auch eingecheckt. Im Gegensatz dazu brauche ich weder die Screenshots aus den Tests noch die Reports in meinem Repository. Deshalb gehören die drei entsprechenden Ordner auf die Ignore-List:
backstop_data/bitmaps_test/
backstop_data/html_report/
backstop_data/ci_report/
Testen wird schnell lästig darum automatisiere ich alles wenn möglich. In meinem Fall besteht die Lösung aus einer Kombination aus NPM-Scripting und GitHub Actions.
Das folgende Script, in die Datei package.json eingefügt startet den Test:
"test:visual": "concurrently --success=first --kill-others \"npx http-server -p 3001 -c-1\" \"npx backstop test\"",
Der erste Teil (concurrently) führt mehrere Befehle parallel aus. Dabei werden alle parallelen Prozesse abgebrochen (--kill-others
) sobald einer davon beendet ist (--success=first
).
Im ersten der parallelen Befehle (http-server) wird der Webserver gestartet. Der zweite Befehl führt den eigentlichen Test aus.
Dieses Script kann jetzt in einer Action ausgeführt werden. Dabei lauern aber zwei Fallstricke:
Ich muss beim Checkout innerhalb der Action LFS aktivieren.
- uses: actions/checkout@v1
with:
lfs: true
Außerdem sind die Referenzbilder vom Entwicklungsrechner nicht unbedingt passend für die Laufzeitumgebung innerhalb der Action. Ich entwickle auf Windows und die Actions laufen üblicherweise mit Ubuntu. Das führt zu leichten Unterschieden im Rendering und damit auch in den Screenshots. Ich umgehe das Problem einfach indem ich auch die Referenzbilder immer neu erstelle, natürlich nicht von der neu entwickelten Version des Projektes sondern von der produktiven.
Das Projekt das ich zum ausprobieren verwendet habe kann auf GitHub eingesehen werden. Um es etwas komplizierter zu machen verwende ich dabei abweichend von oben aber eine Javascript-Konfiguration .backstoprc.js anstelle der JSON-Datei.
]]>Mit dem neuen Media-Feature screen-spanning lässt sich auf Geräten mit zweigeteiltem Display ein spezielles Styling anwenden. Momentan kann man damit zwischen vertikal oder horizontal geteilten Displays unterscheiden. Das Feature ist mir für meine Testseite zu Media Queries endlich mal was neues und wurde daher auch gleich eingebaut. Beim ausprobieren aber nicht vergessen die experimentellen Features zu aktivieren (edge://flags/#enable-experimental-web-platform-features)
Das erkennen von betroffenen Geräten ist ein erster Schritt. Um die Position und besonderst die Breite des Bereichs zwischen den Displayteilen in seinem Stylesheet berücksichtigen zu können gibt es zusätzlich neue Variablen mit denen es möglich ist die Aufteilung der eigenen Inhalte auf die Teile des Displays zu organisieren. Ich hab das für die oben erwähnte Testseite auf Basis eines Gridlayouts beispielhaft gemacht. Aber auch hier sind die Möglichkeiten auf den einfachen Fall eines zweiteiligen Displays beschränkt.
@media all and (screen-spanning: single-fold-vertical) {
body {
display: grid;
grid-template-areas:
"header nav"
"main nav"
"main aside"
"main footer";
grid-template-columns: env(fold-left) calc(100% - env(fold-left) - env(fold-width));
grid-template-rows: auto auto 1fr auto;
grid-gap: 0px env(fold-width);
}
}
Parallel zu CSS gibt einem Microsoft auch die Möglichkeit mittels Javascript auf die Teilung von Displays zuzugreifen. Hierbei wurde mit der Window Segments Enumeration API aber ein flexiblerer Ansatz gewählt der gut für verschiedenste Anordnungen von beliebig vielen Displays klar kommen sollte. Eine Einschränkung besteht konzeptionell lediglich darin das die Displays rechteckig sein müssen. Das liegt daran das die Beschreibung eines Teils der Anzeigefläche über einen Punkt (links oben) und einer Breite und Höhe geschieht. Diese Informationen kann man den Einträgen eines Arrays entnehmen das man wiederum mit window.getWindowSegments()
erhält.
Die Möglichkeiten im Styling mittels CSS sind noch beschränkt auf den einfachsten Fall, trotzdem ein pragmatischer Ansatz für die aufkommende Geräteklasse mit geteilten oder faltbaren Displays. Im Bereich Javascript gibt es diese Einschränkung nicht.
Ich hätte mir aber gewünscht das die Implementierung nicht nur mobile Geräte wie das Surface Duo unterstützen würde. Auch bei Desktops gibt es durchaus Multimonitorkonfigurationen die sich in der Window Segments Enumeration API niederschlagen könnten sobald sich ein Browserfenster über mehrere Monitore erstreckt.
]]>Wie der Name schon sagt, geht es darum, die Rollbalken des Browsers an den Style der eigenen Seite anzupassen. Dazu werden zwei neue CSS-Eigenschaften erfunden. Eine definiert Farben, die Andere bestimmt die Breite.
Ein Wort vorweg: wie bei allen Eingriffen in die UI(User Interface) des Browsers muss man sich bewusst sein, was man tut. Jede Änderung bricht mit der Erwartung des Benutzers und kann sich auf die Zugänglichkeit auswirken. Bezüglich letzterem ist besonders zu berücksichtigen, den Kontrast in den Farben hoch genug zu wählen.
Es handelt sich noch um einen sehr frühen Stand, daher werden beide Eigenschaften bislang nur von einem Browser unterstützt: Firefox.
Mit der Eigenschaft scrollbar-color
lässt sich sowohl die Farbe des „Schiebers“ als auch die Hintergrundfarbe einstellen. Dazu verwendet man einfach zwei Farbangaben mit einem Leerzeichen getrennt:
Die Scrollbar des Fensters hängt dabei am HTML-Element. Für innere Elemente wie z.B. Textarea-Elemente funktioniert die Eigenschaft natürlich auch.
Leider gibt es keine einzelnen Eigenschaften für die beiden Farben. Also muss man immer beides setzen. Das ist deswegen problematisch, weil man so nicht eines der beiden (z.B. den Hintergrund) auf dem Standard des Systems belassen kann.
Wenn man die Farben anpassen will, während gescrollt wird, kann man dies über Pseudoklassen (hover, focus, active) erreichen. Allerdings ist dabei zu beachten, dass Firefox immer noch eine Abdunklung oder Aufhellung der Farbe des Schiebers vornimmt.
Man kann anstelle der beiden Farbwerte auch eines der beiden Themes light
und dark
angeben. Ich denke mal, das ist für Systeme, die eine Art Dark-Mode der UI unterstützen. Bei mir hatte aber keiner der Werte eine Auswirkung.
Mittels scrollbar-width
lässt sich einer von drei Werten auswählen, der die Breite der Scrollbar bestimmt. Es besteht die Auswahl zwischen auto
für das „normale“ Design des Browsers, thin
für eine schmale Darstellung und none
zum Ausblenden der Scrollbars.
Mit none
kann der Bereich trotzdem noch gescrollt werden, zum Beispiel über das Scrollrad einer Maus. Das Ganze macht vielleicht in Kombination mit den Pseudoklasse Hover und Fokus Sinn. Damit kann man den Scrollbalken ausblenden, bis er gebraucht wird. Allerdings ändert sich dadurch auch die Breite der Box, was zu einem anderen Textumbruch führen kann.
Den Wert thin
hingegen, kann ich mir ganz gut vorstellen, bei Scrollbars innerhalb einer Seite. Unter Windows 10 wirken diese so nicht ganz so brachial als Fremdkörper.
Die Eigenschaft wird übrigens nicht vererbt. Man kann sie also nicht an einem Element setzen und erwarten, dass sie sich auch bei allen Kindern auswirkt. Stattdessen muss man sie überall deklarieren, wo man sie auch wirklich braucht (oder eben mit dem *-Selektor überall).
Nicht gerade das wichtigste Feature auf der Welt, aber ganz nett. Insbesondere die schmaleren Scrollbalken können bei Textareas recht schick sein. Ich hoffe aber, dass diese Einflussnahme in die UI durch die Nutzer leicht deaktivierbar sein wird. Ein paar Gruppen könnten sonst Probleme haben die schmalen Scrollbars zu bedienen oder die gefärbten überhaupt richtig wahrzunehmen.
Da ein Mitarbeiter von Microsoft an der Spezifikation arbeitet, besteht die Hoffnung, dass Chromium im Rahmen des neuen Edge Browsers auch bald unterstützt wird?
]]>Um das Innere einer Web Component zu kapseln verwendet man sogenanntes „Shadow DOM“. So erreicht man das nach außen nur ein einzelnes HTML Element sichtbar ist. Dadurch bedingt kann man aber auch keinen CSS-Selektor mehr erstellen der dieses Shadow DOM adressiert. Daher sehen Web Components immer so aus wie der Entwickler der Komponente es vorgesehen hat. Ein Einfluss von außen ist erst mal nicht vorgesehen. Um ein einheitliches Look and Feel in einer Webanwendung zu erhalten ist aber genau das wünschenswert.
Im Verlauf der Zeit gab es verschiedene Ansätze um eine solche Möglichkeit zu schaffen. Ich beschreibe im folgenden die Ansätze die momentan (also im November 2019) anwendbar sind und halbwegs praktikabel erscheinen. Vorweg: Eine einzelne übergreifend und flexibel nutzbare Lösung habe ich nicht.
13.09.2020: Die in diesem Abschnitt beschriebene Herangehensweise ist hinfällig geworden. Firefox unterstützt mittlerweile das Pseudoelement ::part() und kann daher die darauf aufbauende Lösung weiter unten nutzen. Zudem hat Chromium generell Untersützung für das das Schlüsselwort revert realisiert, leider aber nicht als Fallback für Custom Properties. So wie Chromium arbeitet macht der Ansatz hier sogar den Style in solchen Browsern kaputt.
In CSS gibt es mittlerweile eine Art Variablen um konkrete Werte mehrfach in seinem Stylesheet für Eigenschaften setzen zu können. Solche Variablen werden als Custom Properties bezeichnet.
Für die vorliegende Aufgabenstellung sind sie interessant weil sie die Grenzen des Shadow DOMs überwinden. Das bedeutet, außerhalb einer Web Component deklarierte Custom Properties können innerhalb der Web Component genutzt werden um das Shadow DOM zu stylen.
Wenn der Entwickler der Komponente Custom Properties als Werte nutzt und diese dann nicht deklariert wird kommt der angegebene Fallback zum tragen. Wenn ein solcher nicht angegeben wurde wird „unset“ angenommen. Das bedeutet die verschiedenen originalen Styles der Browser werden ausgehebelt.
Am Beispiel eines Buttons wird das Problem deutlich. Dieses Element sieht auf den verschiedenen Plattformen jeweils so aus wie ein Button nun mal auf der jeweiligen Plattform aussieht. Wenn diesem Button nun eine oder mehrere Custom Properties zugewiesen werden legt der Entwickler damit das Aussehen auf genau einen Wert fest: den Wert der Custom Property oder eben unset.
Solange Komponente und die nutzende Seite aus einer Hand kommen kann man noch sicherstellen das alle Custom Properties auch deklariert werden. Sobald aber mehrere Parteien ins Spiel kommen ist das aber schon sehr schwierig.
Eine Möglichkeit dieses Problem zu umgehen ist das Keyword „revert“ bei der Zuweisung als Fallback zu setzen. Revert sorgt dafür das die Eigenschaft auf den vom Browser vorgegebenen Wert gesetzt wird. Somit wird also nicht mehr unset angenommen. Das Problem dabei ist allerdings das momentan nur Firefox und Safari das Schlüsselwort unterstützen.
Schon für ein einzelnes HTML-Element gibt es eine Vielzahl an CSS-Eigenschaften. Für jede davon eine Custom Property vorzusehen ist enorm aufwändig. Bei komplexeren Konstrukten im Shadow DOM wird es schlicht unpraktikabel.
Noch schlimmer wird es wenn Pseudoklassen wie focus oder hover ins Spiel kommen. Dann müssen auch für diese wiederum Custom Properties vorgesehen werden.
Zusammen betrachtet kann diese Technik nur sehr selektiv eingesetzt werden. Etwas besseres für Firefox ist mir aber noch nicht untergekommen um ein wenig externe Farbe in Web Components zu bringen.
Goggle hat einen aktuellen Lösungsansatz in Chrome integriert. Das neue Pseudoelement „part“ erlaubt es auf Teile eines Shadow DOMs zuzugreifen. Dazu muss der Entwickler der Komponente das gewünschte Element mittels eines HTML-Attributes das wiederum „part“ heißt mit einem Namen versehen.
<button type="button" part="componentbutton">Ein Button innerhalb eines Shadow DOMs</button>
Anschließend kann der benannte Teil über CSS-Selektoren adressiert werden. So kann auf die übliche Weise das ganze Element neu gestaltet werden. Auch eine Kombination mit Pseudoklassen (fokus, hover) ist im Selektor ebenfalls möglich.
my-component::part(componentbutton) {
background: green;
}
my-component::part(componentbutton):hover {
background: darkgreen;
}
Auf diese Weise wird recht elegant ermöglicht das der Komponentenentwickler einzelne Teile seines Shadow DOMs freigeben kann und gleichzeitig erlaubt es dem Anwendungsentwickler eben diese Teile auf dem herkömmlichen Weg seinem Styleguide anzupassen. Leider unterstützten momentan nur Browser auf Chromium basierend dieses Feature. Zumindest Firefox hat allerdings schon eine experimentelle Implementierung. Hier kann man also hoffen.
Es gab seit der Einführung von Web Components auch ein paar andere Ansätze die aber wieder verworfen wurden. Wer ein bisschen „Altertumsforschung“ betreiben will sei der Artikel „Styling Web Components Using A Shared Style Sheet“ zur Recherche empfohlen.
Das Logo das ich zur Illustration dieses Artikels verwende entstammt einer Sammlung von Icons zum Thema Web Components. Es steht unter einer Creative Commons BY-SA 3.0 und wurde durch WebComponents.org bereitgestellt.
]]>(Geänderte Fassung um Entwicklungen beim Browsersupport von Firefox uns Chromium zu berücksichtigen)
]]>Aufgrund Alterungserscheinungen war es nötig das ich mir einen neuen eBook-Reader anschaffen. Seit 2012 hatte ich einen alt, ehrwürdigen PRS-T1 der Firma Sony der mich viele, viele Stunden begleitet hat. Da Sony keine eBook-Reader mehr produziert musste ich mich anderweitig umsehen. Kindle kommt nicht in frage; das Geschäftsgebaren von Amazon im Bereich der eBooks schmeckt mir nicht. Da gibt es zu viel DRM und zu viel proprietäres Zeug. Die Entscheidung viel dann auf einen Tolino Epos. Der Grund hierfür ist das große Display.
Jedem würde ich das knapp 20cm große Display nicht als Kaufgrund empfehlen. Bei mir ist es aber so das ich neben Romanen auch öfter mal Fachbücher mit Codelistings lese und bei letzterem erhoffe ich mir eine bessere Darstellung durch die größere Fläche. Bei Romanen ist das kompaktere Format des Sony Readers meiner Meinung nach angenehmer zu halten.
Durch die höhere Auflösung wirk der Text auf dem Tolino klarer als auf dem Sony. Auch ist der Hintergrund etwas heller, auch ohne die Hintergrundbeleuchtung zu aktivieren die das alte Gerät von Sony noch gar nicht hatte. Bei aktivierter Beleuchtung wirkt der Hintergrund noch heller, was den Kontrast noch mal etwas verbessert.
ePaper-Displays müssen gelegentlich, kurzfristig schwarz gefärbt werden um Schatten zu beseitigen die von zuvor angezeigten Seiten zurückbleiben. Dieses Verhalten hat mich bei meinem Sony schon nach kurzem nicht mehr gestört. Beim Epos fällt es mir momentan noch negativ auf, das ist aber eventuell der gesteigerten Aufmerksamkeit geschuldet die ich neuen Dingen entgegenbringe.
Ein Unterschied der ins Auge fällt ist die Gehäusefarbe: Warum müssen die Geräte heute alle schwarz sein? Ein weißes Gehäuse, wie das meines PRS-T1, ist irgendwie dichter am gedruckten Buch und fördert die Konzentration auf den Inhalt. Ist aber wahrscheinlich Geschmackssache. Einen Vorteil hat das Gehäuse des Epos gegenüber dem Sony: Das Display ist plan eingelassen.
Wo der Sony-Reader noch richtige Tasten hatte, die allerdings zum Prellen neigten, hat der Tolino Epos nur noch ein Sensorfeld unterhalb des Displays mit dem man zum Hauptmenü zurückkommt. Mich stört es nicht, wegen des Prellens habe ich sowieso meist das Touchdisplay genutzt. Jetzt habe ich einfach nur keine Wahl mehr.
Zur Performance kann ich zum jetzigen Zeitpunkt noch nicht viel sagen. Bei PDFs fühlt sich der Tolino etwas langsam an. Das war aber auch nie eine Stärke des Sony. Der wiederum mit zunehmenden Alter immer langsamer wurde, vor allem beim öffnen von Büchern. Ich weiß allerdings nicht ob das am Füllstand des Speichers, an den heutigen eBooks oder an sonst was liegt.
Beim Tolino gibt es übrigens keinen SD-Karten-Slot und auch keinen Kopfhöreranschluss. Beides habe ich beim Sony bisher auch nie gebraucht. WLAN haben sie hingegen beide.
Das erste was auffällt ist das niedliches StandBy-Bild. Dieses schlafende Tolinogesicht ist aber leider nur 5 Minuten niedlich danach hab ich mich satt gesehen. Was ich wirklich will ist die Anzeige des Buchcovers das ich gerade lese. Ich verknüpfe die Inhalte im Gedächtnis nämlich gerne mit dem Cover. Leider gibt es diese Funktion vor Version 12.2.0 nur auf meinem alten Sony-Reader. Um wenigstens das Tolino-Gesicht los zu werden kann man ein anderes Bild zur anzeige bringen. Dazu muss man lediglich eine Datei mit dem Namen „suspend.jpg“ auf dem Gerät ablegen. Eine Anleitung dazu gibt es auf papierlos-lesen.de. Mit ein wenig Suchen im Internet findet man verschiedene Sammlungen von Bildern in funktionierenden Größen. Ich habe mich aus einer Liste abstrakter Bilder bedient. Seit Version 12.2.0 gibt es in den Einstellungen aber auch die Möglichkeit das Buchcover anzeigen zu lassen. Wenn man aber wie hier beschrieben ein eigenes Bild hinterlegt hat überschreibt dies die Einstellung zum Coverbild im Menü. Die Datei suspend.jpg muss also gelöscht werden damit die neue Option greifen kann.
Wem die Schriftarten nicht gefallen kann die Liste der verfügbaren Fonts einfach ergänzen. Dazu muss man die Font-Datei einfach in einen speziellen Ordner auf dem Gerät kopieren. Details kann man dem Tolino-FAQ entnehmen.
Beim Markieren von Stellen innerhalb von Büchern hat der Sony PRS-T1 trotz seines Alters die Nase vorn. Esselsohren können beide in Seiten machen. Auch können beide Geräte Textstellen markieren, der Epos allerdings nicht in PDFs. Was der Epos aber nicht kann ist Freihandmarkierungen zu malen. Manchmal, zugegebenermaßen Selten, mache ich sowas bei Diagrammen.
Wenn man nicht nur eBooks im EPUP-Format konsumiert sondern auch mal das ein oder andere PDF konnte mit dem Sony-Reader mehr Optionen nutzen. Zum Beispiel kann man mehrspaltigen Seiten in mehrer Kacheln aufteilen um dann von Oben nach Unten und von Rechts nach Links durchzublättern. Auch kann man die Seitenränder wegschneiden um mehr Platz für den Text zu schaffen.
Beide Funktionen bietet der Tolino nicht an. Was er anbietet ist eine Vergrößerung des Textes in mehreren Schritten, die Darstellung im Querformat und eine „nur Text“-Darstellung.
Das Vergrößern ist nur nützlich wenn man einzelne Details, zum Beispiel in einem Diagramm, näher betrachten will. Dabei werden nämlich die Zeilen auf mehrere Bildschirmseiten verteilt so das ein flüssiges lesen nicht mehr möglich ist.
Im Querformat sind PDFs in Oben und Unten geteilt. Damit erhält man eine gute Lesbarkeit. Leider ist die Navigation nur wenig durchdacht. Wenn man auf dem Touchdisplay nach Links wischt kommt man nicht etwa erst von oben nach unten und beim nächsten Wisch zur folgenden Seite sondern gleich eine Seite weiter womit die untere Hälfte einer Seite übersprungen wird. Um dorthin zu kommen muss man von Unten nach Oben wischen. Das führt dazu das man jede halbe Seite einmal umdenken muss.
Die dritte Option extrahiert den reinen Text aus dem PDF und zeigt ihn ohne Formatierung an. Dabei werden auch Fußzeilen mitten im Text positioniert und es entsteht ein fürchterlicher Textbrei.
Positiv kann man aber hervorheben das das große Display ausreichend ist um ganze DIN-A4-Seiten groß genug darstellen zu können das man den Text, gute Augen vorausgesetzt, lesen kann.
Da beide hier verglichenen Geräte WLAN haben, bringen Sie auch beide einen Browser mit. Leider sind diese Browser lieblos und Funktionsarm. Den des Tolinos zu untersuchen habe ich recht schnell aufgegeben. Meine Enttäuschung, und das bezieht sich auf beide Reader, macht sich hauptsächlich an zwei Punkten fest:
Der Browser scrollt durch Webseiten. Das verursacht Schlieren und ein ständiges Flackern. Das ist meines Erachtens dem ePaper geschuldet. Es ist einfach nicht schnell genug fürs Scrolling. Von einem Browser auf einem eReader würde ich erwarten das er Webseiten seitenweise blättern kann. So wie es ist kann ich den Browser nur als Notbehelf
verwenden.
Ein technischer Aspekt der Aufzeigt wie wenig Sorgfalt in den Browser gesteckt wurde betrifft das monochrome Display. CSS Media Queries erlauben es diese Eigenschaft abzufragen. Leider behaupten beide Browser standhaft Sie würden auf Farbdisplays zugreifen können.
Was mir den Spaß auf dem Tolino zusätzlich vermiest ist die fehlende Möglichkeit die Startseite zu ändern. Was soll das? Warum muss ich immer erst einen Ausflug zu Google machen bevor ich Surfen kann?
Tolinos sind mit einer integrierten Shop ausgestattet der dem Online-Shop des Anbieters entspricht bei dem man den Tolino gekauft hat. Das wäre soweit nicht schlimm, leider werden mir lauter nutzlose Buchvorschläge auf dem Launcher präsentiert die ein Drittel der Oberfläche in Anspruch nehmen. Das Feature lässt sich leider auch nicht abschalten.
Mehr kann ich zu diesem Thema nicht sagen da ich meine Bücher lieber am PC kaufe und daher den Epos noch nie zu diesem Zweck genutzt habe.
Noch etwas das das Betriebssystem des Sony dem Tolino voraus hat ist die Verwaltung von Serien und Kategorien. Der Sony kann in kombination mit Calibre die Bücher automatisch in sogenannte Sammlungen einsortieren. Dabei können verschiedene Informationen genutzt werden und die Bücher gleichzeitig in mehreren davon abgelegt werden. Zum Beispiel kann man das Buch „Die Herren von Winterfell“ in Fantasy und in „Game of Thrones“ ablegen. Bei Tolino hingegen muss man etwas tricksen und bekommt doch nur maximal eine Serie, wo heißt das Feature bei Tolino, hin. Andere Serien müsste man von Hand direkt auf dem Gerät zuordnen, was recht nervig ist.
Die Serie wird aus dem Ordner abgeleitet in dem das Buch auf dem Epos abgespeichert wird. Um eine Bestimmte Information aus den Metadaten in Calibre in einen Ordnernamen zu verwandeln muss man in den Einstellungen von Calibre unter „Senden von Büchern auf Geräte“ im Feld „Speichervorlage“ ein neues Muster anlegen nach dem Calibre den Speicherpfad auf dem Gerät bildet. Wenn man diese Muster nicht für alle Geräte ändern will kann man auch, bei angeschlossenem Reader, in der Symbolleiste unter „Gerät“ den Menüpunkt „Dieses Gerät konfigurieren“ wählen und dort wiederum das Feld „Speichervorlage“ ausfüllen. Die Anleitung von Calibre führt auf wie die Vorlagensprache für diese Muster funktioniert.
Ich habe folgendes Muster für mich gewählt. Es erzeugt einen Ordner für das erste Stichwort, einen Unterordner für die Buchreihe und benennt die Datei dann nach Reihe inklusive Nummer, Titel und Author. Wenn keine Stichwort oder keine Reihe festgelegt ist entfallen die jeweiligen Ordner.
{tags:list_item(0,\,)}/{series}/{series:| - |}{series_index:0>2s}_{title}_{authors}
Leider führt es nicht zur Zuordnung von mehreren Serien wenn man die Dateien in tiefen Ordnerstrukturen ablegt. Lediglich die tiefste Ebene führt auch dazu das dass Buch in einer Serie abgelegt wird. In meinem Fall hat also die Reihe Vorrang vor dem ersten Stichwort.
Nach dieser ersten Begutachtung und einer Woche der Nutzung muss ich leider sagen das Sony die Software bereits vor sechs Jahren besser hinbekommen hat. Mit der Hardware bin ich hingegen recht zufrieden soweit man das nach so kurzer Zeit sagen kann.
]]>Die Entwicklung im Bereich der Hardware von eBook-Readern ist klar erkennbar – bei der Software hingegen…
(Geänderte Version unter Berücksichtigung von Version 12.2.0 der Tolino-Software)
]]>Spaß beiseite! Das Buch von Uwe Post ist ein eingängiges Lesevergnügen für alle die Software entwickeln. Dank des luftigen, lockeren Schreibstils liest es sich recht schnell weg. Inhaltlich geht das Werk auf allerlei Techniken und Tools die in Java- und C#-Projekten die Entstehung einer Software unterstützen: Versionskontrolle, Projektmanagement, Teamkommunikation, Testing, Dokumentation, Continuous Integration. Vieles davon wird der Programmierer von Heute hoffentlich schon kennen. Für mich war das Buch allerdings nicht aufgrund seiner einzelnen Themen interessant sondern aufgrund der kompakten Auffrischung des gesamten Ökosystems das zur Entstehung von guter Software beiträgt.
Die eben beschriebenen Themen werden ergänzt durch „echte“ Programmierthemen wie Entwurfsmuster, Refactoring und Multithreading. Alles zusammen hat ganz klar seinen Schwerpunkt auf die Java-Welt. Für alle .NET-Fans wird auch noch auf die Eigenheiten dieser Plattform und deren Tools eingegangen. Für andere Umgebungen muss der Leser den Inhalt aber selber adaptieren.
Alles in allem bin ich sehr zufrieden mit dem Buch. Um allerdings noch etwas Kritik zu üben hier zwei Punkte: Bei manchen der Anmerkungen zu den eingestreuten Anekdoten viel es mir schwer zu entscheiden ob diese sarkastisch gemeint sind oder nicht – ein Nachteil der Schriftform. Bei der Vorstellung des Toolings zum Continous Integration wird für Java nur auf Jenkins eingegangen, im Gegensatz zu allen anderen Kapitel wo eigentlich immer auch eine Alternative besprochen wird. Ob dies daran liegt das Jenkins allem anderen Haushoch überlegen ist oder der Author keine Erfahrung über Jenkins hinaus aufweisen kann wird nicht klar.
Ich beziehe mich übrigens auf die gedruckte Version, zur Aufbereitung als eBook kann ich nichts sagen. Die Form (Zeilenabstand, Schriftgröße und so) ist, passend zum lockeren Schreibstil des Autors, recht luftig und leicht lesbar. In der Marginalspalte gibt es verstreut Stichwörter über den nebenstehenden Absätzen. Die hätte es meines Erachtens nicht benötigt, sie stören aber den Lesefluss nicht.
]]>In Vorbereitung auf das Update musste ich ein paar Vorbereitungen treffen:
Ich deaktivierte des Plugins egg_anonymizer. Dies ist notwendig da Textpattern 4.7 alle Datenbankspalten entfernt hat die sich auf IP-Adressen beziehen. Eben diese Spalten adressiert aber egg_anonymizer um die Zugriffsdaten zu anonymisieren. Wenn man das Plugin nicht deaktiviert wird erhält man eine Reihe von Fehlern beim schreiben oder ändern von Artikeln und wahrscheinlich auch an anderen Stellen.
Vorsichtshalber habe ich auch alle angebotenen Updates für die installierten Sprachen eingespielt. Dazu muss man innerhalb von Textpattern im Menü unter „Administration“ und dann „Sprachen“ den entsprechenden Button bei jeder der betroffenen Sprache klicken.
Abschließend habe ich noch die empfohlenen Maßnahmen aus der Anleitung durchgeführt. In aller Kürze sind das Logout und Browsercache löschen.
Das eigentliche Upgrade habe ich streng nach Anleitung durchgeführt. Also anlegen eines Backups und einspielen der neuen Dateien. Wenn man eigene Änderungen, z.B. an der Datei .htaccess vorgenommen hat muss man diese in die neue Version reintegrieren. Beim Abschließenden Aufruf von Textpattern (nicht der damit erstellten Webseite) wird dann das Upgrade durchgeführt.
Bei mir verlief alles wie gewünscht und fehlerlos.
Nach dem Upgrade bietet es sich an den Menüpunkt „Diagnostics“ aufzusuchen und eventuelle Fehlermeldungen zu bearbeiten. In meinem Fall waren das zwei Stück:
Im Rahmen der neuen Unterstützung von Website-Themes wird ein neues Verzeichnis themes auf dem Webserver benötigt. Dieses hatte nach dem Upload der Dateien zu meinem Hoster nicht die nötigen Rechte. Das musste ich daher kurz anpassen.
Das zweite Problem besteht darin das der Update-Server von Textpattern nicht kontaktiert werden kann. Dies macht sich durch die Meldung „problem_connecting_update_server“ bemerkbar. Bislang konnte ich diesem Problem noch nicht nachgehen. Da ich aber den Textpattern-Blog registiert habe bekomme ich sowieso mit wenn es neue Versionen gibt.
Eine weitere Maßnahme um das Update zu prüfen ist in den Einstellungen die Seite in den Debug-Modus zu schalten. In diesem Modus erhält man zusätzliche Warnungen und Fehlermeldungen während man sich die Webseite ansieht. Am besten also in diesem Modus alle Arten von Seiten (Liste, Artikel, Suchergebnis und was man sonst so hat) aufrufen und sehen ob oben irgendwelche Meldungen auftauchen. Anschließend nicht vergessen den Modus wieder zurück zu stellen.
]]>Für das Backup benutze ich Dirvish. Meine Konfiguration habe ich in einem Artikel Backup Debian vorgestellt. In einem weiteren Artikel habe ich beschrieben wie man Speichermedien mit Hilfe von dm-crypt und LUKS verschlüsselt. Mit diesen beiden Zutaten ist das Ziel verschlüsselter Backups eigentlich schon erreicht. Leider stört die notwendige Eingabe der Passphrase die Automatisierung der Backups.
Die Passphrase wird hinfällig sobald ich für die Verschlüsselung eine Keyfile verwende. Mit Hilfe einer solchen Datei kann die Festplatte genauso entschlüsselt werden wie mit einer Passphrase. Solange also die Datei auf dem Computer verfügbar ist, der das Backup machen soll kann das Backup automatisch erfolgen.
Aber, ist das jetzt überhaupt noch sicher? Die Gegenfrage die ich hier stellen muss ist: Sicher vor was? Wenn ein Angreifer Zugriff auf den Rechner hat und damit an die Keyfile kommt kann er sich auch gleich an den original Dateien bedienen und braucht das Backup nicht mehr. Wenn sich jemand aber das Backup aus dem Bankschließfach (oder sonst wo her) besorgt hat er keinen Zugriff auf die Keyfile und kann daher die Daten nicht lesen.
Als Keyfile kann im Grunde jede beliebige Datei herhalten. Am wenigsten vorhersehbar dürfte aber zufälliger Inhalt sein. Dazu kann man mit folgendem Befehl eine 4 KB große Datei mit Zufallsbits erzeugen:
sudo dd if=/dev/urandom of=/root/backupKeyfile bs=1024 count=4
sudo chmod 0400 /root/backupKeyfile
Der zweite Befehl ändert die Zugriffsrechte auf ein Minimum (lesend für Root).
Die soeben erzeugte Datei muss nun als zusätzlicher Schlüssel bei den verwendeten Festplatten hinterlegt werden. Im folgenden gehe ich davon aus das dass Backupmedium als /dev/sdb erreichbar ist. Die folgenden Beispiele sind daher gemäß den eigenen Bedingungen anzupassen.
Mit der Operation luksAddKey des Befehls cryptsetup können zusätzliche Schlüssel hinterlegt werden. In meinem Fall wähle ich Key-Slot 1, Slot 0 wird schon durch die Passphrase genutzt. Jeder der Key-Slots kann unabhängig von den anderen genutzt werde um die Daten zu entschlüsseln. Ich habe damit also zwei Möglichkeiten an die Daten zu kommen: Für das Backup nutze ich Slot 1 mit der Keyfile. Wenn allerdings, zum Beispiel bei einem Systemcrash, das Keyfile verloren geht kann ich immer noch die Passphrase verwenden um auf die Daten zuzugreifen.
sudo cryptsetup luksAddKey --key-slot 1 /dev/sdb /root/backupKeyfile
Um das Öffnen und Mounten der Backupmedien zu erleichtern habe ich ein kleines Shellscript geschrieben. Dieses ermittelt das angeschlossene Medium über die UUID. Für alle verwendeten Medien muss man diese UUID im Vorfeld ermitteln und das Script entsprechend anpassen.
Recht einfach ermittelt man die UUID im Zwei-Schritt-Verfahren: Zuerst lässt man sich die (meist) sprechenden IDs aller Festplatten ausgeben um die zugehörige Gerätedatei zu bestimmen. Anschließend listet man die UUIDs aller Disks auf und sucht sich anhand der Gerätedatei die benötigte aus.
ls -la /dev/disk/by-id
ls -la /dev/disk/by-uuid
Das eigentliche Script prüft nun nacheinander, welche der Platten angeschlossen ist und mounted diese. Das Beispiel ist hier für zwei Platten aufgeführt:
if [ -e /dev/disk/by-uuid/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee ]
then
/sbin/cryptsetup luksOpen --key-file /root/backupKeyfile /dev/disk/by-uuid/aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee backup
else
if [ -e /dev/disk/by-uuid/ffffffff-gggg-hhhh-iiii-jjjjjjjjjjjj ]
then
/sbin/cryptsetup luksOpen --key-file /root/backupKeyfile /dev/disk/by-uuid/ffffffff-gggg-hhhh-iiii-jjjjjjjjjjjj backup
else
exit 1
fi
fi
mount /dev/mapper/backup /backup
Umgekehrt kann das schließen und aushängen des Mediums mit einem Zweizeiler erledigt werden:
umount /dev/mapper/backup
/sbin/cryptsetup luksclose backup
Bei der Installation von Dirvish wird bereits ein Cron-Job eingerichtet der täglich ein Backup durchführt. Dieser Cron-Job wird in der Datei /etc/cron.d/dirvish für die nächtliche Ausführung eingeplant. Bei der Ausführung wird dann das Script /etc/dirvish/dirvish-cronjob aufgerufen.
Das genannte Script löscht, so wie es nach der Installation vorliegt, alle abgelaufenen Backups und legt dann ein neues an. Dies funktioniert nur dann wenn ein Backupmedium gemounted ist. Daher habe ich in der Datei /etc/dirvish/dirvish-cronjob den oben beschriebenen Code für das öffnen und schließen der Backupmedien ergänzt.
Um bei Fehlern benachrichtigt zu werden musste ich übrigens nicht extra tätig werden. Cron benachrichtigt automatisch per E-Mail wenn das jeweilige Script einen Fehler verursacht. Dem Thema wie man solche E-Mails an eine externe Adresse weiterleitet habe ich einen anderen Artikel gewidmet.
Damit ist das Backup jetzt weitestgehend automatisiert. Der einzige manuelle Schritt der noch bleibt ist es das Backupmedium regelmäßig zu wechseln. Solange niemand einen vertrauenswürdigen, sicheren und autonomen Roboter erfindet wird das wohl leider auch so bleiben.
]]>In der Systemsteuerung, im Bereich „Sicherheit und Wartung“ gibt es einen Menüpunkt „Einstellungen der Benutzerkontensteuerung ändern“. In dem Dialog der sich dahinter verbirgt empfehle ich den Regler ganz nach oben zu schieben um den sichersten aber auch restriktivsten Modus zu aktivieren.
Die Benutzerkontensteuerung ist eine Sicherheitstechnik in Windows die vor Konfigurationsänderungen, Installationen und anderen kritischen Operationen eine Rückfrage einblendet die Nachfragt ob man weiß was man tut.
Mit den „Datenschutzeinstellungen“ fängt bei mir üblicherweise die Arbeit direkt nach der Installation an. Da ich ein recht stabiles Set an traditionellen Anwendungen für meine alltäglichen Arbeiten habe und diesem Appgedöhns bislang nicht viel abgewinnen konnte schalte ich in den meisten Kategorien den Zugriff erst mal pauschal ab. Der Witz ist nämlich das die meisten Einstellungen sich nur auf die Apps auswirkt die man aus dem Windows Store bezieht (inklusive der vorinstallierten).
Windows 10 ist meines Erachtens ganz schön aufdringlich wenn es darum geht die Microsoft-Apps in den Vordergrund zu spielen. Für die meisten Aufgaben habe ich aber gar keine Verwendung oder traditionellere Alternativen. Es ist mir aber zu anstrengend den ganzen nicht benötigten Kram zu deinstallieren, insbesondere weil ich das Gefühl hatte das die Apps mit irgendwelchen Update ständig wieder zurückkommen.
Abhilfe habe ich mir mit W10Privacy verschafft. Das Programm erlaubt es unzählige Einstellungen in Windows vorzunehmen und die meisten Windows-Apps zu deinstallieren. Wenn ich damit die unerwünschten Apps deinstalliere bleiben sie bislang auch weg.
Wer die Muße aufbringt alle Einstellungen die W10Privacy darbietet durchzusehen kann auch sonst viel erreichen um Microsofts Datenhunger zu bändigen.
Windows kann die Systemzeit gemäß verschiedener Zeitserver aus dem Internet festlegen. Die Information welche Server dazu verwendet werden kann man finden wenn man in der Systemsteuerung über die Kategorie „Zeit, Sprache und Region“ den Dialog „Datum & Uhrzeit“ öffnet und dort wiederum auf dem Reiter „Internetzeit“ den Button „Einstellungen Ändern“ klickt. In dem dadurch geöffneten Dialog kann man die Liste der Server einsehen. Man kann auch neue Server hinzufügen indem man deren Adresse einfach in die Dropdown der Server einträgt. Die vorhandenen zu löschen scheint aber nicht zu gehen.
Anstelle des vorausgewählten Servers von Microsoft würde ich empfehlen den des eigenen Routers (zum Beispiel einer Fritz!Box) zu verwenden falls dieser einen Zeitserver mitbringt. Alternativ gibt es auch das NTP Pool Project das NTP-Server bereitstellt.
Die Liste der Zeitserver findet man in der Registry von Windows wieder. Unter dem Key Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\DateTime\Servers
sind Einträge pro Server abgelegt. Diese kann man dort auch löschen.
Detailliertere Informationen zu diesem Thema gibt es auch auf WinFAQ.
Microsoft hält es wohl für eine gute Idee Sicherheitszertifikate bei Bedarf nachzuladen. Ich nicht! Wenn Windows oder ein Programm das die Crypto-API von Windows nutzt auf ein Sicherheitszertifikat stößt das noch nicht bekannt ist, wird einfach mal bei Microsoft angerufen und nachgefragt ob die es für Vertrauenswürdig halten. Es gab hierzu mal einen Artikel in der c’t der darlegt warum man das nicht so gut finden kann.
Um den Mechanismus abzustellen kann man in der Registry einen neuen Eintrag hinterlegen. Dazu muss man mit dem Programm regedit.exe
unter dem Schlüssel Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\SystemCertificates\AuthRoot
einen Eintrag vom Typ DWord mit dem Namen DisableRootAutoUpdate
und dem Wert 1
anlegen.
Mit einem Windows 10 auf dem aktuellen Patchstand kann man den unsinnigen Sperrbildschirm deaktivieren. Der Sperrbildschirm ist die Anzeige die man nach dem Starten des Computers erst wegwischen muss bevor man sich anmelden kann. Wozu das Ding gut ist hat sich mir bislang nie erschlossen – also weg damit.
Wie bei Heise beschrieben muss man den Registry-Key Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\Personalization
anlegen und darin den Eintrag NoLockScreen
mit dem Wert 1 hinterlegen.
Da ich jetzt bestimmt schon wieder irgendwas vergessen habe werde ich diesen Artikel sicher noch mal ergänzen müssen.
Momentan experimentiere ich auch mit Software Restriction Policies. Diese Richtlinien sind dank des Magazins c’t und dem Tool Restric’tor recht komfortable zu konfigurieren. Allerdings habe ich Probleme mit verschiedenen Spieleplattformen und mit Entwicklungstools im Zusammenhang mit Node.js. Mal sehen wann ich die Zeit finde dieses Thema zu vertiefen.
Wenn du noch andere Einstellungen oder Tipps kennst benutz doch bitte die Kommentarfunktion, ich würde darüber freuen.
]]>Der Updateprozess ist in der Dokumentation von Textpattern beschrieben und unterscheidet sich nicht von dem Update auf Version 4.5.1 über das ich in einem Artikel vor einigen Jahren bereits geschrieben habe.
Achtung ist geboten wenn man, so wie ich, Anpassungen an einzelnen Dateien vorgenommen hat. Ich habe zusätzliche Konfigurationen in den beiden Dateien „.htaccess“ (eine davon im Unterverzeichnis „textpattern“) vorgenommen. Solche Anpassungen muss man in den neuen Dateien entsprechend nachziehen.
Bei mir trat diesmal ein Fehler auf: Das Updatescript das nach dem Einloggen gestartet wird konnte aufgrund von fehlenden Berechtigungen einen Ordner nicht löschen. Nachdem ich die entsprechenden Rechte kurzfristig vergeben hatte wurden wiederum Dateien nicht gefunden die im ersten Versuch bereits gelöscht worden sind. Ich konnte das Problem lösen indem ich die bemängelten Dateien aus dem Backup wiederhergestellt habe. Danach konnten die Dateien und der Ordner gelöscht werden. Abschießend habe ich die Rechte wieder zurückgesetzt.
Ein neues Feature von Textpattern 4.6 ist das Description-Feld. Hiermit ist es möglich zu jeder Seite (und anderen Elementen innerhalb von Textpattern) eine Beschreibung zu erfassen. Diese Beschreibung kann, ähnlich wie das bereits vorher vorhanden Feld für Keywords, in den Metaangaben des erzeugten HTML ausgegeben werden.
Bislang habe ich eines der benutzerdefinierten Felder für diese Aufgabe verwendet. Um zukünftig stattdessen das neue Feld nutzen zu können ist es nötig die bereits erfassten Beschreibungen zu kopieren. Das geht am leichtesten direkt auf der Datenbank. Das folgende SQL-Statement kopiert die Beschreibung aus der Spalte für das benutzerdefinierten Feld 10 in die neue Spalte.
UPDATE textpattern SET description = custom_10;
Danach kann man das die bisherigen Beschreibungen aus der ursprünglichen Spalte löschen:
UPDATE textpattern SET custom_10 = '';
Abschließend muss man in seinen Seitenvorlagen den bisherigen Code durch das neue Tag <txp:meta_description> ersetzen.
]]>Ein Problem im Web entsteht durch die Nutzung von Ressourcen verschiedener Herkunft. Was eigentlich eine der Stärken des Netzes ist, Ressourcen verschiedenster Art und Herkunft zu verknüpfen, eröffnet auch Gefahrenquellen. Insbesondere im Umgang mit User-Generated-Content tritt dies immer wieder zutage. Findige Angreifer finden immer wieder einen Weg Schadcode zur Ausführung zu bringen. SQL-Injection, Cross-Site-Scripting und andere Angriffsvektoren funktionieren weil Code in einer fremden Anwendung oder Webseite eingeschleust werden konnte. Ein anderes Beispiel ist der Android-Bug Stagefright. Hierbei wird eine manipulierte Videodatei genutzt um in Android einzubrechen.
Mit der Content Security Policy versucht das W3C das Problem abzumildern. Dazu kann der Entwickler für verschiedene Arten von Ressourcen oder Zugriffstechniken definieren welche Quellen als Vertrauenswürdig gelten. URLs anderer Quellen sollen vom Browser dann gar nicht erst geladen werden.
Im aktuellen Entwurf des CSP Level 2 identifiziert die Spezifikation im folgenden aufgeführten Arten von Ressourcen. Für jede dieser Arten ist eine Direktive definiert unter der die erlaubten Quellen aufgeführt werden können:
script-src
)style-src
)img-src
)font-src
)media-src
)form-action
)connect-src
)object-src
)plugin-types
)child-src
)frame-ancestors
)Für alle diese Direktiven, außer plugin-types
, kann man eine Liste von URL-Masken angeben die dann als vertrauenswürdig gelten. In diesen URL-Masken, bestehend aus Protokoll, Hostname, Port und Pfad. Jeder Teil kann weggelassen werde, das bedeutet dann ‘jedes Protokoll’ beziehungsweise Hostname, Port oder Pfad. Der Host kann generalisiert werden durch einen *.
Hier einige Beipiele:
https:
– nur HTTPS-Ressourcenhuman-injection.de
– nur Ressourcen von human-injection.de*.human-injection.de
– nur Ressourcen von Subdomains unterhalb von human-injection.de*:443
– alle Ressourcen über Port 443https://*.de:443
– alle Ressourcen aus HTTPS-Quellen unterhalb der deutschen TLD über Port 443http://human-injection.de:80/Home
– nur die angegebene URLDer Stern (*) kann nur in Zusammenhang mit Domainnamen verwendet werden. Alleine verwendet bedeutet er: Jede Domain in Kombination mit jedem Protokoll, jedem Port und jedem Pfad. Diese Beschränkung auf Host- oder Domainnamen hat einige überraschende Auswirkungen. Durch die Verwendung des Asterisk werden nämlich Protokolle wie file://, data:// oder blob:// nicht erfasst da sie sich nicht auf Hostnamen beziehen. Diese Protokolle müssen daher zusätzlich angegeben werden wenn Sie benötigt werden.
Mozilla hat übrigens vor Version 40 des Firefox diese Regel nicht beachtet und das Verhalten nachträglich in Ihrem Browser angepasst, was bei bei meinem Podcatcher zu hübschen Fehlern geführt hat.
Im Gegensatz zu anderen Direktiven schränkt plugin-types
nicht die Quelle ein sondern die Dateiformate die wiedergegeben werden können. Die Werte sind demzufolge auch nicht URL-Masken sondern MIME-Types. Mittels der Angabe application/pdf werden etwa PDF-Dokumente für das Einbetten zugelassen, aber alle anderen eingebetteten Inhalte nicht geladen.
Wenn man die Inhalte auch nach ihrer Quelle filtern will kann man dafür die Direktive object-src
zusätzlich nutzen.
Zusätzlich zu den URL-Masken lassen sich auch vier Schlüsselwörter verwenden.
Mit ‘none’ (inklusive der Anführungszeichen) werden alle Quellen für die verwendete Direktive abgewiesen. Auf alle Ressourcen von der Domain der Webseite schränkt hingegen das Keyword ‘self’ ein.
Für Scripte und Stylesheets gibt es noch zwei weitere Schlüsselwörter. Die Nutzung der entsprechenden CSP-Direktiven führt dazu das auch Inline-Scripte beziehungsweise -Styles nicht angewendet werden. Mit ‘unsafe-inline’ schaltet man dieses verhalten wider ab. Allerdings sind Inline-Scripte ein großes Einfallstor für Angreifer, man sollte dieses Keyword also mit bedacht einsetzen.
Das andere Schlüsselwort ‘unsafe-eval’ erlaubt den Einsatz der eval-Funktion in Javascript. Auch hier sollte man sich genau überlegen was man tut.
Um nicht alle elf oben aufgeführten Direktiven einzeln konfigurieren zu müssen gibt es auch noch die Direktive default-src
. Damit lassen sich die Direktiven child-src
, connect-src
, font-src
, img-src
, media-src
, object-src
, script-src
, style-src
zusammenfassen.
Nach all den bisherigen Ausführungen über Direktiven bleibt die Frage wie diese überhaupt den Browser erreichen? Normalerweise verwendet man dazu den HTTP-Header Content-Security-Policy
. Als Wert dieses Headers verwendet man, durch Semikolon getrennt, die Direktiven.
In Webserver Apache kann man den Header am einfachsten über die htaccess-Datei einfügen:
set Content-Security-Policy "default-src 'self'; img-src: img.human-injection.de"
Alternativ kann man auch ein HTML-Meta-Tag verwenden, das ist aber nur zweite Wahl:
<meta http-equiv="Content-Security-Policy" content="script-src 'self'; img-src: img.human-injection.de">
Anstelle des Blockierens von Ressourcen kann man auch auf ein Reporting ausweichen. Dazu verwendet man den HTTP-Header Content-Security-Policy-Report-Only
mit den selben Werten wie oben und einer Report-URL zusätzlich. An diese URL wird im Fall eines Verstoßes gegen die CSP ein JSON-Bericht geschickt.
Content-Security-Policy-Report-Only: "default-src 'self'; img-src: img.human-injection.de; report-uri http://human-injection.de/csp.report"
Wenn man seine Seite testen möchte bietet sich SecurityHeader.io an. Hier bekommt man auch gleich noch ein paar andere Tipps.
]]>Diese Gelegenheit nutze ich um das CSS Flexible Box Layout Module in meinem CSS einzuführen. Ich finde das Konzept hinter diesem Layout-Modul recht vielversprechend. Es ermöglicht sehr flexible zeilen- oder spaltenweise Anordnung von Elementen. Die Kompatibilität ist auch recht gut wenn man auf veraltete Browser keine Rücksicht nimmt.
Der erste Schritt besteht darin zwei nebeneinander angeordneter Bereiche zu erzeugen, einen für das Logo, einen für die Navigation.
<div id="toparea">
<header role="banner"></header>
<nav role="navigation"></nav>
</div>
Um das Flexbox-Modul zu aktivieren verwendet man den Wert flex für die CSS-Eigenschaft display. In diesem Fall sollen die beiden Elemente header und nav zeilenweise angeordnet werden. Dafür sorgt die Angabe flex-direction: row;
. Mit justify-content: flex-start;
sorgt man dafür das die Kindelemente von Links nach Rechts angeordnet werden.
Ein Vorteil von Flexboxen ist ihr Umgang mit dem verfügbaren Platz. Die Kindelemente, die sogenannten Flex-Items, erhalten soviel Platz wie sie benötigen. Sollte dann noch Platz in einer Zeile, respektive einer Spalte, übrig sein wird dieser nach einem festzulegenden Schlüssel verteilt. Diesen legt man über die Eigenschaft flex-grow für die einzelnen Items fest. Die damit angegebenen Werte definieren das Verhältnis der Elemente zueinander. Im vorliegenden Fall erhält das Logo keinen und die Navigation allen zusätzlichen Platz.
Die Kindelemente in einer Flexbox können natürlich unterschiedlich hoch (bei Spaltenanordnung: breit) sein. Die Eigenschaft align-items mit dem Wert stretch sorgt dafür das sie alle auf die gleiche Höhe ausgedehnt werden. So sind der Header und die Navigation immer gleich hoch.
#toparea {
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: flex-start;
align-content: stretch;
align-items: stretch;
}
#toparea > header {
flex-grow: 0;
}
#toparea > nav {
flex-grow: 1;
}
Im zweiten Schritt wird die vertikale Anordnung der beiden Elemente im Bereich der Navigation realisiert. Dazu wird das Nav-Element in einen Flexbox-Container umgewandelt und die flex-direction als column definiert. Die weiteren Eigenschaften werden identisch zum ersten Schritt gesetzt.
<div id="toparea">
<header role="banner"></header>
<nav role="navigation">
<div id="mainnav"></div>
<div id="seqnav"></div>
</nav>
</div>
Wie man am Markup ablesen kann ist die primäre Navigation oberhalb der Sekundären niedergeschrieben. Im Layout soll dies aber andersherum dargestellt werden. Hierzu kann auf die Eigenschaft order zurückgegriffen werden. Damit ist es möglich die Darstellungsreihenfolge innerhalb einer Flexbox unabhängig von derjenigen im Markup zu verändern.
#toparea nav {
display: flex;
flex-direction: column;
flex-wrap: wrap;
justify-content: flex-start;
align-content: stretch;
align-items: stretch;
}
#mainnav {
flex-grow: 1;
order: 2;
}
#seqnav {
flex-grow: 0;
order: 1;
}
Im dritten Schritt wird der Zweck des Flexbox-Moduls ein wenig strapaziert. Um die Menüpunkte der Hauptnavigation zu strecken und unten auszurichten werden auch hier wieder Flexboxen verwendet obwohl es nicht direkt um die Umsetzung eines Rasters geht.
<div id="mainnav"></div>
<ul>
<li><a>Item 1</a></li>
<li><a>Item 2</a></li>
<li><a>Item 3</a></li>
</ul>
</div>
Damit sich sowohl die Liste als auch die einzelnen Listenpunkte auf den gesamten verfügbaren Platz ausdehnen, werden diese wiederum als Flexboxen konfiguriert. Bei den Listenpunkten wird ein abweichender Wert für align-items verwendet: Der Wert flex-end sorgt dafür das die Schrift unten ausgerichtet wird.
#mainnav ul {
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: flex-start;
align-content: stretch;
align-items: stretch;
flex-grow: 1;
}
#mainnav ul li {
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: flex-start;
align-content: flex-start;
align-items: flex-end;
}
]]>