[PHP] Variablen einer Datei verfügbar macen, bevor diese includiert wird

klausschreiber

Well-known member
ID: 162475
L
6 Mai 2006
247
8
Hallo,

ich bin grad am erstellen einer Seite, die folgende Linkstruktur haben soll: index.php?site=$seitenname

In der index.php ist das Design gespeichert und die Contentdatei wird dann per include eingefügt. Also die Codestruktur sieht in etwa so aus:
PHP:
<html>
<head><title>Herzlich Willkommen</title></head>
<body>
Header und Navigationsleiste
<?php
$dateiname = "content/" . $_GET['site'] . ".php";
  if(file_exists($dateiname)) {
  include ($dateiname);
  }
  else {
  include ("includes/fehler.php");
  }
?>
Footer der Seite
</body>
</html>
Jetzt das Problem: Variablen, die ich in der Datei mit dem Content, definiere, stehen in der index.php erst zur Verfügung, wenn ich die entsprechende Datei includiert habe. Bei dem obigen würde folgendes also nicht funktionieren, da die Contentseite erst nach der Benutzung der Variable includiert wird:

Contentseite:
PHP:
<?php
$title="Herzlich Willkommen";
?>
Hier steht der Content. Ganz viel text. blabla bla
index.php
PHP:
<html>
<head><title><?php echo $title; ?></title></head>
<body>...

Gibt es eine Möglichkeit, bereits im Vorraus die Variablen der Contentseite verfügbar zu machen?
Oder bleibt mir nichts anderes übrig, als das nochmal zu ändern und eine header.php und footer.php zu erstellen, die dann beide in jede Contentseite eingefügt per include werden?

Gruß,
Klaus
 
du machst deinen includekram einfach am anfang der index.php unterdrückst die ausgabe, der eingelesenen datei.

darunter kommt dann der html kram mit title. da kannst dann die variable nutzen.

und darunter lässt dann die eingelesene datei ausgeben.

Der Titel kann auch nicht angezeigt werden, da der Parser ja schon weitergelaufen ist.
 
saubere Alternative: Template-System nutzen ;)

Btw: Whitelist benutzen :!:
 
Vielen Dank für eure Antworten.

du machst deinen includekram einfach am anfang der index.php unterdrückst die ausgabe, der eingelesenen datei.
An so etwas habe ich auch schon gedacht, nur habe ich leider nichts gefunden, wie man das machen kann. Bin noch relativer Anfänger in PHP. Kannst du mir bitte sagen, wie?

saubere Alternative: Template-System nutzen ;)
Btw: Whitelist benutzen :!:
Ich habe gelesen, dass hier viele auf Smarty schwören und habe mir auch mal den Wikipedia-Artikel über Smarty angeschaut. Ich verstehe aber nicht ganz, was ein Template-System für Vorteile hat, wenn man das Gewünschte auch mit 5-10 Zeilen Code erreichen kann. Und Smarty hat ja anscheinend auch Befehle, die man erstmal lernen muss.

Zur Whitelist:
Also um das includen von fremden Dateien zu verhindern, sind ja alle Dateien bei mir im Ordner content gespeichert und z.B. die Eingabe "boeseDatei" wird umgeändert in "content/boeseDatei.php". Dadurch sollte doch bereits verhindert sein, dass man Dateien außerhalb des Servers inlcudieren kann, da dafür ja "https://..." nötig wäre, was zu "content/https://....php" würde. Oder ist es trotzdem mit einem Trick noch möglich, andere Dateien einzuschleusen? Und includiert wird die Datei ja auch nur, wenn sie existiert. Da Schadcode nicht als Dateiname existiert, sollte dieser doch auch nicht includiert werden, oder übersehe ich etwas?
 
An so etwas habe ich auch schon gedacht, nur habe ich leider nichts gefunden, wie man das machen kann. Bin noch relativer Anfänger in PHP. Kannst du mir bitte sagen, wie?
Outputbuffering. Guckst du die Funktionen, ob_start(), ob_get_contents() und ob_end_clean() durch :)
Ich habe gelesen, dass hier viele auf Smarty schwören und habe mir auch mal den Wikipedia-Artikel über Smarty angeschaut. Ich verstehe aber nicht ganz, was ein Template-System für Vorteile hat, wenn man das Gewünschte auch mit 5-10 Zeilen Code erreichen kann. Und Smarty hat ja anscheinend auch Befehle, die man erstmal lernen muss.
Jaja, das leidige Daueraktiv-Thema...
Ich muss sagen, ich habe Smarty nie benutzt, sondern mir immer "schnell" ein eigenes Template-System geschrieben. Neulich hab ich Smarty einmal probiert, weil ich auch mal mitreden wollte. ...und ich werde es immer benutzen. Probiers einfach aus. Kostd ja nix :) :mrgreen:

Warum überhaupt ein Template-System ? Naja, hättest du eines benutzt, hättest du den Thread niemals erstellt, weil dein Problem nur daher kommt, dass du Ausgabe machst, ohne die Logik vorher vollständig durchlaufen zu haben.

Zu den Befehlen: Eine Stunde Manual lesen und du kannst loslegen. Das is nix Großes, was da drinsteckt, ob es viele Funktionen gibt.
Is wie PHP: Selbst mit keiner Ahnung bringst du schnell was auf die Beine. Im Laufe der Zeit perfektioniert sich das dann automatisch.
Dadurch sollte doch bereits verhindert sein, dass man Dateien außerhalb des Servers inlcudieren kann, [...]
Richtig. Ich hab da in Erinnerung, wie ich neulich jemanden ne PN geschrieben hab - derjenige hatte wohl denselben Code -, dass man sein Layout total kaputtmachen und wilde Fehlermeldungen triggern kann. Der Betroffene hat ganz schön dumm geguckt, obwohl ich doch nur sein Script mit https://www.example.com/?page=../index aufgerufen hab. Das eine Projekt war im Unterordner des Hauptprojektes. Resultat is dann klar: Im Kontext des Unterprojekts lade ich das Script des Hauptprojekts, was dann die wildesten Fehler bringt.

Wenn du keine Whitelist machen willst, prüf, ob "/" im Argument is. Wenn du natürlich selber in Unterverzeichnisse willst, solltest du den Pfad so checken, dass wirklich nur die Verzeichnis weiter unten erreichbar sind und das alles, was nach oben will, abgefangen wird.
 
danke für die schnelle Antwort. Ich werde mir die Befehle anschauen.

Smarty werde ich wohl bei Gelegenheit mal anschauen, auch wenn ich bisher nicht von überzeugt bin.:LOL:

Zur Whitelist. Autsch, ich habe zwar eigentlich schon darüber nachgedacht, obs wirklich sicher ist, aber auf die Idee bin ich nicht gekommen. Werde ich dann noch ändern.
 
[..]Wenn du keine Whitelist machen willst, prüf, ob "/" im Argument is. Wenn du natürlich selber in Unterverzeichnisse willst, solltest du den Pfad so checken, dass wirklich nur die Verzeichnis weiter unten erreichbar sind und das alles, was nach oben will, abgefangen wird.

Naja, ich würde auch noch auf den Null-Byte (\0) aufpassen ;)
Da wird ja sofort ans Ende gesprungen und man kann jeglichen Dateityp includen lassen.

Mein Tipp:
checke per RegEx ob der String '../' oder auch '..../' enthält, dass ist ganz einfach gemacht mit folgendem RegEx: ~.\.\./~
Wenn etwas gefunden wird, dieses Stück halt abschneiden (RegEx bisschen ändern und mit preg_replace() arbeiten) ;)
Somit kann man schon einmal nicht Verzeichnisse zurückgehen (..../ wird auch zu ../ !)
Dann noch auf \0 aufpassen, also z.B. \0 verbieten oder so.


(Danke an Johnson, ich hoffe, ich habe alles richtig wiedergegeben. Mit ihm habe ich gestern darüber geredet^^ Bin aber bei mir auf einer Whitelist umgestiegen, sicher ist sicher! Auch das oben genannte ist keine 100% sichere Alternative)
 
Wenns ganz einfach sein soll, würd ich einfach sowas in der Art machen:
PHP:
if(!preg_match('/[a-z0-9_]+/i', $_GET['site']))
  /* ... Default-Seite */
 
Danke für eure Antworten. Outputbuffering war die Lösung. Wundert mich nur, warum in SELFPHP nichts dazu steht?
Ich habe das jetzt vereinfacht dargestellt folgendermaßen gemacht, ich hoffe, das ist richtig so:
PHP:
<?php
ob_start();

$dateiname = "content/" . $_GET['site'] . ".php";
include ($dateiname);

$content=ob_get_contents();
ob_end_clean();
?>

<head>
    <title><?php echo $title; ?></title>
</head>
<body>

<?php 
echo $content;
?>

</body>
</html>
Ist das so richtig?


Nun zum Absichern der include-Anweisung. Diese sah ja vorher so aus:
PHP:
if(isset($_GET['site'])){
$dateiname = "content/" . $_GET['site'] . ".php";
  if(file_exists($dateiname)) {
  include ($dateiname);
  }
  else {
  include ("includes/fehler.php");
  }
}  
else {
include("content/index.php");
}
Es müsste doch in Ordnung sein, wenn ich das so ändere, oder?
PHP:
if(isset($_GET['site'])){
    if (!preg_match('/^[a-z0-9_]+$/i', $_GET['site'])) {
        echo "Nana, so nicht";
    }
    else {
        $dateiname = "content/" . $_GET['site'] . ".php";
        if(file_exists($dateiname)) {
            include ($dateiname);
        }
        else {
            include ("includes/fehler.php");
        }
    }
}
else {
    include("content/index.php");
}
Funktionieren tut es zumindest, sobald im String ein Sonderzeichen ist, kommt "Nana, so nicht".

edit:
Das ist noch etwas kürzer:
PHP:
if (!isset($_GET['site'])) {
    include ("content/index.php");
}
elseif (!preg_match('/^[a-z0-9_]+$/i', $_GET['site'])) {
    echo "Nana, so nicht";
}
else {
    $dateiname = "content/" . $_GET['site'] . ".php";
    if(file_exists($dateiname)) {
            include ($dateiname);
        }
        else {
            include ("includes/fehler.php");
        }
}
 
Zuletzt bearbeitet: