Src2Textarea
Src2Textarea-Tutorial von Daniel Schwamm (09.03.2009)
Inhalt
Dieses Tutorial beschreibt den Werdegang eines Projektes,
welches - ganz ehrenrührig - Wahrheit verkünden will. Nämlich
den Sourcecode einer Webseite so anzuzeigen, wie er ist.
Aufgrund ungünstiger Umstände in Form von HTML-Syntax,
auf die man keinen Einfluss hat, muss dazu aber die Wahrheit
gefälscht werden.
Da nun aber gefälschte Wahrheit keine Wahrheit mehr ist,
muss die Fälschung ihrerseits gefälscht werden, jetzt
aber wieder zur Wahrheit hin.
Die Fälschung der Fälschung bewirkt aber wiederum eine
Fälschung derjenigen Wahrheit, die die Fälschung der
Fälschung vornimmt, ist also ihrerseits nicht Wahrheit,
womit das Ganze einmal mehr zwangsläufig zur Fälschung
wird ...
Muss man also alle Hoffnung auf Wahrheit fahren lassen,
so wie Unwahrheit zur Wiedergabe verwendet werden muss?
Nein, wie die folgende Dokumentation hoffentlich zu belegen weiss ...
Die meisten meiner Talente sind ... nun ja, eher schwach ausgeprägt.
Allerdings beherrsche ich ein Gebiet sicherlich besser als der
bundesdeutsche Durchschnitt: Programmieren!
Daher dachte ich, es wäre eine nette Idee, den Leuten, die sich auf meine
Homepage verirren, gleich einen Ausschnitt von dem aufzudrängen, womit ich
mich am liebsten beschäftige, nämlich den oftmals kryptisch anmutenden
Sourcecode von Computer-Programmen.
Und ein Beispiel, welches sich dazu als eine Art intellektueller Gag
anbot, war der PHP-, HTML- und JavaScript-Source eben derjenigen Seite,
auf der sich der Betrachter gerade selbst befand.
Die Startseite meiner Homepage sah daher von Ende 2007 bis Anfang 2009
in etwa so aus:
Die alte Homepage: In der Textarea wird der Sourcecode der eigenen Seite angezeigt
Doch die "Sourcecode-Selbstanzeige" erwies sich als erstaunlich
komplexes Problem, wie im Folgenden geschildert werden soll.
Zunächst muss man den PHP-Sourcecode der Webseite in irgendeiner
Form von der Platte einladen. Dazu bietet sich der
PHP-Befehl "file_get_contents()" an:
00001
00002
00003
00004
<?PHP
$fn=__FILE__;
$src=file_get_contents($fn);
?>
Es wird hier einfach der Dateiname "$fn" übergeben und man erhält
einen String "$src" zurück, der den kompletten Dateiinhalt
speichert. Die Variable "__FILE__" ist in PHP eingebaut und
enthält stets den Dateipfad des aufgerufenen Scripts.
Man könnte nun auf den naheliegenden Gedanken kommen, den String
"$src" unmittelbar per "echo"-Kommando auszugeben, eingerahmt
in die üblichen HTML-Tags einer gültigen Webseite, also z.B.
auf diese Weise:
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.01 Transitional//EN'
'http://www.w3.org/TR/html4/loose.dtd'>
<html>
<head>
<META NAME='ROBOTS' CONTENT='INDEX, FOLLOW, ARCHIVE'>
<META HTTP-EQUIV='Content-Type' CONTENT='text/html;
charset=windows-1252'>
<meta name='author' content='Daniel Schwamm'>
<meta name='Description' content='Scr2Textarea - Tutorial 1:
Quellcode der eigenen PHP-Seite mit "echo" ausgeben'>
<meta name='Keywords' content='software, tutorial, php, src2textarea, echo'>
<link rel='canonical' href='http://www.henrys.de/daniel/index.php?
cmd=software_php_src2textarea_script-echo-src.php'>
<title>[DAN] • Software - PHP - Scr2Textarea - Tutorial 1</title>
</head>
<?PHP
$fn=__FILE__;
$src=file_get_contents($fn);
$fn=substr($fn,strpos($fn,"script"),strlen($fn));
echo "
<body>
<h1>Scr2Textarea - Tutorial 1</h1>
<h2>Quellcode der eigenen PHP-Seite mit 'echo' ausgeben</h2>
<b>Aktuelle Datei:</b> $fn
<hr>
$src
<hr>
</body>
</html>
";
?>
Doch seht selbst, was dabei herauskommt:
"Script-Echo-Src.php", der erste Versuch
Verflixt! Man sieht tatsächlich genau das, was wir eigentlich
anzeigen lassen wollten, gerade nicht! Der Webseiten-Source
ist ausgeblendet. Holt man sich jedoch mit dem (IE-)Browser
(über "Quelltext anzeigen") den Sourcecode (in Notepad), erkennt man,
dass der oben gezeigte PHP-Script-Text durchaus vorhanden ist.
Allerdings ist er in das PHP-Start-Tag ("<?PHP") und
das PHP-End-Tag ("?>") eingekapselt. Und da der Browser
mit diesen Tags nichts anfangen kann, ignoriert er
definitionsgemäss einfach alles, was sich dazwischen befindet.
Okay, in Versuch I haben wir gelernt, dass direkt ausgegebener
PHP-Source auf der Webseite nicht erscheint, weil der Browser
die PHP-Start- und -End-Tags als unbekannte Tags "interpretiert"
und daher nicht weiter verarbeitet.
Um dies zu umgehen, kann die in HTML eingebaute "Textarea"
zum Einsatz kommen. Schriftsätze, die darin eingebettet sind, werden
nämlich normalerweise 1:1 auf dem Bildschirm wiedergegeben,
ohne zuvor vom HTML-Parser "übersetzt" zu werden.
Ein passendes Programm dazu ist schnell getippt:
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.01 Transitional//EN'
'http://www.w3.org/TR/html4/loose.dtd'>
<html>
<head>
<META NAME='ROBOTS' CONTENT='INDEX, FOLLOW, ARCHIVE'>
<META HTTP-EQUIV='Content-Type' CONTENT='text/html;
charset=windows-1252'>
<meta name='author' content='Daniel Schwamm'>
<meta name='Description' content='Scr2Textarea - Tutorial 2:
Quellcode der eigenen PHP-Seite in "Textarea" ausgeben'>
<meta name='Keywords' content='software, tutorial, php,
src2textarea, textarea'>
<link rel='canonical' href='http://www.henrys.de/daniel/index.php?
cmd=software_php_src2textarea_script-src-in-textarea.php'>
<title>[DAN] • Software - PHP - Scr2Textarea - Tutorial 2</title>
</head>
<body>
<h1>Scr2Textarea - Tutorial 2</h1>
<h2>Quellcode der eigenen PHP-Seite in 'Textarea' ausgeben</h2>
<?PHP
$fn=__FILE__;
$src=file_get_contents($fn);
$fn=substr($fn,strpos($fn,"script"),strlen($fn));
echo "<b>Aktuelle Datei:</b> $fn<br><br>";
echo "<textarea cols='80' rows='20' wrap='off'>";
echo $src;
echo "</textarea>";
?>
</body>
</html>
Doch seht selbst, was dabei herauskommt:
"Script-Src-in-Textarea.php", der zweite Versuch
Tja, das haut sicher besser hin als Versuch I. Man sieht tatsächlich fast
den gesamten Sourcecode in der Textarea, allerdings fehlt der Schluss.
Genauer: Direkt vor dem schliessenden Tag "</textare>"
endet die Ausgabe - ab hier kommt der HTML-Parser offenbar durcheinander.
Also, was - zum Teufel - geht da schief?
Zur
Fehlersuche muss sich gewissermassen in den HTML-Parser
hineindenken. Der erkennt am Anfang "Aha, eben beginnt eine
Textarea" und weiss "Ich muss nun alles ausgeben, bis ich das
schliessende Tag '</textarea>' entdecke". Nun ist aber das
gesuchte schliessende Tag wiederum Teil des auszugebenden Sourcecodes,
muss also eigentlich mit ausgegeben werden, statt ein Zeichen
davor den Output zu beenden, wie es die Syntax des HTML-Parsers aber
zwingend vorschreibt.
Ein geradezu philosophisches Dilemma. Erinnert ein wenig an den Kerl,
der auf einem Baum hockt und ausgerechnet an dem Ast herumsägt, auf
dem er selbst sitzt ...
In Versuch II haben wir gesehen, dass der HTML-Parser aufgrund
der Ausgabe des schliessenden Textarea-Tags die Ausgabe früher beendet,
als er eigentlich sollte.
Um dieses zu umgehen, verhindern wir in Versuch III - raffiniert, wie wir sind -,
dass das besagte schliessende Textarea-Tag im Sourcecode auftaucht.
Wir nutzen dazu die PHP-Funktion "str_replace()", mit deren Hilfe
man bestimmte Textteile in einem String durch andere Inhalte ersetzen kann.
Indem wir das hier machen ...
00001
00002
00003
00004
<?PHP
$src=file_get_contents($fn);
$src=str_replace("textarea","text_area",$src);
?>
... überschreiben wir das Auftauchen von "textarea" in "$src"
durch "text_area". Findet der HTML-Parser nämlich
dieses Dummy-Tag innerhalb einer Textarea, wird es wie normaler Text
ausgegeben.
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.01 Transitional//EN'
'http://www.w3.org/TR/html4/loose.dtd'>
<html>
<head>
<META NAME='ROBOTS' CONTENT='INDEX, FOLLOW, ARCHIVE'>
<META HTTP-EQUIV='Content-Type' CONTENT='text/html;
charset=windows-1252'>
<meta name='author' content='Daniel Schwamm'>
<meta name='Description' content='Scr2Textarea - Tutorial 3:
Quellcode der eigenen PHP-Seite in "Textarea" ausgeben ohne
"Textarea"-Tags'>
<meta name='Keywords' content='software, tutorial, php,
src2textarea, echo'>
<link rel='canonical' href='http://www.henrys.de/daniel/index.php?
cmd=software_php_src2textarea_script-src-in-textarea-ohne-tag.php'>
<title>[DAN] • Software - PHP - Scr2Textarea - Tutorial 3</title>
</head>
<body>
<h1>Scr2Textarea - Tutorial 3</h1>
<h2>Quellcode der eigenen PHP-Seite in 'Textarea'
ausgeben ohne 'Textarea'-Tags</h2>
Das "textarea"-Tag wird durch das ungültige "text_area"-Tag ersetzt!
<br><br>
<?PHP
$fn=__FILE__;
$src=file_get_contents($fn);
$fn=substr($fn,strpos($fn,"script"),strlen($fn));
echo "<b>Aktuelle Datei:</b> $fn<br><br>";
$src=str_replace("textarea","text_area",$src);
echo "<textarea cols='80' rows='25' wrap='off'>";
echo $src;
echo "</textarea>";
?>
</body>
</html>
Doch seht selbst, was dabei herauskommt:
"Script-Src-in-Textarea-ohne-Tag.php", der dritte Versuch
Ha! Das klappt. Der Source ist jetzt komplett in der Textarea enthalten.
Allerdings mit einem dickem Schönheitsfehler: Die Anzeige lügt
nämlich - innerhalb der Textarea steht nun etwas von irgendwelchen
"text_area"-Tags, die im echten Sourcecode der Seite nicht vorhanden
sind. Würde jetzt jemand den Source aus der Textarea kopieren, um ihn für
eigene Zwecke zu verwenden, könnte er in dieser "gefälschten" Form
schlicht nicht funktionieren.
Versuch III war weitgehend erfolgreich darin, den eigenen Sourcecode
in einer Textarea anzuzeigen. Für die korrekte Ausgabe war es aber
nötig, das "textarea"-Tag in "text_area" zu fälschen,
sodass in Wirklichkeit doch nicht der originale Sourcecode wiedergegeben
wird.
Es stellt sich also die Frage: Wie machen wir aus "text_area"
nach der Ausgabe in der Textarea wieder "textarea"?
Wie fälschen wir quasi die Fälschung durch eine erneute "Rückfälschung"?
Die Antwort: Per JavaScript (JS).
Schauen wir uns dazu folgenden Source an:
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.01 Transitional//EN'
'http://www.w3.org/TR/html4/loose.dtd'>
<html>
<head>
<META NAME='ROBOTS' CONTENT='INDEX, FOLLOW, ARCHIVE'>
<META HTTP-EQUIV='Content-Type' CONTENT='text/html;
charset=windows-1252'>
<meta name='author' content='Daniel Schwamm'>
<meta name='Description' content='Scr2Textarea - Tutorial 4:
Quellcode der eigenen PHP-Seite in "Textarea" ausgeben
ohne "Textarea"-Tags und mit JS-Korrektur'>
<meta name='Keywords' content='software, tutorial, php, src2textarea,
echo, tag-filter, js-korrektur'>
<link rel='canonical' href='http://www.henrys.de/daniel/index.php?
cmd=software_php_src2textarea_script-src-in-textarea-ohne-tag-js-korrektur.php'>
<title>[DAN] • Software - PHP - Scr2Textarea - Tutorial 4</title>
</head>
<body>
<h1>Scr2Textarea - Tutorial 4</h1>
<h2>Quellcode der eigenen PHP-Seite in 'Textarea'
ausgeben ohne 'Textarea'-Tags und mit JS-Korrektur</h2>
Per PHP "textarea" zu "text_area" ändern - und per Javascript wieder zurück
<br><br>
<?PHP
$fn=__FILE__;
$src=file_get_contents($fn);
$fn=substr($fn,strpos($fn,"script"),strlen($fn));
echo "<b>Aktuelle Datei:</b> $fn<br><br>";
$src=str_replace("textarea","text_area",$src);
echo "<form name='frm'>";
echo "<textarea name='ta'cols='80' rows='25' wrap='off'>";
echo $src;
echo "</textarea>";
echo "</form>";
?>
<script language='javascript' type='text/javascript'>
alert("Vor der JS-Manipulation");
var ta_ar=document.frm.ta.value.split("\n"),s="";
for(r=0;r<ta_ar.length;r++){
ss=ta_ar[r];
ss=ss.replace("ext_area","extarea");
s=s+ss+'\n';
};
document.frm.ta.value=s;
</script>
</body>
</html>
Zunächst kapseln wir die Textarea in eine HTML-Form namens "frm".
Die Textarea erhält den Namen "ta". Diese Namensgebung ist nötig,
damit wir auf die HTML-Objekte per JavaScript zugreifen können.
Nach der Ausgabe der Textarea beginnt der JavaScript-Teil.
Über den "split"-Befehl transferieren wir den Inhalt der
Textarea "ta" in das Zeilen-Array "ta_ar".
Danach
durchlaufen wir das Zeilen-Array und ändern über das
""replace"-Kommando in jeder einzelnen Zeile das erste
Auftauchen von "ext_area" in "extarea". Wohlgemerkt,
wir ersetzen nicht "text_area" in "textarea", denn diese Zeichenfolge
wäre durch den zuvor angewendeten PHP-Befehl "str_replace" ihrerseits
manipuliert worden. Mit der Folge, dass auch der JS-Code fehlerhaft
wiedergegeben würde, da dort ja sonst stünde, man würde "textarea"
durch "text_area" ersetzen, also genau anders herum vorgehen ...
Brrr! Da verrenkt man sich echt das Hirn, wenn man zu lange
darüber nachdenkt.
Leider haut unser Source aber auch so immer noch nicht ganz hin.
Denn wir haben zwar erfolgreich verhindert, das PHP den JS-Source
ändert, nicht jedoch, das JS sich selbst, also den eigenen JS-Code
verfälscht!
Doch seht selbst, was dabei herauskommt:
"Script-Src-in-Textarea-ohne-Tag-JS-Korrektur.php", der vierte Versuch
Wie man sieht, steht im JavaScript-Teil folgende Zeile:
00001
ss=ss.replace('extarea','extarea');
Korrekt ist aber:
00001
ss=ss.replace('ext_area','extarea');
Das dreckige JavaScript hat sich bei der Fälschung selbst
gefälscht. Und zwar derart unglücklich, dass Fälschung und
Original identisch sind, man nun also gar nicht mehr unterschieden
kann, was was ist. Teufel aber auch, da sind wir doch glatt in eine
Deadlock-Falle getappt.
Unser Versuch IV, den eigenen Sourcecode in einer Textarea anzuzeigen,
hat funktioniert. zumindest was den PHP-Teil betrifft. Dies haben
wir durch nachträgliche Manipulation per JavaScript erreicht. Allerdings
hört die JS-Fälschung nicht beim PHP-Source auf, sondern vergreift sich
frecherweise auch am JS-Source, wodurch dieser nun seinerseits vom Original
abweicht.
Im Prinzip ist damit schon angedeutet, wie das Dilemma aufgelöst
werden kann: Der JS-Manipulations-Code darf überall wirken, nur
halt nicht im JS-Script-Sourcecode selbst.
Der einfachste Weg, der mir einfiel, um das zu realisieren, war,
mit Zeilennummern zu arbeiten. Da der JS-Code ganz am Schluss
steht, haben wir es auch relativ leicht. Denn es muss dadurch nur
dafür gesorgt werden, dass die JS-Manipulation ab der ersten JS-Zeile
ausser Kraft gesetzt wird. Und diese Zeilennummer ist bei gegebenem Code
eine Konstante (hier "52").
Schauen wir uns also den fertigen Source an:
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.01 Transitional//EN'
'http://www.w3.org/TR/html4/loose.dtd'>
<html>
<head>
<META NAME='ROBOTS' CONTENT='INDEX, FOLLOW, ARCHIVE'>
<META HTTP-EQUIV='Content-Type' CONTENT='text/html;
charset=windows-1252'>
<meta name='author' content='Daniel Schwamm'>
<meta name='Description' content='Scr2Textarea - Tutorial 5:
Quellcode der eigenen PHP-Seite in "Textarea" ausgeben
ohne "Textarea"-Tags und mit JS-Korrektur bis zu fixer Zeilennummer'>
<meta name='Keywords' content='software, tutorial, php, src2textarea,
echo, tag-filter, js-korrektur, zeilennummer'>
<link rel='canonical' href='http://www.henrys.de/daniel/index.php?
cmd=software_php_src2textarea_script.php'>
<title>[DAN] • Software - PHP - Scr2Textarea - Tutorial 5</title>
</head>
<?PHP
$fn=__FILE__;
$src=file_get_contents($fn);
$src=str_replace("textarea","text_area",$src);
echo "
<body>
<center>
<h1>Scr2Textarea - Tutorial 5</h1>
<h2>Quellcode der eigenen PHP-Seite in 'Textarea'
ausgeben ohne 'Textarea'-Tags und mit JS-Korrektur
bis zu fixer Zeilennummer</h2>
<hr>
<h1>Homepage von Daniel Schwamm</h1>
<form name='frm'>
<textarea name='ta' cols='80' rows='26' wrap='off'>
$src
</textarea>
</form>
<h2>Heimat des Dilettantismus</h2>
Zugriffe seit 11.12.98<br>
<img src='http://www.henrys.de/cgi-bin/bmc.exe?bmcdaniel.txt'
width='39' height='19' alt='Counter'>
</center>
";
?>
<script language='javascript' type='text/javascript'>
var ta_ar=document.frm.ta.value.split("\n"),s="";
for(r=0;r<ta_ar.length;r++){
rs='0'+r; while(rs.length<3)rs='0'+rs;
ss=ta_ar[r];if(r<52)ss=ss.replace("ext_area","extarea");
s=s+rs+'| '+ss+'\n';
};
document.frm.ta.value=s;
</script>
</body>
</html>
Puh! Schwere Geburt, was? Für eine vermeintlich so simple Sache.
Aber es funzt. Und alleine das zählt letztlich!
Doch seht selbst, was dabei herauskommt:
"Script.php", der fünfte Versuch bringt endlich den Erfolg
"Src2Textarea" beweist uns also, dass Unwahrheit Unwahrheit
produziert. Ist Wahrheit aber nicht direkt darstellbar,
muss auf Lug und Betrug zurückgegriffen werden. Doch wer
geschickt lügt, kann Fälschung durchaus wieder zur Wahrheit
erheben - wie wir gerade gesehen haben.
Quod erat demonstrandum :-)