Konfigurationsdateien (.ini) mit PHP- und Bash-Skripten auslesen

Während der Programmierung einer Web-Anwendung basierend auf PHP und MySQL, kam ich letztens in die Verlegenheit eine Konfigurationsdatei auszulesen. Das kann doch nicht so schwer sein – dachte ich...

Fest verdrahtet

Meine Aufgabe bestand darin die Daten für den Zugriff auf eine MySQL-Datenbank so abzulegen, dass sie vor den Augen der Benutzer des Systems möglichst gut und für immer verborgen bleiben.

Die feste Verdrahtung der Verbindungsdaten in einer Include-Datei kam aus meiner Ansicht nicht in Frage.

Gute Gründe zu dieser Annahme gibt es allemal:

  • die Möglichkeit zur Steuerung von verschiedenen Paramtern aus einer zentralen Datei
  • der PHP-Interpreter des Apache-Webservers könnte eines Tages durch einen Fehler nicht ausgeführt werden, was den Apachen dazu verleiten dürfte, die Include-Datei beim Aufruf im Klartext auszugeben
  • die .inc-Dateien des Includes-Verzeichnis könnten durch einen Konfigurationsfehler in der httpd.conf plötzlich öffentlich als Text interpretiert werden
  • falsche Datei-Berechtigungen könnte dazu führen, dass die Konfigurationsdatei für den Anwender zum Download bereitsteht

Mein Lösungsansatz war eine einfache Text-Datei mit Key-/Value-Paaren ausserhalb des Webservers/Document-Root abzulegen. Damit könnte man mit einem Schlag allen genannten Punkten gebührend Rechnung tragen.

Selbst ist der Mann

Ich machte mir als erstes Gedanken darüber, wie das Format der Steuerungsdatei aussehen könnte. Müsste man Anführungszeichen für Variablennamen und deren Werte verwenden? Einfache oder doppelt? Wie füge ich Kommentare ein, müssen die Zeilenenden mit einem Semikolon abgeschlossen werden? Wie kann man die Konfiguration unterteilen und was schreibe ich in die Dokumentation hierzu?

Man muss sich so einige Fragen beantworten, bevor man beginnt einen eigenen Parser zu schreiben.

Eine Marktanalyse von Parsern in verschiedensten Programmiersprachen, hat mir letzten Endes gezeigt, dass sich viele Entwickler bereits mit dieser Thematik beschäftigt haben. Und so wundert es mich nicht, dass PHP mit einer tollen built-in Funktion daher kommt: parse_ini_file().

Ein kurzer Blick auf die Funktionsweise von parse_ini_file():

Datei: sample.ini

; Dies ist ein Beispiel für eine Konfigurationsdatei
; Kommentare beginnen wie in der php.ini mit ';'

[mysql]
hostname = 'localhost'
username = 'benutzer'
password = 'passwort'
database = 'datenbank'

[other]
upload_path = './uploads'

Datei: skript.php

<?php
    $ini_array = parse_ini_file("sample.ini", TRUE);
    print_r($ini_array);
?>

Ausgabe: skript.php

Array
(
    [mysql] => Array
        (
            [hostname] => localhost
            [username] => benutzer
            [password] => passwort
            [database] => datenbank
        )

    [other] => Array
        (
            [upload_path] => ./uploads
        )

)

Die Dateifunktion kennt zwei Parameter um 1. den Pfad anzugeben und 2. die Option zu setzen, dass die Unterteilung in Sektionen berücksichtigt werden soll.

Backup

Da die Implementierung in PHP so reibungslos geklappt hat, wollte ich nun auch das existierende Bash-Skript, welches verantwortlich für die Sicherung der MySQL-Datenbank ist, umbauen. Leider fehlt mir das Verständis, wie die Kommandozeilen-Version von PHP ihren generierten Output an die Shell zurück gibt.

Ich suchte also nach einer Shell-Alternative zu parse_ini_file() und wurde über diesen Blog-Post darauf aufmerksam gemacht, dass es bei den Debian Administratoren schon eine Lösung hierfür gibt.

Das ganze in einer Funktion verpackt und mit ein paar Quotes versehen, sieht dann so aus:

my_parse_ini_file() {
        INI_FILE="$1"
        INI_SECTION="$2"

        eval `sed -e 's/[[:space:]]*\=[[:space:]]*/=/g' \
            -e 's/;.*$//' \
            -e 's/[[:space:]]*$//' \
            -e 's/^[[:space:]]*//' \
            -e "s/^\(.*\)=\([^\"']*\)$/\1=\"\2\"/" \
           < "$INI_FILE" \
            | sed -n -e "/^\[$INI_SECTION\]/,/^\s*\[/{/^[^;].*\=.*/p;}"`
}

my_parse_ini_file 'sample.ini' 'mysql'

Blickschutz 2.0

Um auch auf Datei-Ebene auf Nummer sicher zu gehen und einen Blickschutz zu bieten, könnte ich mir vorstellen in Version 2.0 der Skripte die Verwendung der Base64-Funktionen einzubauen, was sowohl in PHP als auch Bash schnell gemacht ist.

Mission accomplished.

links

social