Integration einer Hilfe in DSM 3.x

Aus

Einleitung

Ich zeige euch hier am Beispiel vom DDNS updater wie man leicht seine eigene Hilfe in die DSM 3 Hilfe integriert.
Als erstes überlegen wir uns den strukturellen Aufbau unserer Hilfe, welche Baumstruktur wir benötigen und was dort hinein soll.

Voraussetzungen

  • installiertes Paket Init_3rdpartyHelp [1] (nur für DSM 3 notwendig!!!)
  • HTML-Kenntnisse

JSON Konfiguration (helptoc.conf) erstellen

Die Datei befindet sich im Anwendungsverzeichnis und enhält die Hilfekonfiguration. Der Indexer bekommt diese automatisch durch das DSM Paketmanagement bei der Installation, Aktualisierung und Deinstallation per Kommandozeile übergeben.

{
   "app": "SYNO.SDS._ThirdParty.App.ddnsupdater",
   "title": "DDNS updater",
   "content": "DDNSupdater/ddnsupdater_desc.html",
   "toc": [{
        "title": "helptoc:ddnsupdater_use",
        "content": "DDNSupdater/ddnsupdater_use.html",
        "nodes": [{
            "title": "helptoc:ddnsupdater_add",
            "content": "DDNSupdater/ddnsupdater_add.html"
        }, {
            "title": "helptoc:ddnsupdater_edit",
            "content": "DDNSupdater/ddnsupdater_edit.html"
        }, {
            "title": "helptoc:ddnsupdater_del",
            "content": "DDNSupdater/ddnsupdater_del.html"
        }, {
            "title": "helptoc:ddnsupdater_customprovider",
            "content": "DDNSupdater/ddnsupdater_customprovider.html"
        }]
    }, {
        "title": "helptoc:ddnsupdater_options",
        "content": "DDNSupdater/ddnsupdater_options.html",
        "nodes": [{
            "title": "helptoc:ddnsupdater_interval",
            "content": "DDNSupdater/ddnsupdater_interval.html"
        }, {
            "title": "helptoc:ddnsupdater_forceupdate",
            "content": "DDNSupdater/ddnsupdater_forceupdate.html"
        }, {
            "title": "helptoc:ddnsupdater_ssl",
            "content": "DDNSupdater/ddnsupdater_ssl.html"
        }, {
            "title": "helptoc:ddnsupdater_desktop",
            "content": "DDNSupdater/ddnsupdater_desktop.html"
        }, {
            "title": "helptoc:ddnsupdater_offlineip",
            "content": "DDNSupdater/ddnsupdater_offlineip.html"
        }, {
            "title": "helptoc:ddnsupdater_offlinescript",
            "content": "DDNSupdater/ddnsupdater_offlinescript.html"
        }]
    }, {
        "title": "helptoc:ddnsupdater_provider",
        "content": "DDNSupdater/ddnsupdater_provider.html"
    }]
}

Wir erstellen uns eine Datei "helptoc.conf" im root Verzeichnis unserer Anwendung und gestalten den Inhalt entsprechend unserer zuvor überlegten Baumstruktur. Stellt euch den Hilfebaum als eine Verzeichnisstruktur vor, die nodes wären dort die Verzeichnisse. Jeder nodes Eintrag enthält title und contents Einträge und kann weitere nodes Einträge beinhalten.
Die Texte helptoc:<name> sind Abschnitt:Variablen, die der Indexer beim Erstellen/Ändern der Indizes mit den Texten der entsprechenden Sprache ersetzt (siehe #Sprachdateien (strings) erstellen).
Achtet beim Schreiben der Datei darauf, das für jede { auch eine } existiert. Das gleiche gilt für die []. Der Indexer ist da sehr empfindlich und quittiert den Aufruf dann mit einem "Failed to load".

Erklärung der Schlüsselwörter

Parameter Beschreibnung Wert/Typ/Beispiel
app Name der Applikation, bei 3rdparty Apps immer SYNO.SDS._ThirdParty.App.<Anwendungsname> (Name wie er in der Datei INFO hinter "package=" steht oder der Verzeichnisname) alphanumerisch
title* Der Titel eines Eintrags/Zweiges alphanumerisch
toc Hier beginnt der Inhalt des Hilfebaumes (Table of Contents)
content* Inhalt, Pfad zur HTML-Datei, relativ zum Verzeichnis /usr/syno/synoman/webman/help/<Sprachkürzel> alphanumerisch
nodes Beginn eines Zweiges im Hilfebaum

* notwendig

Fassen wir zusammen:

  • Datei "helptoc.conf" im Anwendungsverzeichnis erstellen
  • Inhalt entsprechend unserer zuvor überlegten Baumstruktur erzeugen

Sprachdateien (strings) erstellen

Die Texte befinden sich in einer Datei "strings" im Verzeichnis /usr/syno/synoman/webman/texts. In diesem Verzeichnis existiert für jede Sprache ein Unterverzeichnis, in dem dann eine Datei "strings" mit den Texten liegt. Beispiel für deutsch: /usr/syno/synoman/webman/texts/ger/strings.
Damit wir die Original Dateien nicht für unsere Zwecke anpassen müssen und Synology dies mit grosser Wahrscheinlichkeit nicht für 3rdparty Anwendungen vorgesehen hat, habe ich einen kleine Modifikation geschrieben, die den Indexer so modifiziert, dass er auch mit Dateien von anderen Orten zurecht kommt (siehe Init_3rdpartyHelp).
Der Indexer wird nur beim Hinzufügen/Aktualisieren/Entfernen vom Hilfeindex benötigt.

Der Aufbau einer strings-Datei sieht folgendermaßen aus:

[helptoc]
ddnsupdater_use			=	"Einträge verwalten"
ddnsupdater_add			=	"Hinzufügen"
ddnsupdater_edit		=	"Bearbeiten"
ddnsupdater_del			=	"Löschen"
ddnsupdater_customprovider	=	"Selbsterstellte Anbieter"
ddnsupdater_options		=	"Einstellungen"
ddnsupdater_interval		=	"Überprüfungsintervall"
ddnsupdater_forceupdate		=	"Erzwingen der Aktualisierung"
ddnsupdater_ssl			=	"SSL-Verbindung"
ddnsupdater_desktop		=	"Desktopsymbol"
ddnsupdater_offlineip		=	"Offline IP"
ddnsupdater_offlinescript	=	"Offline Skript"
ddnsupdater_provider		=	"Unterstützte Anbieter"

Der Text [helptoc] bezeichnet einen Abschnitt. Es können beliebig viele Abschnitte innerhalb der Datei definiert werden, die Bezeichnung [helptoc] habe ich nur als Referenz zur Synology Datei beibehalten. Es kann auch jeder andere Bezeichner benutzt werden, achtet aber darauf, dass der Bezeichner dem Teil der Variablen im Baum entspricht, der vor dem : steht.
Erstellt nun ein Verzeichnis "help", danach in diesem Ordner für jede unterstützte Sprache ein neues Verzeichnis (siehe #Sprachkürzeltabelle), in der sich dann die Datei "strings" befindet. Beispiel: help/ger/strings
In der Datei "strings" müssen dann zu allen Platzhalter/Variablen aus dem obigen Beispiel die passenden Texte in der gewünschten Sprache enthalten sein. Findet der Indexer beim Erzeugen/Ändern keinen passenden Text, wird "null" an diese Stelle geschrieben, was dann einem nicht vorhandenen Text entspricht.

Sprachkürzeltabelle

ger = german
enu = english US
chs = chinese simplified
cht = chinese traditional
csy = czech
jpn = japanese
krn = korean
dan = danish
fre = french
ita = italian
nld = dutch
nor = norwegian
plk = polish
rus = russian
spn = spanish
sve = swedish
hun = hungarian
trk = turkish
ptg = portuguese european
ptb = portuguese brazilian

Fassen wir zusammen:

  • Verzeichnis "help" im Anwendungsverzeichnis erstellen
  • für jede zu unterstützende Sprache ein Verzeichnis unterhalb vom Ordner "help" erstellen (siehe #Sprachkürzeltabelle)
  • Datei "strings" mit Texten zu allen Platzhalter/Variablen, entsprechend dem definiertem Baum, in der gewünschten Sprache erzeugen

Hilfe-Seiten erstellen

Jetzt bauen wir unsere Hilfeseiten, entweder mit einem einfachen Editor oder besser grafisch mit einem HTML-Editor. Ein HTML-Editor hat den Vorteil, das wir das spätere Erscheinungsbild schon fast 100%ig beim Erstellen beurteilen können. Einen einfachen und kostenlosen HTML-Editor wäre zum Beispiel Amaya, es kann aber auch jeder andere Editor benutzt werden. Damit die Hilfeseiten im Stil der DSM 3 Hilfe angezeigt werden, erstellen wir einen Ordner in der Freigabe "public" und mounten dort hin das Verzeichnis /usr/syno/synoman/webman/. Nun starten wir den HTML-Editor und öffnen die erste Seite. Navigiert in den neu erstellten Ordner und öffnet z.B. die Datei help/ger/SystemInfoApp/SystemInfoApp_desc.html.
Nun kopieren wir den Quelltext des Kopfteils vom Anfang bis inklusive Systeminformationen und fügen ihn in eine neue Seite ein, den vorhandenen Kopfteil überschreiben wir natürlich. Jetzt haben wir den Style der original Hilfeseiten und können unsere eigenen Hilfeseiten darauf aufbauen. Die verschiedenen Stile wie z.B. Anmerkung Links und Überschriften stehen nun zur Verfügung. Schaut in die anderen Hilfeseiten um den gewünschten Stil zu finden. Ihr könnt natürlich auch eigene Stile oder Farben benutzen.
Damit wir später beim Verlinken zum "Synology help-Verzeichnis" keine Klimmzüge machen müssen, erstellen wir analog der originalen Struktur in jedem zuvor erzeugtem Sprachverzeichnis einen Ordner mit dem Anwendungsnamen. Komplett würde das so aussehen: help/<Sprachkürzel>/<Anwendungsname>. In diesen Ordner sichern wir die Hilfedateien der jeweiligen Sprache.

Falls ihr Grafiken in die Hilfe einbinden möchtet, solltet ihr diese am besten im Anwendungsverzeichnis z.B. im Ordner "help/images" ablegen. Es existiert zwar ein Verzeichnis Images im Hilfepfad, man müßte/sollte aber, damit kein "Müll" übrig bleibt, bei einer Deinstallation die Grafiken dort wieder entfernen. Die Arbeit erspart ihr euch mit einem eigenem images-Verzeichnis.

Fassen wir zusammen:

  • Verzeichnis in /public erstellen
  • Verzeichnis /usr/syno/synoman/webman/ in das neue Verzeichnis mounten
  • mount --bind /usr/syno/synoman/webman/ /volume(x)/public/<neues Verzeichnis> (für (x) und <neues Verzeichnis> bitte eure Daten eintragen)
  • Verzeichnisstruktur .../help/<Sprachkürzel>/<Anwendungsname>/... erstellen
  • HTML-Editor starten und Datei help\ger\SystemInfoApp\SystemInfoApp_desc.html öffnen
  • Quelltext des Kopfteils kopieren und in neue HTML-Seite einfügen, vorhandenen Kopfteil überschreiben
  • HTML-Seiten erstellen und in die angelegte Verzeichnisstruktur sichern

Test der Hilfe-Seiten

Vor dem ersten Lauf des Indexer's solltet ihr eine Kopie der Index-DB anlegen. Die Index-DB befindet sich in /usr/syno/synoman/indexdb.

ACHTUNG Wird die Option -a oder -d ohne Pfadangabe oder mit falschem Pfad benutzt, werden alle Hilfedateien aktualisiert oder entfernt!!!
Das dauert lange und kann im ungünstigstem Fall die Hilfe-DB unbrauchbar machen.

Damit wir die erstellten Hilfeseiten auch in der DSM-Hilfe sehen, muss der Indexer die Indizes in die Index-DB schreiben und für jede gefundene Sprache ein TOC im JSON-Format anlegen. Die TOC befinden sich anschließend im Verzeichnis ".helptoc" des Anwendungsverzeichnisses. Da der Indexer normalerweise nur bei einer Installation, Aktualisierung oder Deinstallation durch den Paketmanager aufgerufen wird, müssen wir dies für unseren Test manuell durchführen. Falls nicht schon geschehen, melden wir uns per telnet oder ssh auf der DiskStation an. Der Aufruf vom Indexer ist der folgende:
/usr/bin/php -n -d safe_mode_exec_dir=/usr/syno/bin /usr/syno/synoman/webman/modules/Indexer/indexer.php -a /volume1/@appstore/<Anwendungsverzeichnis>/helptoc.conf -s <Pfad-zum-Verzeichnis-der-strings>

Die für uns wichtigen Kommandos sind

-a = hinzufügen/aktualisieren <Pfad-zur-helptoc>
-d = entfernen
-s = <Pfad-zum-Verzeichnis-der- Sprachdateien (strings)> (ermöglicht durch den Patch mit Init_3rdpartyHelp)

Die Option "safe_mode_exec_dir" ist notwendig, da es sonst "open-base-dir" Fehlermeldungen hageln würde.

Am Beispiel für den DDNS updater müßte die Zeile folgendermaßen aussehen:
/usr/bin/php -n -d safe_mode_exec_dir=/usr/syno/bin /usr/syno/synoman/webman/modules/Indexer/indexer.php -a /volume1/@appstore/ddnsupdater/helptoc.conf -s /volume1/@appstore/ddnsupdater/help
Der Indexer sollte nun laufen und die entsprechenden Indizes und TOC erzeugen. Die Fehlermeldungen "No localized strings for..." und "File not found:" könnt ihr ignorieren, solange es sich nicht um eure erstellten Sprachen handelt.
Nach Aufruf des DSM-Hilfe-Browsers sollte ein neuer Zweig mit eurer Hilfe zu sehen sein. Prüft alle Zweige und beseitigt eventuelle Fehler in den Hilfe-Dateien. Den Indexer müsst ihr nur erneut aufrufen, wenn ihr Zweige hinzugefügt/entfernt oder die Titel/Inhalte der Zweige geändert habt. Um die Änderungen dann in die Index-DB zu übernehmen, reicht ein erneuter Aufruf mit den oben angegeben Optionen -a und -s. Der Indexer erkennt selbstständig das Vorhandensein von Einträgen und aktualisiert diese dann nur. Erkennen kann man dies am Text "records (added, replaced, deleted)" = (0, x, 0). (x = Anzahl)

Zum Löschen eurer Indizes aus der DB wird der Indexer mit der Option -d aufgerufen. Die Option -s ist hiefür nicht notwendig.

Benutzung in Installationspaketen (SPK)

Die folgenden Dateien/Verzeichnisse müssen dem Paket zusätzlich mitgegeben werden:

package.tgz

  • /.helptoc
  • /help
  • helptoc.conf

Sollte ihr Grafiken verwendet haben, müssen diese natürlich ebenfalls im entsprechenden Verzeichnis mitgegeben werden.

Der Indexer wird, bei vorhandener helptoc.conf, automatisch durch das Paketmanagement gestartet.

Installation/Aktualisierung

Im preinst-Teil des SPK sollte die Datei /tmp/3PHELPENABLED angelegt werden (siehe Init_3rdpartyHelp). Im postinst-Teil müssen dann nur noch die symbolischen Links für die HTML-Seiten erzeugt werden. Zum Anlegen der Links kann dieses kleine Script benutzt werden:

DSMVERSION=`/bin/get_key_value /etc.defaults/VERSION majorversion`
APPHOME="/usr/syno/synoman/webman/3rdparty/<Anwendungsname>"
if test $DSMVERSION -eq 3 ; then
    cd $APPHOME/help
    for langname in * ; do
         if test -d $APPHOME/help/$langname/<Anwendungsname> -a ! -h /usr/syno/synoman/webman/help/$langname/<Anwendungsname> -a $langname != "images" ; then
               /bin/ln -s $APPHOME/help/$langname/<Anwendungsname> /usr/syno/synoman/webman/help/$langname/<Anwendungsname>
         fi
    done
fi

Zuerst holt sich das Script die DSM Version. Ist die Version gleich 3, dann wechsel in das Anwendungsverzeichnis. Anschließend wird in einer Schleife für jedes gefundene Sprachverzeichnis überprüft, ob schon ein symbolischer Link existiert. Sollte Dieser noch nicht vorhanden sein, wird er angelegt. Dadurch wird bei einer Aktualisierung eine Verschachtlung der symbolschen Links in sich selbst verhindert.

Deinstallation

In meinen Tests stellte sich heraus, dass das Entfernen der Indizes aus der Index-DB bei der Deinstallation zu einem Timeout führt und die Deinstallation mit einer Fehlermeldung abbricht. Der Trick ist nun, die helptoc.conf zu verschieben, damit der Paketmanager nicht selbständig den Indexer aufruft. Dieser Schritt wird nun von uns mit dem folgendem Script im preuninst-Teil durchgeführt, da im postuninst-Teil das Verzeichnis entfernt wird:

DSMVERSION=`/bin/get_key_value /etc.defaults/VERSION majorversion`
if test $DSMVERSION -eq 3 ; then
    /bin/mv /usr/syno/synoman/webman/3rdparty/<Anwendungsname>/helptoc.conf /tmp/helptoc.conf
    if test ! -f /tmp/${SYNOPKG_PKGNAME}.upgrade ; then
        /usr/bin/php -n -d safe_mode_exec_dir=/usr/syno/bin /usr/syno/synoman/webman/modules/Indexer/indexer.php -d /tmp/helptoc.conf &
    fi
     /usr/bin/find /usr/syno/synoman/webman/help/ -type l -name "<Anwendungsname>" | while read langname ; do
         /bin/rm -f "$langname"
     done
fi

Am Anfang wird wieder die aktuelle DSM Version ermittelt. Ist der Wert gleich 3, wird die helptoc.conf nach /tmp verschoben. Die folgende Abfrage greift nur, wenn es keine Aktualisierung ist (Hintergrund: bei einer Aktualisierung wird das alte Paket trotzdem erst entfernt und dann erst das Neue installiert, Helpindex muss aber nicht enternt werden). Ist es eine reine Deinstallation, dann wird der Indexer manuell aufgerufen und mit & in den Hintergrund geschickt. Mit der abschließenden Schleife werden die symbolischen Links aus dem Hilfeverzeichnis entfernt.