Update meiner Open source docs

Freitag, 19. August, 2022

Unter https://www.axel-hahn.de/docs/[POJEKT] habe ich diverse Hilfen für PHP- und Javascript Tools bereitgestellt, die ich mit einem Parser generieren lasse. Jener Ansatz ist etwas älter und länger her - und stellt bereits geraume Zeit so einige meiner Dokumentationen bereit…

Eigentlich suchte ich nach einem mehr generischen Ansatz, um heutzutage in Git übliche Markdown-Dateien in statisches HTML umzuwandeln. Es gibt da diverse Tools, aber ich bin beim PHP-CLI Tool Daux hängengeblieben. Insbesondere, weil ich hier im Gegensatz zu anderen angetesten Werkzeugen keine Extra Konfiguration für einen Navigationsbaum als Config-Datei hinterlegen muss. Auch hat der Entwickler sehr schnell reagiert und auf gemeldete Feature Requests reagiert. Kurz: ich habe nun diverse einzelne Dokumentationen verschiedener Produkte und Klassen mit Daux gebaut. Das sind jeweils statische Verzeichnisse mit statischen HTML-Dateien + Javascript und Css out of the Box in jedem Browser laufen, wenn man sie vom Filesystem oder aber USB-Stick startet.

Was diverse Markdown zu Html Generatoren bieten, ist ein eingebauer Webserver für eine Vorschau. Der hilft beim Schreiben der Markdown-Dateien. Mittlerweile in Markdown Quasi-Standard ist der Support von mathematischen Formeln oder aber Graphen (mermaid.js) - das soweit ich auf Github, Gitlab oder aber lokal im Visual Studio Code per Markdown Preview gesehen habe.

Soweit so gut. Und wenn ich nun zig alleinstehende Dokumentationen habe und eine Index-Seite haben will?

Ich habe dazu einen Ansatz zum Generieren einer Index-Seite wie folgt gewählt:

  • ich möchte Gruppen: nach Programmiersprache oder nach einer sonstigen Rubrik
  • in jeder Rubrik werden N Projekt-Dokumenationen verlinkt
  • … wobei jene referenziert wird als Git-Repository, um diese mit Daux on the fly generieren zu lassen
  • … oder aber: weil ich noch meine geparsten Dokumentationen habe: ich kann anderweitig bestehende Dokumentationen ebenfalls einbetten
  • die Index-Seite soll flexibel sein und verschiedene Templates/ CSS/ Javascritpt unterstützen

Ich habe dazu ein Bash-Skript geschrieben, das mit jq eine JSON Config-Datei parst und mittels eines Templates die Seitenelemente generieren lässt. Die Flexibilität steckt in den Templates - dese bestimmen, ob es ein

OK, all das ist zu viel Text … so sieht meine Übersichtsseite mit dem Template mit Gruppen und Boxen sieht so aus: Axels Docs

2022-08-20-multidoc-generator-page_boxes.png

weiterführende Links: (en)

  1. Axels Docs-Index-Seite
  2. daux.io Hilfe-generator - Markdown zu HTML
  3. Github: axelhahn/multidoc-generator
  4. Statische Hilfe zum multidoc-generator
  5. Mermaid.js

PHP CLI und FPM-Service: /tmp besser meiden

Montag, 21. Februar, 2022

Ich habe da eine PHP-Applikation, die ein Webinterface besitzt als auch per CLI einige Dinge - z.B. als Cronjob - aufruft.

Beide Arten von Skripten - bei Http Aufruf oder aber CLI - durchliefen dasselbe Init-Prozedere und referenzierten ein und dasselbe File.

$this->sTouchfile = sys_get_temp_dir() . '/some_file.tmp';

Oder besser: ich hatte es zumindest gemeint. sys_get_temp_dir() wurde auf dem Linux-System als “/tmp” aufgelöst. Also optisch war es dieselbe Datei: /tmp/some_file.tmp - aber Das Webinterface erkannte eine Aktion auf CLI Seite nicht … und umgekehrt das CLI nicht eine Schreibaktion aus dem Webinterface.

Bis ich dann mal auf die Idee kam und mir mit einem per Http aufgerufenem Skript eine spezifische Datei in /tmp/ anlegte und diese mal im Filesystem suchte. Unter dem PHP-FPM Service war als /tmp/ jenes “tmp” Verzeichnis verwendet worden:

/tmp/systemd-private-d1b7cf65cce54d4ca9f98c49cca1887f-httpd.service-NoEzTN/tmp/

Das hat mir das ungewöhnliche Verhalten auch sofort erklärt.

Man merke: /tmp sollte man meiden, wenn man gemeinsame Daten per http als auch CLI Daten teilt. Ich habe in meiner Applikation von sys_get_temp_dir() auf ein “tmp” unterhalb [Approot] umgestellt…

weiterführende Links:

  1. php.net: sys_get_temp_dir()

IML Appmonitor ist nun PHP 8.1 kompatibel

Donnerstag, 16. Dezember, 2021

Der Appmonitor ist eine PHP-Applikation mit geringstmöglichen Anforderungen. Mit dieser lassen sich andere (Web-)Applikationen in einem Webfrontend überwachen und bei Statuswechsel Notifikationen per E-Mail und Slack an die am Projekt beteiligten Personen auslösen.

Das Applikationsmonitoring ergänzt unser System-Monitoring, weil es die applikationsseitigen Checks aus Sicht der Applikation und mit den Rechten der Applikation ausführt.

Der Appmonitor ist Freie Software, Opensource und untersteht der GNU GPL 3.0.

Nach gefühlt 2 Jahren habe ich am IML Appmonitor weitergecodet. Es sollte PHP 8 kompatibel werden. Und weil soeben PHP 8.1 erschienen ist, wurde es nun auch für ebenjene Version 8.1 fit gemacht:

Tadaaa: der Appmonitor ist die erste PHP 8.1 kompatible Opensource Applikation unseres Instituts :-)

Zudem wird die Plugin-Unterstützung vorangetrieben, es kam eine grafische Darstellung der Checks in einem ersten Wurf hinzu und die Möglichkeit, die Checks nach vorgegebenen Gruppen zu clustern. Die Notifikation eines Fehlers erfolgt nicht beim ersten Auftreten, sondern wird erst bei der 3. Wiederholung ausgelöst.

2021-12-16-appmonitor-appview.png

Ich bin gerade motiviert, weitere Updates einzubringen und nachzuliefern. Es gibt beispielsweise vorgefertigte Checks für einige PHP-Applikationen, wie Wordpress, Ilias LMS, Concrete5 und Matomo. Diese befinden sich in einem separaten Repository und werden in Kürze in das Repo integriert.

weiterführende Links:

  1. Github: Quellcode des IML Appmonitors
  2. Github: vorgefertigte Appmonitor-Checks für Drittanbieter Applikationen
  3. DOCs: os-docs.iml.unibe.ch
  4. git-repo.iml.unibe.ch - Opensource Projekte des IML

AhCrawler läuft mit PHP8

Montag, 28. Dezember, 2020

Der AhCrawler ist ein PHP Open Source Projekt, das für den Einbau einer Suche auf der eigenen Webseite enststand. Im Backend kann man den Suchindex wie auch die von Besuchern eingegebenen Suchbegriffe analysieren. Hinzu kommen Werkzeuge, wie Linkchecker, Http-Header-Analyse, SSL-Check und Annehmlichkeiten, wie der integrierte webbasierte Updater oder die Verwaltungsmöglichkeit mehrerer Webseiten.

2020-12-28-ahcrawler-v139-is-php8-compatiblepng.png

Nachdem PHP in Version 8 erschien, kam Anfang Dezember 2020 eine Version heraus, die offensichtliche Fehler in der WebGUI unter PHP8 bereinigte. Der Crawler zeigte hingegen bei Http Head Requests mit Curl “irgendwann” ein komisches Verhalten und brach mit einem “Segmentation Fault” ab.

Mit dem heutigen Release des AhCrawler ist aber auch das Geschichte. Ich bezeichne die Software nunmehr als PHP8 kompatibel! Tusch :-)

weiterführende Links:

  1. AhCrawler (de)
  2. DOCs: AhCrawler (en)

Flatpress - sichere Passwortfunktion statt MD5 Hash

Sonntag, 20. Dezember, 2020

Ich hatte es es ja genauso in mein meinen Webtools mit Login gern gemacht: neben dem Admin User wurde das Passwort als MD5 Hash in einer Config-Datei hinterlegt.

Die Hashfunktion MD5 ist nach IT Masstäben nicht mehr wirklich sicher - heisst: man kann mit einem zeitlich vertretbaren Aufwand aus dem Hash das (oder ein) Passwort ermitteln, dass auf den Hash matcht. Verzichtet man gar auf Salts, ist der Angreifer mit Rainbow Tables gar in Sekundenbruchteilen am Ziel. Das ist gar nicht gut. Auf MD5 sollte man heutzutage beim Hashing von Passwörtern - egal ob in einer Konfigurationsdatei oder Datenbank-Feld - komplett verzichten.

Ich will es keineswegs verdammen: als reine Hash Funktion zum Bilden von Prüfsummen von nicht-sensiblen Daten, wie Prüfsummen von Download-Dateien, ist es bedenkenlos einsetzbar.

Aber zurück zum Speichern von Passwörtern. PHP bietet seit einiger Zeit von Haus sichere Funktionen an, sichere Passwort-Hashes zu generieren [2] wie auch eine Check-Funktion [3]. Auf dieses Paar habe ich meine Tools umgestellt und kannte das Prozedere der Umstellung bereits.

Da ich hier als “mein” Blogtool Flatpress seit gefühlten Äonen selbst verwende, hab ich mich gern auch an jenem Tool drangesetzt, und dessen md5 Passwort-Hash durch eine sicherere Variante ersetzt - und eine Lösung für den Issue #59 [4] als Pull Request eingereicht.

Das gilt nicht nur für die neu angelegten Passwörter - auch die Migration ist berücksichtigt: bestehende mit md5 Hash gespeicherte Passwörter werden on the fly beim nächsten Login umgeschrieben.

Arvid, danke und merci für den Merge und Erwähnung auf Twitter [1] für die kommende Version 1.2!

I love OpenSource :-)

weiterführende Links:

  1. Twitter-Nachricht
  2. PHP: Funktion password_hash
  3. PHP: Funktion password_hash
  4. Github Flatpress: Issue #59
  5. Flatpress.org

Xampp: Port 3306 belegt - durch Firefox

Mittwoch, 2. Oktober, 2019

Schon komisch: ein Programm krallt sich einen Port. Ich dachte, das wäre die Domäne von Skype.

2019-10-02-xampp-port-3306-durch-firefox-belegt.png

Abhilfe:

  1. Firefox beenden
  2. Mysql im Xampp starten
  3. Firefox starten

preDispatcher - speed up my slow Concrete5 website

Dienstag, 20. August, 2019

Meine Concrete5 Webseite wurde langsamer und langsamer. Sie wird auf einem Shared Hosting betrieben (was ohnehin nicht die schnellste Option sein kann) - hier kann ich zudem keinen Varnish oder auch nur irgendeinen anderen Caching Dienst installieren und davorschalten, sondern muss mich mit .htaccess und Standard-PHP-Mitteln behelfen können.

Das Initialisieren eines Requests in Concrete5 (Bootstrapping) braucht scheinbar sehr lange. Selbst statische Inhalts-Seiten, die ein aktives Fullpage Cache haben, benötigen für die Verarbeitung am Server mehr als 200 ms. Hinzu kommen für einen kompletten Request dann noch Netzwerkzeiten für Namensauflösung (DNS), Anfrage zum Server senden … und das Ergebnis zum Browser zurücksenden, was der Browser dann rendert. Meine schnellsten Seiten aus dem CMS waren bei 300 ms. Andere brauchten 3 Sekunden und mehr. Concrete5 ist einfach langsam.

Ich habe einen Cache geschrieben, der Concrete5 vorgeschaltet ist und im Filesystem seine Caching-Daten ablegt. Kurz er hat minimalste Anforderungen und arbeitet mit einem Shared Hoster. Dieses “Vorschalten” umgeht die lange Initialisierungszeit von Concrete5 - dies macht die Seite schnell.

Vor einigen Tagen habe ich eine erste Version meines preDispatchers eingespielt. Erwartungsgemäss muss man ein paar Kinderkrankheiten ausmerzen. Aber erste Ergebnisse in der Webseiten-Statistik (Matomo) zeigen, dass es eine gute Entscheidung war: die mittleren Seiten-Generierungs-Zeiten sanken von über 2s auf unter 0.4s

2019-08-20-predispatcher-generation-time-in-matomo.png

Der PreDispatcher besitzt eine Debugging-Ausgabe, die die Arbeitsweise veranschaulicht und den Unterschied deutlich macht. Das ist ein ungecachter Aufruf einer Seite mit Fullpage Cache in C5 - also inkl. Bootstrapping + Auslieferung einer in C5 gecachten Seite:

2019-08-20-predispatcher-uncached-concrete5-request-of-fullpage-cached-page.png

Der PreDispatcher speichert den Request, der nicht im Cache ist (oder dessen Caching Zeit abgelaufen ist). Der nächste Request auf dieselbe Seite wird dann schnell. Richtig schnell:

2019-08-20-predispatcher-cached-request.png

Wie lange eine Seite aus einem Cache kommt? Man definiert einen Default für alle Seiten. Mit einer Liste von Regex für aufzurufende URLS kann man die Standard-Vorgabe übersteuern und einen neuen Wert zuweisen.

Zudem gibt es eine Erkennung, was nicht gecacht werden darf - oder wo ein Cache verworfen werden muss. Ich kann mich im C5 Backend einloggen - und der Cache jeder mit Login aufgerufenen Seite wird verworfen.

Ich bin wohl auf dem richtigen Weg. Aber ein wenig Feintuning braucht es noch. Bei Interesse, schaut auf Github … oder fragt mich an :-)

Der PreDispatcher ist Freie Software - unter GNU GPL 3!

weiterführende Links:

  1. Github: pre-dispatcher for more speed
  2. Concrete5 webseite

PHP-Snippet - URL Parameter escapen

Sonntag, 23. Juni, 2019

Dieser Blogeintrag ist eine Snippet-Ablage.

Die PHP-Funktion mysql_real_escape() maskierte Sonderzeichen in Werten, bevor man sie für Datenbankabfragen verwenden sollte. Die Funktion arbeitet nur dann, wenn Mysql vorab initialisiert wurde.

/**
* mysql_real_escape for an array of options
* @param array $aParams
* @return array
 */
function escapeAllParams($aParams) {
    foreach (array_keys($aParams) as $sKey) {
        $aParams[$sKey] = escapeParam($aParams[$sKey]);
    }
    return $aParams;
}

/**
* replacement for mysql_real_escape.
* @param string $s
* @return string
*/
function escapeParam($s) {
    $s = str_replace(array('\\', "\0", "\n", "\r", "'", '"', "\x1a"), array('\\\\', '\\0', '\\n', '\\r', "\\'", '\\"', '\\Z'), $s);
    return $s;
}

Pimped Apache Status: über 500 Downloads im März

Freitag, 24. Mai, 2019

Ich bin leider erst soeben darüber gestolpert: diesen März gab es auf Sourceforge einen absoluten Peak von 565 Downloads im Monat.

2019-05-25-downloadstats-pimped-apache-status.png

Warum habe ich das nicht gesehen?

In die tageweise Statistik reingezoomt … davon waren 500 an einem Tag (19.3.) - ich glaube, da hat sich wer einen Scherz erlaubt und wget bemüht - oder gar öfter F5 im Browser gedrückt.

So schnell kann eine kleine Euphorieblase wieder platzen.

weiterführende Links:

  1. Axels Webseite - Docs Pimped Apache Status Get started - hier ist das Youtube Video
  2. Github: Pimped Apache Status
  3. Sourceforge: Pimped Apache Status

PHP: komisch grosse Zeiten in Curl

Mittwoch, 8. Mai, 2019

Ich hatte wirklich seltsame Antwortzeiten mit der Curl-Bibliothek in PHP in meiner eigenen Monitoring-Anwendung.
Bei Verwendung von curl_getinfo($curl) ist der Wert von “total_time” ein Wert in Sekunden. Eigentlich. Bei einer Reaktionszeit von 16ms sollte es 0,016 sein, ich erhielt aber 16000.

Das Problem ist, dass sich die Werte der Curl-Funktion bei Verwendung von PHP mit mod_php korrekt verhalten - nur im FCGI Modus gibt es Zahlenwerte, die Faktor 1 Mio. zu gross sind.

Bei einer Antwort-Zeit von 16 ms sollte der Wert im Feld total_time 0.016 sein - unter FCGI kommt aber 16000 zurück.

2019-05-08-curl-time-values.png

Nach einer kurzen Suche, fand ich einen bestehenden Bugreport, wo ich meine Daten ergänzte. Mal schauen, ob da wohl was geht …

weiterführende Links:

  1. bugs.php.net- 76438: wrong curl_getinfo time values
  2. php.net: Funktion curl_getinfo()
  3. Github: IML AppMonitor