Ich arbeite seit einiger Zeit hobbymäßig an einem größeren PHP-Projekt, und während die meisten Teile davon immer mehr Gestalt annehmen bzw. immer wieder mal ändern, ist ein Teil seit Beginn des Ganzen einfach nur ein Grundstück mit der Baustellenankündigung geblieben. Ok, das stimmt nicht, es gab immer wieder Gerüste, nur die sind eingestürzt oder waren zumindest windschief.
Die ganze Seite arbeitet mit einer einzelnen Indexdatei, die allen zentralen Aufgaben erledigt (Datenbankanbindung, Benutzerauthentifizierung, Grundgerüst der Seite mit Links u. Ä....) und dann je nach Seitenaufruf Content einbindet. Jetzt möchte ich es auch möglich machen, dass Benutzer eigene PHP-Seiten hochladen können, die dann als Content angezeigt werden. Mit einem einfachen include() ist das ja zu unsicher, weil das Skript dann ja im Kontext der Indexdatei ausgeführt wird und so z.b. die Datei mit den Datenbankpasswörtern auslesen kann. Frames möchte ich nicht verwenden, und iframes und objects im HTML passen ihre größe nicht dem Inhalt an.
Ich hab schon ein Javascript geschrieben, das den Content nachlädt, aber da über ein simples content.innerHTML=downloadedString eventuelle Javascript-Teile nicht ausgeführt wurden, musste ich den ganzen String zerlegen und Javascript-Teile über eval() oder wie auch immer es da genau hieß ausführen, und insgesamt bin ich mit der Lösung nicht wirklich glücklich.
Eine weitere Lösung war, vom Webserver aus mit fopen(http://[Adresse]) drauf zuzugreifen, um das ganze bereits berechnet zu bekommen und dann so mitzuschicken. Nur ist das auch nicht wirklich eine schöne Vorgehensweise.
Gestern hab ich dann noch folgendes probiert: Der Gedanke war, einen SSI-Includebefehl mit PHP zu generieren, damit der Apache nach Ausführung des Skripts nochmal drübergeht und den entsprechenden Teil ersetzt und nochmal an PHP schickt. Das tatsächliche Verhalten finde ich aber höchst seltsam:
Dieser Teil steht am Anfang des Skripts:
<?php
$time_scriptstart = microtime(true);
$test_script="A";
ob_start();
include("ssitest.php");
echo '<!';
echo '--';
echo '#in';
echo 'clude ';
echo 'file="ssitest.php" -';
echo '-> ';
Alles anzeigen
Das echo für den SSI-Includebefehl habe ich sicherheitshalber so aufgespalten, dass der Apache möglichst nicht gleich draufkommt, hier was ersetzen zu müssen. ssitest.php gibt einfach alle globalen Variablen ($GLOBALS) als "[name]=[value]<br/>" aus. Außerdem wichtig: der Output-Buffer wird gestartet.
(Fast) am Ende des Skripts steht nun:
In der Ausgabe steht nun von der über include() eingebundenen ssitest.php für $test_script eben "A". Interessanterweise ist der Wert für $test_script in der über SSI eingebundenen ssitest.php aber "B" (und nicht "C" oder gar nicht vorhanden, wie ich mir ursprünglich vorgestellt hätte). Ein Test auf $_SERVER['script_filename'] ergab bei beiden Varianten außerdem den Namen der indexdatei. Apache scheint also die SSI-Ersetzungen durchzuführen, sobald sie in der Ausgabe erscheinen. Das ist ja noch ok, mich wundert nur, dass dieser Code anscheinend _sofort_ an PHP weitergegeben, im aktuellen Kontext ausgeführt und anschließend in die richtige Stelle eingefügt wird.
Weiters hab ich es schon öfters versucht, über passthru(), exec() und was es da sonst noch so gibt, PHP vom Skript aus auf Kommandozeilenebene und so die betreffende Datei auszuführen, was ich aber auch noch nie richtig zusammengebracht habe. Irgendwas scheint da falsch eingestellt zu sein und ich komm nicht drauf.
Gestern hätte ich dann noch gefunden, was ich eigentlich bräuchte: die runkit-Erweiterung mit einer Sandbox-Funktion. Diese führt ein PHP-Skript in einer Sandbox aus - man kann ihr beliebige Variablen übergeben, ein eigenes open_basedir zuweisen und andere PHP-Einstellungen ändern, was das Ganze ziemlich sicher machen dürfte. Leider ist das wieder keine offizielle Erweiterung, sondern muss eigens mit PHP kompiliert werden (außerdem ist die aktuellste Version 0.9 von 2006). Als Windows-Binaries-Verwöhnter Schnösel hab ich damit bisher nur schlechte Erfahrungen gemacht - so auch diesmal: das Setup für das geforderte Windows Server 2008 SDK ließ sich nicht starten, weil ihm eine XML-Datei fehlt, und die Links zu den beiden anderen Bibliotheken, auf die die PHP.net-Howto-Seite verwies, waren gleich broken. Jetzt gibts zusätzlich zur documentation auch noch eine wiki, nur dort steht unter "Windows Build, step by step" nur wieder, was man braucht. Der Rest ist "... to be written". Und das bei PHP...
Fällt irgendjemandem hier sonst noch etwas ein, wie man mein "Sandkisten-Problem" lösen könnte?
Und für die, die sich auskennen, wär für mich auch eine Erklärung des SSI-Verhaltens interessant.