Aufbau der "Header.def" ======================= -1. Vorwort ~~~~~~~ Die Beschreibung der Skriptsprache ist nicht nur für Korrnews, sondern auch für CopyIf relevant, da beide dieselbe Engine verwenden, praktische Unter- schiede im Sprachumfang existieren im Normalfall dann, wenn eine Funktion nur in einem der Programme Sinn ergibt. Die weitere Beschreibung ist dabei auf Korrnews zugeschnitten, spezielle CopyIf-Befehle finden sich in der CopyIf.txt. 0. Aufbau ~~~~~~ 1. Allgemeines 2. Die konkreten Möglichkeiten 2.1 Definition zusätzlicher Header, Header ändern oder Header löschen 2.2 "Wildcards", Variablen, Stringfunktionen, Numerische Funktionen 2.3 Bodyheader nutzen / löschen 2.4 Introductions, Lines & Signaturen 2.5 Text-Body bearbeiten 2.6 Optionen umstellen 2.7 Bedingte Anweisungen (If, else, Bedingungen) 2.8 Ablaufsteuerung (Gosub, Goto, Schleifen, Quit, Do Include) 2.9 Interaktion mit dem Nutzer 2.10 Sonderbefehle 2.11 Debugging 2.12 Multi-Part-Postings/Mails 3. Syntax 1. Allgemeines ~~~~~~~~~~~ Der exakte Name der Datei ist in den Optionen beliebig einstellbar, die Datei muß sich im "Workpath" befinden, was defaultmäßig das Korrnews- Verzeichnis ist. Die Auswertung der Header.Def-Anweisungen findet vor der Eintragung der "Bodyheader" statt, also der Header, welche im Body mit "X-Sowieso=Wert" bzw. "@Sowieso=Wert" am Anfang des Textes definiert wurden. Kommentare sind möglich, die entsprechenden Zeilen müssen mit ";", "#" oder ":" anfangen. Zeilen, die zu lang werden, können mittels "_" am Zeilenende über mehrere Zeilen verteilt werden. Als Begriffsklärung hier noch der Aufbau einer Mail bzw. eines Postings: ------------ I. Header II. Body a) BodyHeader b) Introduction c) Text d) Lines e) -- f) Sig ------------ Beispiel: ------------ I. Message-ID: <3375981e.18152730@news.netway.at> Date: Sat, 10 May 1997 16:32:11 GMT Newsgroups: de.newusers.questions From: habol@netway.at (Hans Boldrino) ... II. a) X-Homepage: http://home.knuut.de/tgl/ X-Virus: Och nö b) Hallo Leute! c) Werdegang eines Newbies Anfang Februar dieses Jahres hat mich (49) die neue Zeit eingeholt. Mit einem Internet-Anschluß. Aber der Reihe nach....... ... d) Gruß und Tschüss! Hans e) -- f) de.* Kurzform für »alle de-Hierarchien und -Gruppen« de.all Synonym für »de.*« de.!alt Kurzform für »de.* außer de.alt« ------------ Außer "normalen" Postings gibt es auch noch Multipart-Postings, auf deren Behandlung noch mal gesondert in 2.12 eingegangen wird: ------------ I. Header II. Multi-Part 1 a) Mime-Header b) BodyHeader c) Introduction d) Text e) Lines f) -- g) Sig III. Multi-Part 2 a) Mime-Header b) BodyHeader c) Introduction d) Text e) Lines f) -- g) Sig ... ------------ Der Sonderfall, daß ein Multi-Part wiederum Multi-Parts enthalten kann, wird von Korrnews nicht beachtet, dürfte aber eher selten sein. 2. Die konkreten Möglichkeiten ~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2.1 Definition zusätzlicher Header, Header ändern oder Header löschen ----------------------------------------------------------------- Die Grundfunktion von Header.def besteht darin, dauerhafte Zusatzheader zu nutzen, dazu reicht es, die gewünschten Einträge einfach in die Datei zu schreiben, alternativ ist auch die Anweisung "Set Header Be- zeichnung = Wert" zulässig und um der Lesbarkeit willen auch empfohlen. Sollte der Header bereits existieren, wird der aktuelle Inhalt durch die Zuweisung an der Originalposition ersetzt, die korrekte Kodierung von 8-Bit-Zeichen erledigt Korrnews übrigens automatisch. Per "Delete Header Bezeichnung" oder einer leeren Zuweisung können überflüssige Header gelöscht werden. Beispiel: Set Header X-Newsreader: Forte Agent 32Bit (mit Hamster und einigen Patches) Set Header X-Homepage = http://www.Ich.bin.toll.de Delete Header X-Mailreader ersetzt bzw. setzt den Newsreader-Verweis, ergänzt den Header um einen Homepage-Verweis und löscht den Header "X-Mailreader", sofern existent. Die alternative Kurz-Schreibweise sieht so aus: X-Newsreader: Forte Agent 32Bit (mit Hamster und einigen Patches) X-Homepage: www.Ich.bin.toll.de X-Mailreader: In seltenen Fällen sind auch mehrzeilige Header sinnvoll, beispiels- weise für "X-Face"-Header. Diese sind folgendermaßen definierbar: Set raw Header X-Face: #0o.eQed-fmU0T,?>{H9_B<%gqE~/fGDJ@[X.]<6obVPh=~9!7-U2x~73]qltjG9F;&/m"-e^.S`B=3[HG$1tjJXq~XDVXVf!r5}EuobNU) MA\WC%"2U8qB3uaW1#U`w9U=`VN/WxZZG^RA+m3&~d"\Vo;dq?eV>WV;Z=6_Q= end Die Einrückung ist möglich, da KorrNews die Tiefe der Einrückung der ersten Zeile überprüft und bei allen weiteren Zeilen dann genau so viele Leerzeichen am Anfang kürzt. Grundsätzlich sollten Header einmalig sein, daher gibt es auch keine Möglich- keit, gezielt den vierten From-Header zu setzen. Eine Ausnahme davon sind zumindest die Auslieferungsheader von Mails mit dem "!RCPT TO"-Header. Um auch damit umgehen zu können, berücksichtigt Korrnews multiple Header in zwei Fällen: - Ein "Delete Header abc" löscht im Gegensatz zu "abc:" nicht nur den ersten, sondern alle Inkarnationen des abc-Headers - Der Befehl "Append Header abc: blubb" löscht keinen bestehenden abc-Header, sondern setzt einen weiteren Header dieses Namens ein. Falls noch kein abc-Header existiert, entspricht es einem "Set Header abc: blubb" Für die systematische Abarbeitung stehen inzwischen noch folgender Befehl zur Verfügung: Set [raw] HeaderContent = ... unterstützt von der numerischen Funktion Headerlines und den Stringfunktionen HeaderName(nr), HeaderContent(Nr) und RawHeaderContent(Nr). 2.2 "Wildcards", Variablen, Stringfunktionen ---------------------------------------- 2.2.1 "Wildcards": Wildcards sind jeweils in Prozent-Zeichen eingeschlossen und erlauben z.B. die Nutzung eines Headers bei der Zuweisung an einen anderen Header, eine Sig oder ähnliches. Innerhalb von Wildcards kann man auch Stringfunktionen nutzen, die anschliessend noch erläutert werden. Verwendung finden Wildcards bei - der Zuweisung u.a. von Headern - Blockanweisungen (Signaturen, Macros etc) In den meisten anderen Fällen werden "Stringausdrücke" verwendet, welche zwar dieselben Möglichkeiten, aber eine IMHO sinnvollere Syntax haben, die eigentliche Wildcard-Syntax ist hauptsächlich deshalb noch drin, um reine Headerzuweisungen nicht zu komplizieren. Doch jetzt erst mal konkrete Beispiele... Um z.B. den originalen X-Newsreader-Header einfach zu ergänzen, ist folgende Anweisung möglich: X-Newsreader: %Header(X-Newsreader)% (plus Hamster & Korrnews) Oder um einen In-Reply-To-Header für XNews zu setzen, geht folgendes: X-In-Reply-To: %Last(Header(References))% Die Einzelnen Anweisungen wie Last, Header etc werden weiter unten erläutert, die Anweisung "Header" sollte allerdings relativ selbsterklärend sein. Um in einem Wildcard-Ausdruck trotzdem "echte" Prozentzeichen zu nutzen, kann man entweder "raw"-Elemente verwenden oder je Prozentzeichen einfach zwei hintereinander schreiben: Set Header X-Promille: 25%% je Liter muß sein! Falls einem die Stringausdrücke lieber sind, reicht es, diese mit "%" zu umranden, statt Set Header X-Egal: Der Autor ist %Header(From)%, behauptet er! kann man genauso gut folgendes schreiben: Set Header X-Egal: %"Der Autor ist " + Header(From) + ", behauptet er!"% 2.2.2 Variablen Variablen sind z.B. dazu nutzbar, - einen längeren/komplizierteren und mehrfach gebrauchten Ausdruck mit weniger Tippaufwand nutzen zu können - Zustände zu merken, um sie später noch mal in IF-Anweisungen verwenden zu können - Strings stückchenweise zusammensetzen zu können, um sie dann komplett z.B. einem Header zuzuweisen. Die Skriptsprache kennt folgende Variablentypen: String : Zeichenketten, Länge praktisch beliebig Integer : Ganzzahlen zwischen ca. -4 Milliarden und +4 Milliarden Float : Fliesskommazahlen in doppelter Genauigkeit Boolean : Entweder true oder false Aus Kompatibilitätsgründen können String-Variablen ohne spezielle Deklaration erzeugt werden, ein einfaches "Set", die Übergabe als Parameter oder das Nutzen in einer For-Schleife erzeugt sie automatisch. Erzeugt werden Variablen über den "Var"-Befehl, wobei ggf. auch ein Anfangswert oder die Gültigkeit angegeben werden kann. Um eine Stringvariable %Subjekt% zu erzeugen und mit dem Headerinhalt von "Subject" vorzufüllen, wäre folgendes einzutippen: Var %Subjekt%: String = Header("Subject") Man kann auch mehrere Variablen und sogar mehrere Variablen verschiedener Typen auf einmal erzeugen: Var %Anz%, %Tr%: Integer, %Summe%, %DS%: Float, %Flag%: Boolean = true Werden Variablen innerhalb von Subs definiert, gelten diese nur für die Ausführung der Sub und werden danach automatisch wieder gelöscht. Globale Variablen gleichen Namens werden solange verdeckt, aber nicht geändert. Globale Variablen sind alle außerhalb von Subs angelegten Variablen bzw. auch Variablen in Subs, wenn diese mit dem Zusatz "global" angelegt werden: Sub Init Var global %Subjekt%: String = Header("Hallo") Var global %Fup%: String = Header("FollowUp-To") Var global %AnzNGs%: Integer = Count(",", Header(Newsgroups)) + 1 end sub Zur Illustration: Var %Test%: String %Test% = "Hallo" Gosub Test Do Show Info %Test% Sub Test Var %Test%: Integer = 42 Do Show Info Str(%Test%) end sub gibt zuerst "42", dann "Hallo" aus. Konvertierungen zwischen den verschiedenen Variablentypen sind mit entsprechenden Funktionen (Val, Str, IStr, BoolToStr, ...) möglich, für die Ausgabe von Zahlen ist Str praktisch immer erforderlich. Das normale Setzen oder Ändern einer existierenden Variable sieht so aus: %Gruppe% = Header(Newsgroups) %Programmierer% = "Thomas G. Liesner" %SeinVorname% = "Das ist doch der " + Extract("^[^ ]+", %Programmierer%) + "!" %ZitierteZeilen% = MatchedLines('^>') Aus Kompatibilitätsgründen kann ein "Set" davor gesetzt werden: Set %ZitierteZeilen% = MatchedLines('^>') Die Nutzung in Wildcards sieht dann so aus: X-Der-Programmierer: heisst %Programmierer%! Diese "Wildcard"-Ausdrücke sind nur noch in Headerzuweisungen und Set/end-Blöcken verwendbar, ansonsten entspricht die Skriptsprache einer "normalen" Programmier- sprache: Variablen können überall verwendet werden, wo sie vom Typ passen bzw. durch Hilfsfunktionen wie Val oder Str passend gemacht werden. Ein Sonderfall ist aus Kompatibilitätsgründen For, der sowohl String- als auch numerische Variablen akzeptiert. Richtig interessant werden diese Funktionen aber erst im Zusammenhang mit Bedingungen. 2.2.3 Stringfunktionen: Konvertierungen: ---------------- Lower(...) wandelt den String in Kleinschrift um Upper(...) wandelt den String in Grossschrift um DecodeISO(...) wandelt einen als ISO-8859-1/qp-kodierten Header in einen "normalen" String mit 8Bit-Zeichen um. 8BitTo7Bit(...) wandelt 8-Bit-Zeichen in Ersatzzeichen innerhalb des ASCII- Codes um. (ä => ae, ß => ss, ...) DosToWin(...) wandelt DOS-Umlaute (und andere Sonderzeichen) in passende Zeichen im Windowszeichensatz. WinToDos(...) wandelt Windows-Umlaute (und andere Sonderzeichen) in passende Zeichen im DOS-Zeichensatz. Str(...,...,...) Wandelt den als ersten Parameter übergebenen numerischen Ausdruck in einen String um. Der zweite optionale numerische Parameter legt die Anzahl der Vorkomma-, der dritte optionale die Anzahl der Nachkommastellen fest, bei Nichtangabe werden zwei NK-Stellen angezeigt. IStr(...) wandelt den als ersten Parameter übergebenen numerischen Ausdruck in einen String (ohne NK-Stellen) um. BoolToStr(Bed.) Wandelt das Resultat der übergebenen Bedingung in einen String um und erlaubt somit die direkte Zuweisung einer Bedingung an eine Variable. EscRegExp(...) Wenn man Header u.ä. als RexExp nutzt, kann man mittels dieser Funktion versehentliche Seiteneffekte vermeiden, da alle speziellen Zeichen ausmaskiert werden ("." => "\." etc.) Chr(...) Wandelt den als ersten Parameter übergebenen numerischen Ausdruck in das zugehörige ASCII/ANSI-Zeichen um. FillChar (..., ...) Kopiert den ersten Parameter so oft aneinander, wie als zweiter numerischer Parameter angegeben worden ist, FillChar('+-', 3) würde somit "+-+-+-" zurückliefern. LTrim(...) Kürzt alle Leerzeichen oder Tabs von vorne bis zum ersten anderen Zeichen. RTrim(...) Kürzt alle Leerzeichen oder Tabs von hinten bis zum ersten anderen Zeichen. Trim(...) Kombiniert LTrim und RTrim. String "zerlegen"/"umbauen": --------------------------- First(...) sucht das erste Element des Strings heraus. Bei einem String mit Kommata den Teil vor dem ersten Komma (z.B. Newsgroups-Header bei Crosspostings), falls der String mit "<" anfängt und mit ">" endet, holt er das erste "<...>"-Paar heraus (z.B. References-Header). Last(...) sucht das letzte Element des Strings heraus, äqui- valent zu "First" Address(...) bezieht sich - wie auch die folgenden beiden Funktionen - auf Mailadressen i.S. des From- oder Reply-To-Headers. Address versucht, nur die eigentliche Adresse zu extrahieren, aus "Hans Hirni " wird also "abc@def.gh" Name(...) Versucht, den Gesamtnamen zu extrahieren, aus "Hans Hirni " wird also "Hans Hirni" FirstName(...) Versucht, nur den Vornamen zu extrahieren, aus "Hans Hirni " wird also "Hans" MakeAddress(...,...) kombiniert den übergebenen Namen und die übergebene Mail- adresse zu einem From/Reply-To/To-kompatiblen Ausdruck iSv "Name " incl. Berücksichtigung von Sonderfällen im Namen (Punkte, Anführungsstriche) Extract(...,...) Versucht, den als 1. Parameter angegebenen regulären Ausdruck (entspricht den regulären Ausdrücken im Hamster) im zweiten Parameter zu finden, bei Erfolg liefert er den entsprechenden Teil zurück, sonst einen Leerstring. Aus Extract("a.*e", "Hallenbau") würde also "alle" Left(..., ...) Liefert vom ersten Parameter die ersten x Zeichen zurück, das x steht dabei für den zweiten Parameter. Right(...,...) Liefert vom ersten Parameter die letzten x Zeichen zurück, das x steht dabei für den zweiten Parameter. Copy(...,...,...)Liefert vom ersten Parameter ab dem x. Zeichen y Zeichen zurück, das x steht dabei für den zweiten und das y für den dritten Parameter. CutLeft(...,...) Entfernt die als zweiten Parameter angegebene Zahl von Zeichen links aus dem als ersten Parameter übergebenen String, CutLeft("BENGEL", 1) ergibt somit "ENGEL". CutRight(...,...)Entfernt die als zweiten Parameter angegebene Zahl von Zeichen rechts aus dem als ersten Parameter übergebenen String, CutRight("Re: Ups", 4) ergibt somit "Re:". Line (...,...) Der erste Parameter gibt die Zeilennumer an, der zweite enthält den Text. Als Ergebnis wird die gewünschte Zeile zurückgegeben, bei einer nicht existenten Zeilennummer ein Leerstring. Die Zählung beginnt mit 1 und endet mit CountLines(String). Replace (...,...,...) Ersetzt im ersten Parameter alle Vorkommen des zweiten Parameters (interpretiert als RexExp!) mit dem dritten Parameter. WordWrap (...,...,...) Liefert den ggf. umgebrochenen ersten Parameter zurück, der zweite numerische Parameter gibt dabei die maximal erlaubte Zeilenzahl zurück, der dritte Parameter gibt den ab der zweiten Zeile zu verwendenden Einzug (als String) an. Posting-spezifisches: --------------------- Header(...) liefert den Inhalt des über seinen Namen angesprochenen Headers HeaderName(Nr) liefert den Namen des über seine Position angesprochenen Headers HeaderContent(Nr)liefert den Inhalt des über seine Position angesprochenen Headers RawHeaderContent(Nr) liefert den ggf. noch kodierten Inhalt des über seine Position angesprochenen Headers BodyHeader(...) liefert den Wert des angegebenen BodyHeaders, siehe nächsten Punkt. Full [raw] Header [without Headername1, ...] Ohne Parameter und z.Z. nur in Bedingungen sinnvoll nutzbar, liefert den gesamten Header als Zeichenkette zurück. Um bestimmte Header auszuschliessen, kann der "without"-Zusatz genutzt werden. Full [raw] Body Ohne Parameter und z.Z. nur in Bedingungen sinnvoll nutzbar, liefert den gesamten Textbody abzgl. der Signatur zurück. Full [raw] Sig[nature] Ohne Parameter und z.Z. nur in Bedingungen sinnvoll nutzbar, liefert die komplette Signatur als String zurück Full Article/Posting/Mail liefert den gesamten Text im "raw"-Format als String zurück Path liefert den Pfad, in dem Korrnews nach Postings sucht Filename liefert den Dateinamen des aktuell bearbeiteten Postings Partfilename liefert bei Multi-Part-Postings den Dateinamen für das Attachment, sofern ein entsprechender MIME-Part aktiv ist. Bodyline(...) liefert den Inhalt der x. Zeile des Textbodys, dabei muß als Parameter eine Zahl bzw. ein numerischer Ausdruck angegeben werden. Nicht vorhandene Zeilen liefern einen Leerstring zurück. Externe Daten: -------------- ReadIniStr( ) liest aus einer INI-Datei, als Parameter werden der Dateiname, der Abschnitt, der Key und ein Standardwert (der benutzt wird, wenn der Key nicht existiert) benötigt. GetDateTime(...) erlaubt das Auslesen der aktuellen Zeit bzw. des aktuellen Datums. Folgende Platzhalter sind im Formatstring erlaubt: c Zeigt das Datum im Kurzformat der Windowseinstellungen und die Zeit im Langformat der Windowseinstellungen an. d Zeigt den Tag als Zahl ohne führende Null an (1-31). dd Zeigt den Tag als Zahl mit führender Null an (1-31). ddd Zeigt den Tag als Abkürzung an und verwendet dabei für die Wahl der Abkürzungen die Windowseinstellungen. dddd Zeigt den Tag als vollständigen Namen an, auch hier werden die aktuellen Windowseinstellungen genutzt. ddddd Zeigt das Datum im Kurzformat der Windowseinstellungen an. dddddd Zeigt das Datum im Langformat der Windowseinstellungen an. m Zeigt den Monat als Zahl ohne führende Null an (1-12). Folgt der Bezeichner m direkt nach der Angabe h oder hh, wird statt des Monats die Minute angezeigt. mm Zeigt den Monat als Zahl mit führender Null an (01-12). Folgt der Bezeichner mm direkt nach der Angabe h oder hh, wird statt des Monats die Minute angezeigt. mmm Zeigt den Monat als Abkürzung an und verwendet dabei die Windowseinstellungen für den Bezeichner. mmmm Zeigt den Monat als vollständigen Namen an und verwendet dabei die Windowseinstellungen für den Bezeichner. yy Zeigt das Jahr als zweistellige Zahl an (00-99). yyyy Zeigt das Jahr als vierstellige Zahl an (0000-9999). h Zeigt die Stunde ohne führende Null an (0-23). hh Zeigt die Stunde mit führender Null an (00-23). n Zeigt die Minute ohne führende Null an (0-59). nn Zeigt die Minute mit führender Null an (00-59). s Zeigt die Sekunde ohne führende Null an (0-59). ss Zeigt die Sekunde mit führender Null an (00-59). z Zeigt die Millisekunde ohne führende Nullen an (0-999). zzz Zeigt die Millisekunde mit führenden Nullen an (000-999). t Zeigt die Zeit im Kurzformat der Windowseinstellungen an. tt Zeigt die Zeit im Langformat der Windowseinstellungen an. am/pm Verwendet das 12-Stunden-Format für den führenden Bezeichner h oder hh und zeigt 'am' für Zeitangaben vor 12 Uhr mittags oder 'pm' für Zeitangaben nach 12 Uhr mittags an. Der Bezeich- ner am/pm kann in Groß-, Klein- oder gemischter Schreibweise angegeben werden und wird dementsprechend angezeigt. a/p Verwendet das 12-Stunden-Format für den führenden Bezeichner h oder hh und zeigt 'a' für Zeitangaben vor 12 Uhr mittags oder 'p' für Zeitangaben nach 12 Uhr mittags an. Der Bezeichner a/p kann in Groß-, Klein- oder gemischter Schreibweise angegeben werden und wird dementsprechend angezeigt. ampm Verwendet das 12-Stunden-Format für den führenden Bezeichner h oder hh und zeigt statt am/pm die in den Windowseinstellungen vorgesehenen Kürzel. / Verwendet das in den Windowseinstellungen vorgesehene Datums- trennzeichen. : Verwendet das in den Windowseinstellungen vorgeshene Zeittrenn- zeichen. 'xx'/"xx" In halbe oder ganze Anführungszeichen eingeschlossene Zeichen wirken sich nicht auf die Formatierung aus und werden wie eingegeben angezeigt. Beispiel: GetDateTime("dd.mm.yyyy") am 1.4.2000 => "01.04.2000" Konstanten: ----------- CRLF Entspricht einem Zeilenumbruch TAB Entspricht dem Tabulator-Zeichen SigDel Entspricht dem Signaturabtrenner "-- " Benutzereingaben: ----------------- Input (.,.,.) erlaubt die Eingabe eines Strings per Input-Box. Als Parameter muß der Dialogtitel, eine Eingabeaufforderung und der Vorgabe- wert übergeben werden. Weiteres: --------- Version gibt die aktuelle Versionsnummer zurück, funktioniert aber erst ab V2.86 2.2.4 Numerische Funktionen: Bei verschiedenen Stringfunktionen oder auch bei im weiteren erläuterten Befehlen sind numerische Parameter erlaubt. Diese können durchaus komplexer sein. Zum einen sind natürlich reine Konstanten möglich: Delete Bodylines from 10 to 20 Aber auch Berechnungen: If Bodylines > 0 then Do show Info 'Durchschnittliche Zeichen pro Zeile: ' + _ Str( Len( Full Body ) / Bodylines , 5, 2 ) Und natürlich numerische Variablen: Var %SubjLen%: Integer = Len(header(Subject)) If %SubjLen% > 100 then Do Show Info "A bisserl langer Betreff..." Berechnungen können auf die Grundrechenarten, Klammerungen, die in der Syntax erwähnten normalen Rechenfunktionen, die Potenzfunktion (^) und folgende Zusatzfunktionen zurückgreifen: Allgemeine Funktionen: ====================== Count (String, String) Gibt die Anzahl der Vorkommen vom ersten String im zweiten String zurück, bei Überlappungen wird jedes Teilstück gezählt, Beispiel: Count("elle", "ellellellellelle") ergibt 5 und nicht 3. Ord (String) Gibt den ASCII-Wert des ersten Zeichens des Strings zurück, 0 bei einem leeren String. Pos (String, String) Gibt die Position des ersten im zweiten String an, 0, falls der String nicht im anderen vorkommt. Len[gth] (String) Gibt die Länge eines Strings (=Zeichenzahl) zurück Val (String) Wandelt einen Stringausdruck in eine Zahl, auch Formeln erlaubt. Trunc (Zahl) Gibt die Zahl ohne Nachkommastellen zurück. Random (Zahl) Gibt eine ganzzahlige Zufallszahl zwischen 0 und Zahl-1 zurück. Mail/News-spezifische Funktionen: ================================= PartCount Gibt die Anzahl der MIME-Parts zurück, bei einem normalen Posting ist der Rückwert 1. MatchedLines (RegExp) Gibt die Anzahl der Zeilen zurück, die dem angegebenen RegExp entsprechen. Bodylines Gibt die Anzahl der Zeilen im Textbody zurück Headerlines Gibt die Anzahl der Zeilen im Header zurück Siglines Gibt die Anzahl der Zeilen in der Signatur zurück Introlines Gibt die Anzahl der Zeilen im Intro zurück CountLines (String) Gibt die Anzahl der Zeilen im übergebenen String zurück NextMatchedLine (Zahl, RexExp) Gibt die erste Zeilennummer zurück, in der die RegExp gefunden wird, gesucht wird ab der als ersten Parameter übergebenen Zeilennummer. 2.3. Bodyheader nutzen / löschen --------------------------- Bodyheader sind die im Posting selber definierten Pseudoheader, welche Korrnews nach dem Durchlauf der Header.def automatisch in den eigentlichen Header übernimmt und im Body löscht. Es gibt allerdings durchaus Verwendungsmöglichkeiten innerhalb der Header.def. Zum einen sind Zuweisungen möglich, innerhalb von Wildcards ist ein Bodyheader über das Konstrukt %BodyHeader(Bezeichnung)% erreichbar und somit sowohl Variablen als auch "richtigen" Headern zuweisbar. Die Hauptmöglichkeit dürfte aber auch die Möglichkeit sein, die Header.def zu steuern. Ein kleiner Vorgriff auf den If-Befehl macht das hoffentlich deutlicher: Var %NG%: String = Header("Newsgroups") Var %B-Fup%: String = BodyHeader(Fup) If %B-Fup%>"" If Not (%NG% contains %B-FUP%) Set Header Newsgroups = %NG%,%B-FUP% %NG%=Header(Newsgroups) endif Set Header FollowUp-To: %B-Fup% Delete BodyHeader Fup endif Dieser Block reagiert auf einen gesetzten Bodyheader namens "Fup" und setzt entsprechend den Header "FollowUp-To" und ergänzt ggf. noch den "Newsgroups"-Header um die gesetzte Gruppe. Um Bodyheader, die eigentlich nur temporäre Funktion zu haben, nicht wirklich zu verschicken, dient die Anweisung Delete Bodyheader Bezeichnung welche verhindert, daß die sonst übliche Übertragung in den eigent- lichen Header erfolgt. 2.4 Introductions, Lines & Signaturen --------------------------------- - Introductions sind zusätzliche Zeilen, die zu Anfang des Postings eingefügt werden, - Lines sind zusätzliche Zeilen, die zwischen Text und Signatur eingefügt bzw. ans Textende angefügt werden - und die Signatur wiederum ist ein Textblock am Ende, welcher mittels Trenner ("-- ") optisch vom Rest abgetrennt wird. Die Syntax ist in allen Fällen gleich, die einzige Besonderheit weist die Signatur auf: Bei Zuweisungen überprüft Korrnews automatisch, ob in dem Abschnitt oder der Datei mehrere Signaturen enthalten sind (durch Test auf SigTrenner incl. Sigtrenner ohne Leerzeichen) und wählt - sofern mehr als eine zur Verfügung steht - zufällig eine aus. Bei Zuweisungen gibt es zwei grundsätzliche Alternativen: Neusetzen oder Anhängen, die Anweisungen heissen entsprechend "Set" und "Append". Zudem gibt es drei Möglichkeiten, den Inhalt zu übergeben: Entweder in der Header.def selber als Mehrzeiler: ( Set | Append ) [raw] ( Sig[nature] | Line[s] | Introduction ) Zeile #1 Zeile #2 Zeile #3 Zeile #4 end Beispiele: If Header(Newsgroups) contains "test" Set Intro ignore - noreply - ignore end endif Set Sig Name: Unbekannt Alter: Habe ich Gruß: Tschüss end oder in der Header.def als Einzeiler: Set Signature = "Meine Signatur ist kurz" Append Sig = "(Oder doch nicht?)" oder in einer externen Datei, so daß in der Header.def nur noch ein Verweis steht: Set Sig from "sigs.txt" Set Lines from "Gruss.txt" Sofern die Sig-Datei oder der Sig-Block "--"-Zeilen enthält, interpretiert Korrnews dies so, daß dort mehrere Sigs enthalten sind. Im Normalfall sucht sich Korrnews dann per Zufall eine heraus, um gezielt eine Sig zu verwenden, ist folgende Syntax vorgesehen: Set Sig #12 from "many_sigs.txt" bzw. If BodyHeader(X-Sigfile) > "" Set Sig # Val("0"+BodyHeader(X-SigNr)) from Bodyheader(X-Sigfile) endif Im zweiten Fall würde - sofern der Bodyheader X-Sigfile gesetzt wurde - ein möglicherweise gesetzter Bodyheader X-SigNr ausgewertet, eine Null davorgesetzt, damit auch ein fehlender Bodyheader keinen Fehler verursacht, und das Zusammengesetze in eine Zahl konvertiert. Mit einem X-Sigfile: jokes.txt X-SigNr: 3 am Anfang eines Posting würde man mit obiger Anweisung die dritte Signatur aus der angegebenen "jokes.txt" durch Korrnews ans Posting angehängt. Bitte beachten Sie bzgl. der einzelnen Signaturen das Netiquette-Limit von 4 Zeilen je max. 80 Zeichen! Korrnews achtet übrigens darauf, daß Lines, Intros und Sigs nicht bei mehreren Durchläufen mehrfach drangehängt werden, indem er die jeweiligen Zeilen mit dem einzusetzenden Text vergleicht und bei Identität keine Änderungen vornimmt. Mit Delete Sig Delete Intro Delete Lines können Zuweisungen auch noch mal zurückgenommen werden. Für Abfragen gibt es "HasSig" und für spezielle vergleiche gibt es noch ChangedSig, ChangedIntro, ChangedLines und Siglines und Introlines, wenn man die Zeilenzahl der Abschnitte wissen möchte. 2.5 Text-Body bearbeiten -------------------- Zur Änderung des eigentlichen Textes dienen verschiedene Befehle: Do Replace ( first | last | all ) with [ in ( Header | Header2 | Intro | Body | Lines | Sig | %Variable% ) ] [ from ] [ to ] Hiermit kann gezielt im Text geändert werden, der Suchausdruck ist dabei ein regulärer Ausdruck wie auch im Hamster oft zu finden. Beispiel: Mit Do Replace first ":" nach "Frank Müller schrieb in :" ändern. Um den Bereich einzugrenzen, ist die Eingabe der ersten und/oder letzten untersuchten Textzeile bestimmbar - wobei QP-kodierte Texte umgebrochene Teilzeilen nicht als eigene Zeilen mitzählen. Falls nicht der Textbody durchsucht werden soll, kann die Suche auch alternativ über Lines, Signatur oder den aktuell eingestellten Einleitungsblock gehen: Set Sig # Einrückung soll von Korrnews # nicht geändert # werden # !! end Do Replace all "^#" with "" in Sig Ein Sonderfall ist noch "Do Replace ... in %Variable%": Mit dieser Variante sind auch first/last-Ersetzungen in einer Variablen möglich, welche mit der Stringfunktion Replace nicht machbar sind. Allerdings werden from/to-Angaben nicht beachtet. Eine ähnliche Funktion ist dann noch der Befehl Set Macro ... end Falls man z.B. einen automatischen Gruß haben möchte, kann man folgendes verwenden: Set Macro "#gruss#" Tschüsschen, Euer Paule! end Wenn dann im Posting Das war's eigentlich schon. #gruss# vorkommt, wird daraus mit obigem Befehl: Das war's eigentlich schon. Tschüsschen, Euer Paule! Ein anderes naheliegendes Macro wäre auch #spoiler#, man sollte nur darauf achten, daß nicht versehentlich ungewollte Ersetzungen passieren, weil der gewählte Macro-Name auch mal so einzeln in einer Zeile auftauchen könnte. Für besonders spezielle Fälle gibt es dann noch: Set Bodyline(ZeilenNr) = ... zum Ändern von bestimmen Zeilen, Delete Bodylines xx to xx bzw. Delete Bodyline xx zum Löschen bestimmter Zeilen und Insert Bodyline ZeilenNr = ... zum Einschieben von einzelnen Zeilen. Delete between ( first | last ) , , [, ] löscht den ersten bzw. letzten Textblock, dessen Anfangszeile dem ersten und dessen Endzeile dem zweiten RegExp-Ausdruck entspricht. Falls der erste Suchausdruck leer ist und der erste passende Textblock gelöscht werden soll, wird alles bis zur zweiten RegExp gelöscht, ist der zweite Suchausdruck leer und soll der letzte passende Textblock gelöscht werden, wird alles ab dem ersten RegExp gelöscht. Die Bedingung bestimmt, ob die Anfangs- und Endzeile des Blockes mitgelöscht werden soll und der optionale letzte Stringausdruck wird an die Stelle des ersetzten Ausdrucks eingefügt. Diese Funktion ist zum Beispiel dazu brauchbar, Mailinglisten von Werbeblöcken zu befreien. 2.6 Optionen umstellen ------------------ Mit dem Befehl Set Option Bezeichnung = "Wert" können jederzeit die INI-Optionen für den aktuellen Korrnews-Lauf temporär (!) geändert werden, dauerhafte Änderungen sind damit im Gegensatz zu "Do Write IniStr" nicht möglich. Wenn man z.B. normalerweise in den Optionen eine Signatur-Datei akti- viert hat, diese aber in einer bestimmten Gruppe nicht nutzen will, reicht folgende Anweisung: Set Option SigFile = Die Namen der Option sind zum einen in der HTML-Hilfe hinterlegt, zum anderen auch aus der Korrnews.ini entnehmbar. Hinweis: Die Namen der Optionen können sich im Laufe der zukünftigen Korrnews-Versionen durchaus ändern. Prinzipiell bin ich zwar für Konstanz, aber Garantien kann es nicht geben. 2.7 Bedingte Anweisungen -------------------- 2.7.1 If / else / elseif / endif Um flexiblere Möglichkeiten zu bieten, gibt es die Möglichkeit, Zeilen von Bedingungen abhängig zu machen. Die Grundform lautet: If [then] ... [else if ...] [else ...] endif Der ElseIf- und der Else-Zweig sind optional, für die "..." lassen sich beliebige Anweisungen einsetzen, der Übersichtlichkeit halber sind Ein- rückungen empfehlenswert. If-Bedingungen lassen sich auch schachteln, bis zu 15 Ebenen sind erlaubt. Falls man nur einen Befehl ausführen möchte, geht auch die Kurzvariante: If then Zuerst einige konkrete Beispiele: Beheben des Agent-Bugs bzgl Anführungsstriche um den Namen im From: If Header(From) equals 'Thomas G. Liesner ' From: "Thomas G. Liesner" endif macht aus From: Thomas G. Liesner folgendes: From: "Thomas G. Liesner" Überflüssiges Reply-To löschen: If Header(From) contains Header(Reply-To) Delete Header Reply-To endif In Testgruppen ein spezielles Reply-To setzen: If Header "Newsgroups" contains "test" ; für bitte einen eigenen FQDN eingeben. Reply-To=botanswer@ endif Änderungen nur, wenn bestimmter Body-Header nicht verwendet: If BodyHeader "HeaderOk" Is Empty ... else ; Spuren verwischen Delete BodyHeader HeaderOk endif Gruppenabhängiges Reply-To setzen: ; Nur, wenn auch richtige Mailadresse: If Lower(Header(From)) contains Lower("TGL") If Not Header "Newsgroups" is empty ; für bitte einen eigenen FQDN eingeben. Reply-To=Answer.from.%First(Header(Newsgroups))@ else Reply-To=Mailanswer@ endif endif In bestimmten Gruppen die Speicherung in deja.com vermeiden: Var %NG%: String = Header(Newsgroups) If ("liebesakt" IN %NG%) or (%NG% contains "sex") then X-No-Archive: Yes In bestimmten Gruppen besonders sicherheitsbewusst wirken: If Header(Newsgroups) = "de.soc.zensur" X-No-Archive: Yes X-PGP: ... endif dnq-Sig-Projekt unterstützen, in anderen Gruppen Zufallssprüche: If Not HasSignature and Header(Newsgroups)="de.newusers.questions" Set Signature from "dnq-proj.txt" elseIf not HasSignature Set Signature from "my-sigs.txt" endif Hinweis oberhalb der Sig, wenn man ein FollowUp-To gesetzt hat: If Header "FollowUp-To" > "" If Header "Newsgroups" contains "," Set Lines X-Post über %Str(Count(',', Header(Newsgroups))+1)% Gruppen, FollowUp-To %Header(FollowUp-To)% end else Set Lines FollowUp-To %Header(FollowUp-To)% end endif endif 2.7.2 Boolesche Funktionen Die komplette Übersicht findet sich in der Syntaxbeschreibung am Ende, hier eine Liste der booleschen Sonderfunktionen: Konstanten ---------- True Steht für "Ja"/"Wahr" False Steht für "Nein"/"Falsch" Postingeigenschaften -------------------- HasSig[nature] Liefert "True", wenn eine Signatur existiert bzw. inzwischen per Skript angehängt wurde Has8BitChars Liefert "True", wenn im Posting Zeichen mit gesetztem 8. Bit vorkommen wie unkodierte Umlaute etc. PartTyp is Liefert "True", wenn der Typ des aktuellen MIME-Parts gleich dem ist. Für sind folgende Bezeichner erlaubt: Unknown, Text, Plaintext, UnknownText, HTML, Binary, Application, Audio, Image, Video. PartEncoding is Liefert "True", wenn das Encoding des aktuellen MIME-Parts gleich dem ist. Für sind folgende Bezeichner erlaubt: quoted-printable, qp, 8bit, 8-bit, 8 bit, base64, ascii, 7-bit, 7bit, 7 bit, unknown. Statusabfragen -------------- Changed Gibt "True" zurück, wenn die bisherigen Skriptanwei- sungen Änderungen am Posting bewirkt haben. ChangedLines Gibt "True" zurück, wenn durch "Set/Append Lines" angehängte Zeilen definiert wurden. ChangedSig[nature] Gibt "True" zurück, wenn Sig-Anweisungen ausgeführt worden sind. ChangedIntro[duction] Gibt "True" zurück, wenn die Einleitung per Set/Append Intro gesetzt wurde. VarExists(Variablenname) Gibt "True" zurück, wenn die Variable angelegt worden ist. Benutzersteuerung ----------------- Ask (..., ...) Gibt "True" zurück, wenn der Benutzer den Ja-Button der angezeigten Messagebox bestätigt. Als Parameter muß der Text angegeben werden, der Titel kann zusätzlich bestimmt werden. Abort Gibt "True" zurück, wenn der Benutzer den Abbruch-Button der angezeigten Messagebox bestätigt. Als Parameter muß der Text angegeben werden, der Titel kann zusätzlich bestimmt werden. Sonstiges --------- FileExists (...) Testet, ob der angegebene Dateiname existiert. Sofern kein Pfad angegeben ist, testet KN im aktuellen Verzeichnis. Konvertierung ------------- StrToBool konvertiert einen String in einen boolschen Wert. Das Ergebnis einer Bedingung kann bei Bedarf einer boolschen Variable zugewiesen werden: Var %LongHeader% : boolean = HeaderLines > 30 2.8 Ablaufsteuerung (Gosub, Goto, Quit, Do Include) ----------------------------------------------- Um Funktionsblöcke o.ä. auslagern zu können, gibt es folgendes Statement: Do Include Diese Anweisungen werden beim Laden der Skriptdatei bereits ausgeführt, daher funktioniert auch die Anweisung: Set Sig Do Include "sigs.txt" end Der Inhalt der Datei wird genauso behandelt wie die "originalen" Zeilen des Skripts. Der Dateiname wird - sofern kein absoluter Pfad angegeben - relativ zum Arbeitsverzeichnis geladen. Mit Gosub ist ein Sprung in die gleichnamige "Sub" möglich. Beispiel: Gosub Teil1 Gosub Teil2 Quit Sub Teil1 ... endsub Sub Teil2 ... endsub Um Parameter nutzen zu können, kann folgende Syntax verwendet werden: Nach Gosub Combine "Dies und", "das", %Ergebnis% Gosub Combine %Ergebnis%, "wünsche ich mir", %Ergebnis% Sub Combine (%eins%: String, %zwei%: String, Var %Zusammen%: String) %Zusammen% = %eins% + " " + %zwei% endsub würde in der Variable %Ergebnis% der Wert "Dies und das wünsche ich mir" stehen. Das "Var" erlaubt das Ändern der ursprünglichen Variable. Bei Nicht-Var-Parametern sind sowohl Konstanten als auch Stringfunktionen oder Variablen erlaubt. Als Parameter sind dabei alle Variablentypen zulässig, bei Nicht-Angabe des Types wird der Parameter als Stringparameter behandelt. Um einen Befehl mehrfach auszuführen, gibt es diverse Schleifentypen: Das For / Next-Statement in zwei Varianten: For %i% = 1 to 10 .... Next und For %i% = 1 to 10 do ... Anfangs- und Endwert können dabei auch berechnet werden und mit "Step" kann die Schrittweite beliebig gewählt werden: Var %Countdown%: Integer For %Countdown% = 10 to 1 step -1 ... Next Die Variable muß vom Typ Integer, Float oder String sein, letzteres ist aus Kompatibilitätsgründen drin. Sollte die Variable vorher nicht per "Var" definiert worden sein, wird sie als Stringvariable erzeugt. Das While/Wend-Statement, welches ggf. gar nicht durchlaufen wird, wenn die Bedingung von Anfang an nicht erfüllt wird: While ... Wend Das Repeat/Until-Statement, welches zumindest einen Durchlauf hat, da die Bedingung erst am Ende getestet wird. Bei Erfüllung der Bedingung bricht die Schleife ab: Repeat ... Until Und die Endlosschleife, welche nur im Zusammenhang mit einem Abbruchbefehl Sinn macht: Endless ... If then ... Loop Als Abbruchbefehle stehen Goto - welches ggf. auch mehrere Schleifen auf einmal verlassen kann - , continue (welches bei dieser Schleife allerdings nicht sehr sinnvoll sein dürfte) und break zur Verfügung: ; Aus "@" ein " at " machen Var %i%: Integer, %s%: String = "Hallo@Erde" Endless %i% = Pos("@", %s%) If %i% = 0 then break %s% = Left(%s%, %i%-1)+" at "+Copy(%s%, %i%+1, Len(%s%)-%i%) Loop Do Show Info %s% ; Nur eigenen Text überprüfen... Var %i%: Integer For %i% = 1 to Bodylines If Bodyline(%i%) begins with ">" then Continue ... Next Repeat :Hauptschleife ... While ... ... For ... ... If ... then Goto Hauptschleife If ... then Goto NotAus ... Next ... Wend ... Until ... :NotAus Goto kann auch außerhalb von Schleifen verwendet werden, um bestimmte Teile zu überspringen, im Normalfall führt der Verzicht auf Goto aber zu lesbareren Skripten. Die Sprungziele von Goto müssen mit einem Doppelpunkt eingeleitet werden und sollten jeweils einmalig sein, da KN ansonsten immer auf den ersten passenden Label springen würde. Schleifen können - wie im letzten Beispiel gezeigt - natürlich auch beliebig geschachtelt werden, allerdings ist die intensive Nutzung von Schleifen aus Performancegründen heraus nicht empfehlenswert, da das Interpretieren der Skriptsprache längst nicht so schnell ist wie eine echte Programmiersprache. Der Befehl "Quit" beendet das Skript und ist bei Verwendung von Subs nötig, da ansonsten die Fehlermeldung "Unbekannter Befehl 'Sub ...'" kommen würde. 2.9 Interaktion mit dem Benutzer ---------------------------- Die Funktion Do Show Info [, <Überschrift>] erlaubt die Ausgabe einer Message-Box, erst nach Bestätigung wird das Skript fortgesetzt. Mit Do Show Info "Ein bischen exzessiv gequoted, oder?", "Nur ein Hinweis..." wird z.B. auf ein etwas übertriebenes Zitieren hingewiesen. Akustische Hinweise sind mit Do Play Wave "Troete.wav" möglich. Falls erst nach Abspielen des Wavs weitergemacht werden soll, muß einfach "and wait" angehängt werden: Do Play Wave "Troete.wav" and wait Um auf Benutzereingaben zu reagieren, ist zum einen folgendes nutzbar: If Ask ( [, <Überschrift]) then ... Beispiel: If Not HasSig If Ask ('Soll noch eine Zufallssig an "'+Header(Subject)+'" gehängt werden?', 'Sig-loses Posting!') Set Sig from "ManySigs.txt" endif endif oder If .... If Ask ("Das Posting sollte so nicht abgeschickt werden, Endung auf 'not' ändern?") Set Option DontChangeRenameToExtension = not endif endif oder auch die "dringendere" Variante mit umgekehrtem Vorzeichen: If Abort ( [, <Überschrift]) then ... Beispiel: If HasSig If Not Abort('Die bestehende Signatur wird jetzt überschrieben...') Set Sig from "ManySigs.txt" endif endif oder If Abort('Skript fortführen', 'Experimentelle Header') then Quit Die Eingabe von Texten mittels "Input" wurde bereits unter String-Funktionen erwähnt, eine Beispielanwendung wäre: If Header(newsgroups) ends with ".0d" then Set Header Newsgroups: %Input(Header(Subject), 'Gruppe korrigieren?', Header(newsgroups))% endif Hier hat der Benutzer noch die Möglichkeit, ein versehentlich in de.alt.0d gesendetes Posting noch in eine sinnvollere Gruppe umzuleiten. 2.10 Sonderbefehle ------------- Folgende Befehle passen nicht in die bisherigen Menüpunkte und sind somit hier gesammlt aufgeführt: Do ( Exec | Run ) [ and wait ] [ , ] Hiermit können externe Programme synchron (das Skript pausiert bis zum Programmende) oder asynchron (das Skript läuft parallel weiter) aufgerufen werden, wobei zusätzlich noch Parameter übergeben werden dürfen: Do Run "Notepad.exe", "header.def" würde z.B. die "header.def" in den Editor laden. Als dritter Parameter kann der Windows-Aufrufmodus geändert werden, die möglichen Werte stehen in der Gesamt- übersicht am Ende und entsprechen den internen Namen von Windows. Do ( Open | Print ) ist ein Spezialfall, der das angegebene Dokument asynchron mit der zugehörigen Anwendung öffnet bzw. druckt, sofern entsprechende Verknüpfungen in Windows definiert sind. Do Sort Header , , ... erlaubt die Sortierung der Header nach dem eigenen Geschmack. Do Sort Header Newsgroups, FollowUp-To, From, Reply-To würde dafür sorgen, daß die genannten Header als erste kommen - wobei nicht existente Header schlicht ignoriert werden - und die restlichen Header darunter in ihrer Originalreihenfolge stehen bleiben. Do Repair OEQuoting entspricht der Konfigurationsoption "Kammquoting reparieren", kann aber natürlich im Gegensatz zur Option auch bedingt genutzt werden: If Lower(Header(X-Newsreader)) contains "outlook" then Do Repair OEQuoting ruft die Funktion nur dann auf, wenn der entsprechende Headereintrag auf OE hinweist. Do Write IniStr Datei, Abschnitt, Key, Wert ist die Gegenfunktion zu ReadIniStr und erlaubt das Setzen von Werten in einer INI-Datei. Do Write Textfile Datei, String schreibt den String (der im Falle einer Variable o.ä. durchaus mehrzeilig sein kann) in die angegebene Textdatei, eine eventuell schon vorhandene Datei wird dabei überschrieben. Do Convert BoxQuotes Nummer führt gezielt eine bestimmte BoxQuote-Definition aus. Delete empty Lines at end löscht Leerzeilen am Postingende. Delete Blanks at end of lines löscht Leerzeichen an Zeilenenden, sofern kein Sig-Trenner. Do Convert Header to 8Bit dekodiert alle Header in 8-Bit, aber ist ausschliesslich für empfangende Mails bzw. CopyIf und Reader ohne MIME-Support sinnvoll, ausgehende Postings und Mails dürfen nicht mit 8-Bit-Headern rausgeschickt werden! Do Convert Encoding to [ qp | 8bit | base64 | 7bit ] Konvertiert den aktuellen MIME-Part in die gewünschte Kodierung. Do Convert HTML to Text konvertiert HTML in Text, eine doppelte Anwendung ist nicht empfehlenswert. Do Convert OEBeginBug verhindert ggf. die Erkennung von angeblichen Attachments bei OE. Do Optimize BodyCharset sucht den kleinstmöglichen Zeichensatz für den aktuellen MIME-Part und setzt die MIME-Header entsprechend. Do Optimize Bodycharsets sucht für allen MIME-Parts den kleinstmöglichen Zeichensatz und setzt die MIME-Header entsprechend. Do Optimize MIMEHeader kodiert Header mit 8-Bit-Zeichen und optimiert ggf. MIME-Kodierungen, um die Erkennung durch andere Reader zu optimieren. 2.11 Debugging --------- Wenn Korrnews auf "Stop" stößt, erscheint (fast) derselbe Dialog wie bei Fehlern, welcher es erlaubt, aktuelle Variablenwerte u.ä. einzusehen. Falls Only_KN verwendet wird, ist die Stop-Anweisung unzulässig. 2.12 Multi-Part-Postings/Mails ------------------------- Für die Verwaltung von MIME-Multi-Part-Postings sind nur wenige Befehle nötig, da alle anderen Anweisungen automatisch mit dem gerade eingestellten MIME-Part arbeiten. Do Select Part Nummer aktiviert den entsprechenden MIME-Part, mittels der numerischen Funktion PartCount läßt sich die Anzahl der MIME-Parts feststellen, mit Do Save Part [, [, ( Rename | overwrite | Nothing ) ] ] läßt sich ein MIME-Part als externe Datei speichern, wobei das Original durch einen Link zur erzeugten Datei ersetzt wird. Die letzten beiden Parameter sind optional und werden bei Fehlen durch die Einstellungen der aktuellen Konfiguration bestimmt. Der letzte Parameter gibt die Reaktion darauf an, wenn bereits eine Datei mit dem angegebenen Namen existiert und der Name auch keinen Joker (*) enthält: If PartType is video and Partfilename > "" Do Save Part Partfilename, "c:\Anhaenge\video\", Overwrite endif speichert alle Attachments vom Typ video/irgenwas im passenden Pfad, wobei gleich- namige Dateien sich automatisch überschreiben sollen. Mit Delete part because läßt sich ein MIME-Part löschen, der Text erscheint dann als Ersatz für den originalen Inhalt und ist als Begründung für die Löschung gedacht. Eine Beispielnutzung bzgl. Multi-Part-Postings/Mails sähe so aus: For %Part% = 1 to PartCount Do Select Part Val(%Part%) If Partencoding is qp then Do Convert Encoding to 8bit If Parttype is html then Do Convert HTML to Text If PartType is binary Do Save Part "c:\tmp\", PartFileName, false endif If PartType is plaintext Gosub Standardbehandlung endif Next Quit Sub Standardbehandlung ... end sub Die Überprüfung des Parttype ist im Zusammenhang mit MIMEParts extrem empfehlens- wert, da z.B. die Umkodierung von Base64 nach 8Bit im Zusammenhang mit Attachments zum Verlust des Inhalts durch enthaltene Null-Bytes führen kann. 3. Syntax ~~~~~~ Die Header.def ist zeilenweise organisiert, somit muß zwischen Block- strukturen, die sich über mehrere Zeilen erstrecken, und "normalen" Anweisungen unterschieden werden. Es gibt folgende Blockstrukturen: Sub [ "(" [ Var ] [ : | ... endsub For = to [ Step ] | ... Next If [then] | ... else if | ... else | ... endif ( Set | Append ) ( Intro[duction] | Lines | Sig[nature] [ # ] ) ... end ( Set | Append ) raw ( Intro[duction] | Lines | Sig[nature] [ # ] ) ... end Set [raw] Macro ... end Set [raw] Header Headername: ... ... end Set [raw] %Variablenname% ... ... end Folgende Sonderfälle gibt es noch: Do Include Diese Anweisung wird ausserhalb des normalen Ablaufs ausgeführt, somit führen Zugriffe auf Variablen automatisch zu Fehlern. :Label Labels dürfen nicht innerhalb von If-Blöcken/Anweisungen plaziert werden, da im ersten Fall die Anzahl der Endifs nicht mehr stimmen dürfte und im zweiten Fall der Label nicht gefunden wird. "Normale" Anweisungen können ggf. auch über mehrere Zeilen gehen, wenn sie jeweils mit einem "_" abgeschlossen werden, was vor allem bei längeren Bedingungen ganz gut nutzbar ist, intern werden sie zu einer großen Zeile zusammengesetzt und wie eine normale Zeile behandelt. Die einzelnen Elemente sind so definiert: Anweisung := ( Do Select Part | Delete part because | Do Save Part [ , [ , ( Nothing | Rename | Overwrite ) ] ] | [Set Header] ( = | : ) ( ) | Set [raw] HeaderContent ( from | = ) | Set Header from | Var ( local | global ) (, ...) : [ = ] [, ... ] | Set = | Set from | ( Set | Append ) [raw] H[eader] ( = | : ) ) | Delete Header | Do Sort Header , , ... | Delete BodyHeader | ( Set | Append ) [raw] ( Intro[duction] | Line[s] ) = | ( Set | Append ) [raw] ( Intro[duction] | Line[s] ) from | ( Set | Append ) [raw] Sig[nature] [ # ] = | ( Set | Append ) [raw] Sig[nature] [ # ] from | Delete ( Intro[duction] | Line[s] | Sig[nature] ) | Set [raw] Macro ( from | = ) | Do Convert Boxquotes | Do Replace ( first | all | last ) with [ in ( Body | Sig | Lines | Intro | Header | Header2 | ) ] [ from ] [ to ] | Set Bodyline ( from | = ) | Insert Bodyline = | Delete Bodylines from to | Delete Bodyline | Delete between (first|last) , , [, ] | Delete Empty Lines at end | Delete Blanks at end of lines | Do Convert Header to 8Bit | Do Convert Encoding to ( qp | 8bit | base64 | 7bit ) | Do Convert HTML to Text | Do Convert OEBeginBug | Do Convert OEKillFalseReBug | Do Repair OEQuotings | Do Optimize MIMEHeader | Do Optimize BodyCharset | Do Optimize Bodycharsets | Set Opt[ion] = | Do ( Exec | Run ) [ and wait ] [, [, ] ] | Do ( Open | Print ) | Do Write IniStr , , , | Do Write Textfile , | Do Show Info [, ] | Do Play Wave [ and wait ] | Do Include | If then | For = to [ Step ] do | break | cont[inue] | Next | Gosub [ ( | ) [, ...] ] | Return | Goto