Logo: Proxomitron - Ein Universeller Webfilter

Metazeichen / Befehlsreferenz

Die Filtersprache ist der Schlüssel zum Verständnis der Arbeitsweise der Proxomitron-Filter. Sie erlaubt dir, komplexe Kombinationen von HTML-Tags zu verarbeiten, Teile davon in Variablen zu speichern und später in anderer Kombination wieder in den Quelltext einzufügen.

Vorneweg ist zu sagen, dass Proxomitron die ASCII-Buchstaben A bis Z case insensitive, also ohne Rücksicht auf Groß- und Kleinschreibung vergleicht. Im Vergleichsausdruck (Matching Expression) ist deshalb völlig egal, ob du den zu suchenden Text groß oder klein schreibst.

Einzige Ausnahme: Deutsche Umlaute und andere nationale Sonderzeichen, deren Existenz und zugeordneter Byte-Wert vom eingestellten System-Zeichensatz abhängen, werden nicht case insensitive behandelt.

Filter verarbeiten den Quelltext zeichenweise. Alle Zeichenfolgen, bei denen der Vergleichsausdruck wahr wird, werden "verbraucht". Sie werden schlicht gelöscht. Für dich bedeutet das, dass du alle Quelltextteile, die du später in der Ausgabe des Filters haben möchtest, in Variablen "retten" und im Ersetzungsausdruck wieder einfügen musst.

Übersicht der Metazeichen und ihrer Bedeutung

* Das Sternchen entspricht einer beliebigen Zeichenfolge. Beispiel: ord*er wird wahr bei Ordner und ordentlicher, aber nicht bei Ordnung. Das Sternchen sagt dem Programm also: "Suche weiter und brauche alle Zeichen auf, bis du auf die Zeichenfolge stößt, die hinter dem Sternchen steht."
? Das Fragezeichen ? ist ebenfalls ein Platzhalter und verhält sich wie das Sternchen *. Der Unterschied ist, dass das Fragezeichen nur einem einzelnen Zeichen entspricht. le?ren würde also sowohl bei lehren als auch bei leeren wahr werden. Nicht jedoch bei leckeren.
[abc...] Eckige Klammern entsprechen jedem einzelnen in ihnen aufgeführten Zeichen. Es können auch Von-Bis-Angaben gemacht werden: [a-z] entspricht einem Zeichen von A bis Z. [0-9] entspricht einer Ziffer von 0 bis 9. Auch das Gegenteil ist möglich: [^a-z] entspricht einem Zeichen, das nicht im Alphabet zwischen A und Z liegt. [^a-z0-9] entspricht einem Zeichen, dass weder ein Buchstabe von A bis Z, noch eine Ziffer ist.
[#n:n]
oder
[#n-n]
Die spezielle Nummernentsprechung. Dieser Ausdruck steht für einen numerischen Wert oder einen Wertebereich. Die Zahlen werden hierbei nicht als einzelne Ziffern betrachtet, sondern als Integer-Wert. Führende Nullen und die Anführungszeichen, die einen numerischen Wert in HTML oft umschließen, werden hier automatisch berücksichtigt. [#100] steht für die Zahl 100. [#50:100] steht für einen Wertebereich von 50 bis 100. [#50:*] steht für eine Zahl ≥ 50. Wenn du einen Wert ≤ 50 suchst, kannst du [#0:50] schreiben. Auch negative Werte sind möglich: [#-10:50] steht für einen Wert zwischen -10 und 50.
[%n-%n] Byte-Werte in Hexadezimal-Schreibweise. Mit dieser Notation können beliebige Bytes mit einem bestimmten Wert oder aus einem bestimmten Wertebereiche angegeben werden, auch wenn diese nicht als Symbole darstellbar bzw. auf der Tastatur vorhanden sind. Technisch gesehen, ist ja jedes Zeichen im Quelltext einer Webseite einfach nur ein Byte mit einem bestimmten Wert. Der Ausdruck [%4E] entspricht genau einem Byte mit dem Wert "4E". Im ASCII-Zeichensatz ist das der Buchstabe N. Der Ausdruck [%41-%5A] entspricht genau einem Byte mit einem Wert aus dem Bereich "41" bis "5A". Im ASCII-Zeichensatz sind das die Buchstaben A bis Z. Mehrere Wertebereiche können durch einen Ausdruck wie [%00-%08%0b-%0c%0e-%1f] erfasst werden.
" "

Ein Leerzeichen ist immer wahr. Es verbraucht sämtliche Leerzeichen, Tabulatorzeichen, Zeilenumbrüche und andere "white space"-Zeichen, die es findet. Wenn keine Leerzeichen da sind, ist der Ausdruck trotzdem wahr. Man kann Leerzeichen im Vergleichsausdruck also überall setzen, wo Leerzeichen, Tabs, Zeilenumbrüche usw. vorkommen könnten. Beispiel: <br > wird wahr bei <br > und <br  >, aber auch bei <br>.

Es ist nicht sinnvoll, Leerzeichen in Filtern aus rein optischen Gründen zu benutzen. Es gibt genügend Stellen in Quelltexten, an denen Leerzeichen nicht einfach verschwinden dürfen.

\s Backslash-s verbraucht, wie das Leerzeichen, unbegrenzt viele Leerzeichen und Tabs. Der Unterschied ist, dass es mindestens ein Leerzeichen bzw. Tabulatorzeichen finden muss, damit der Ausdruck wahr wird. Beispiel: <br\s> wird wahr bei <br > und <br  >, aber nicht bei <br>.
\w Die Wortentsprechung steht für eine zusammenhängende Zeichenkette ohne Leerzeichen. \w eignet sich deshalb gut zum Erfassen kompletter URLs. Der erfasste Bereich endet, sobald der Vergleich auf ein Leerzeichen, ein Tabulatorzeichen, einen Zeilenumbruch oder auf ein > stößt, was ja meist das Ende eines Tags signalisiert.
\t entspricht genau einem Tabulatorzeichen
\r entspricht genau einem Wagenrücklauf-Zeichen (engl. carriage return character)
\n entspricht genau einem Neue-Zeile-Zeichen (engl. newline character)
\0-9

Backslash+Ziffer: Bereich erfassen und in Variable speichern. Das ist einer der wichtigsten Proxomitron-Befehle. Er verbraucht Text genau so wie das Sternchen, kopiert ihn aber vorher in die gewünschte Variable, sodass er im Ersetzungsausdruck eingefügt werden kann. Variablen werden fast überall gebraucht. Meistens, um vom Vergleichsausdruck erfasste Quelltext-Bereiche in den Ersetzungsausdruck zu übernehmen.

Beispiel: Um den Hintergrund im BODY-Tag zu ändern, kann man folgendes schreiben:

Filter/Ausdruck
Vergleichsausdruck: <body \1 background="*" \2>
Ersetzungsausdruck: <body \1 background="meinbackground.gif" \2>

Alles was vor und hinter der background-Angabe steht, wird unverändert in die Ausgabe übernommen.

Man kann auch Text in Variablen schreiben lassen, der von einem Ausdruck verbraucht wird. Dazu schreibt man den Ausdruck in runde Klammern und setzt direkt dahinter die Variable. Z.B.: (abc*xyz)\1 Dieser Ausdruck sucht nach allem was mit abc beginnt und mit xyz endet und kopiert es in die Variable \1.

Man kann obiges Beispiel deshalb also auch so schreiben:

Filter/Ausdruck
Vergleichsausdruck: (<body*background=")\1*("*>)\2
Ersetzungsausdruck: \1meinbackground.gif\2
\# \# wird genau wie \0 bis \9 eingesetzt, funktioniert aber etwas anders. \# ist der Befehl für den Zugriff auf den Stapelspeicher. Der Stapelspeicher ist ein Stapel (engl. stack) aus 100 Speicherplätzen, die jeweils, wie eine Variable, beliebigen Text aufnehmen können. Man schreibt sowohl im Vergleichsausdruck als auch im Ersetzungsausdruck \# ... \# ... \# usw.. Die im Stapelspeicher abgelegten Zeichenfolgen werden beim Einfügen in der Reihenfolge eingefügt, in der sie im Stapel abgelegt wurden ("FIFO-Stack"). Die Stapelfunktion eignet sich also nur zum Übernehmen von Text und nicht zum Umsortieren.
| Der vertikale Strich steht für ein logisches "ODER". cd|dvd wird wahr sowohl bei CD, als auch bei DVD, aber nicht bei MOD.
&

Das & steht für ein logisches "UND". *peter&*müller wird wahr, sowohl bei Peter Müller, als auch bei Müller Peter, aber nicht bei Peter Peter.

Der Ausdruck sagt Proxomitron:
Suche nach "peter". Wenn du das gefunden hast, springe zum Anfang zurück und suche dann nach "müller". Wenn du das auch gefunden hast, betrachte den Gesamtausdruck als wahr.

Die Sternchen vor den beiden Teilausdrücken haben die Aufgabe, die Zeichen aufzunehmen, die zwischen der Startposition und dem gesuchten Wort liegen. Das ist wichtig, weil die beiden Teilausdrücke (hier: "peter" und "müller") ja auf keinen Fall gleichzeitig an der selben Position im Quelltext stehen können. Es muss also immer ein Metazeichen vorhanden sein, das die unterschiedliche Anzahl Zeichen bis zum gesuchten Wort aufnimmt.

Anstelle des Sternchens eignen sich auch andere Metazeichen, die einen Bereich aufspannen können. Ob z.B. \w sinnvoller ist, hängt ganz vom jeweiligen Filter ab.

Die UND-Verknüpfung ist nützlich, wenn man die Reihenfolge der zu suchenden Zeichenfolgen nicht kennt. Das ist z.B. bei Attributen in Tags der Fall.

<img src="bild" height=60 width=200>

kann man auch so schreiben:

<img width=200 height=60 src="bild">

Beides wird erfasst von:

<img(*src="bild"&*height=60&*width=200)*>
&&

Das && arbeitet fast genau so wie das einfache &. Der entscheidende Unterschied ist, dass hierbei der zweite der beiden Teilausdrücke auf genau den Quelltextbereich zutreffen muss, der vom ersten Teilausdruck erfasst worden ist.

Eine Anwendungsmöglichkeit zeigt sich im folgenden Ausdruck:

(<img*>&&\1)

Das <img*> in der ersten Hälfte umschließt den gesamten IMG-Tag. Dann wird die Variable \1 auf den so eingegrenzten Bereich angewandt. Im Endeffekt wird also der gesamte Inhalt des <img ...> - Tags in \1 gespeichert.

( ... )

Nach obigen Beispielen hast du es dir bestimmt schon gedacht: Klammern dienen, wie in der Mathematik, dazu, Ausdrücke zu gruppieren.

fuß(ball|schweiß|pilz) wird wahr bei Fußball, Fußschweiß und Fußpilz.

Auch das Gegenteil ist möglich: Wenn das erste Zeichen hinter der öffnenden Klammer ein ^ ist, wird der Ausdruck nur wahr, wenn der Inhalt der Klammer nicht wahr ist.

schwarzer (^kaffee|tee) wird dann wahr, wenn das Wort schwarzer gefunden wird und dahinter nicht kaffee oder tee steht.

+

Das Plus-Zeichen steht für einen sich wiederholenden Ausdruck. a+ würde zutreffen auf a, auf aaa, und auf aaaaaaaaa.

Natürlich sind auch kompliziertere Ausdrücke möglich:

[abc]+ trifft auf eine Folge von "a", "b", oder "c" zu. Z.B. ababccba.

([a-z]&[^n])+ trifft zu auf eine Folge von Buchstaben von "a" bis "z", mit Ausnahme von "n".

(bla)+ trifft zu auf bla, blabla, blablabla, usw.

Es ist wichtig zu wissen, dass das + ziemlich dumm ist. Es interessiert sich nicht für das, was hinter ihm steht. Es hört erst auf Bytes zu erfassen, wenn die vorgegebene Folge endet. Ein Ausdruck wie (bla)+blalaber kann niemals wahr werden. Der Grund ist, dass das (bla)+ alle bla erfasst und somit das nachfolgende blalaber nicht zustande kommen kann.

++

Das Doppelplus arbeitet etwas aufwändiger als das einfache Plus. Es erfasst zwar ebenfalls Zeichen und Zeichenfolgen, prüft aber zusätzlich vor jedem Erfassungsschritt, ob der hinter dem Doppelplus stehende Ausdruck zutrifft. Wenn ja, wird die Erfassung an dieser Stelle beendet.

Der beim einfachen Plus noch unzulässige Ausdruck (bla)++blalaber ist deshalb hier zulässig und würde z.B. folgendes erfassen: blablablalaber

Ausdrücke wie [a-z]++gesuchterString sind sehr häufig in Filtern anzutreffen.

{n,n} Sowohl dem einfachen Plus als auch dem Doppelplus kann eine Angabe in geschweiften Klammern folgen. Dort wird definiert, wie viele Wiederholungen des zu suchenden Ausdrucks mindestens bzw. höchstens vorkommen dürfen. Z.B. [a]+{4,10} würde eine Folge von mindestens 4 und höchstens 10 "a"s erfassen. [b]+{20} entspricht einer Folge von exakt 20 "b"s. Das Sternchen steht für "unendlich". Deshalb trifft der Ausdruck [c]+{10,*} auf eine Folge von mindestens 10 "c"s zu.
\

Wenn er nicht gerade zu einer Variablen oder zu einem mit Backslash beginnenden Metazeichen gehört, ist der Backslash das "escape"-Zeichen. Das bedeutet: Mit ihm hebt man einmalig die Sonderbedeutung eines Metazeichens auf.

Wenn man z.B. Klammern als Text in den Vergleichsausdruck einfügen will, schreibt man: \( ... \). Proxomitron weiß dann, dass die Klammern Teil des Textes sind und nicht interpretiert werden sollen. Um einen Backslash als Zeichen einzusetzen, schreibt man: \\

= Das Gleichheitszeichen entspricht nicht nur einem einzelnen =, sondern es nimmt auch Leerzeichen auf, die im Quelltext möglicherweise vor oder hinter dem = stehen. Z.B.: name="wert wird auch wahr bei name ="wert" und name = "wert".
" Das Anführungszeichen entspricht entweder einem Anführungszeichen " oder einem Apostroph ' im Quelltext. "text" würde wahr bei "Text" und bei 'Text'. Wenn man ausdrücklich nur nach "Text" suchen möchte, kann man \"text\" als Vergleichsausdruck schreiben. Der Backslash hebt auch hierbei die Sonderbedeutung des Metazeichens auf.
'

Der Apostroph (oder auch einfaches Anführungszeichen) kann als "Partner" zum Anführungszeichen eingesetzt werden. Er entspricht ebenfalls entweder einem Anführungszeichen oder einem Apostroph, richtet sich dabei aber danach, welches Zeichen zuletzt von einem Anführungszeichen aufgenommen wurde. Wenn das letzte Anführungszeichen also ein Anführungszeichen verbraucht hat, dann wird der nächste Apostroph auch nur bei einem Anführungszeichen wahr. Durch diese Verknüpfung ist es möglich, Quelltexte mit verschachtelten Anführungszeichen zu bearbeiten.

Apostroph in Anführungszeichen: href="javascript:window.open('bison.html');" oder...

Anführungszeichen in Apostrophen: href='javascript:window.open("bison.html");'

Beide Beispiele werden aufgenommen von href=("*'). Das Anführungszeichen nimmt das erste Zeichen auf und der Apostroph sucht das dazu passende Endzeichen.

Es gibt dabei jedoch ein paar Einschränkungen: Das zu suchende Startzeichen und das zu suchende Endzeichen müssen beide im selben Unterausdruck stehen. Das bedeutet, sie müssen im selben Klammer-Paar stehen.

"beliebiger text' funktioniert...

("beliebiger text') funktioniert auch...

"(beliebiger text|anderer text)' funktioniert auch noch, aber...

"(beliebiger text') funktioniert nicht

("|)beliebiger text('|) funktioniert auch nicht.

Wegen der Sonderfunktionen können Anführungszeichen und Apostrophe nicht im selben Unterausdruck verschachtelt werden.

"etwas" etwas anderes 'ende von etwas' wird nicht funktionieren

Es ist sicherer, gezielt nach einem \' zu suchen, wenn man die Sonderfunktionen nicht braucht.

Zum Erfassen von Attributwerten eignet sich die Funktion $AV() besser.

Für alle Metazeichen die nicht mit einem Backslash beginnen gilt: Ein Backslash deaktiviert die Sonderbedeutung der Zeichen im Vergleichsausdruck. \? sucht also nach einem Fragezeichen, \& sucht nach einem UND-Zeichen und \+ sucht nach einem Plus-Zeichen.

Spezielle Zeichen für den Ersetzungsausdruck

Neben den Metazeichen, die nur für den Vergleichsausdruck vorgesehen sind, gibt es auch einige Spezialzeichen, die im Ersetzungsausdruck benutzt werden können.

\0 bis \9 werden benutzt, um den Inhalt der entsprechenden Variablen aus dem Vergleichsausdruck einzufügen.

Zum Einfügen der Daten aus dem Stapelspeicher gibt es zwei Befehle:
Jedes \# im Ersetzungsausdruck fügt den Inhalt eines Speicherplatzes ein. \#\#\# fügt also drei Textblöcke aus dem Stapel ein. Der zweite Befehl ist \@. Er fügt den gesamten Inhalt des Stapelspeichers ein. Die Einträge werden auch hierbei in der Reihenfolge eingefügt, in der sie im Stapel abgelegt wurden.

\u fügt den vollständigen URL der aktuellen Webseite ein
\k unterbricht die aktuelle Verbindung – Dieser Befehl ist in Header-Filtern sehr nützlich, um das Laden von bestimmten Seiten oder Bannern zu verhindern.
\h fügt den Host-Teil des aktuellen URL ein; Im Ersetzungsausdruck wird der vollständige Host-Teil eingefügt, im Vergleichsausdruck wird nur die Domain berücksichtigt und alle Subdomains ignoriert.
\p fügt den Pfad-Teil des aktuellen URL ein
\q fügt den Abfrage-Teil des URL (alles, was auf "?" folgt)
\a fügt den Ankernamen aus dem URL ein (alles, was auf "#" folgt)
\d fügt den Pfad zum Proxomitron-Programmverzeichnis ein, im Format "file://...". Kann z.B. benutzt werden, um Verweise auf lokal gespeicherte Bilder oder Skriptdateien einzufügen.
Das Einbinden von Elementen über lokale Datei-Pfade in Webseiten ist aus Sicherheitsgründen nicht empfehlenswert. Proxomitron bietet dafür mit dem virtuellen Webserver "local.ptron" eine elegantere und sicherere Lösung.

Hinweis: \h, \p, \q, \a und \u können auch im Vergleichsausdruck benutzt werden. Insbesondere \h ist oftmals nützlich, um zu prüfen, ob der URL eines Bildes vom selben Host stammt, wie die Seite selbst.

Weiter geht es mit den erweiterten Befehlen / Funktionen.

© Michael Bürschgens <website@proxomitron.de>