Structure of "Header.def" ========================= # 12/22/01; updated 7/06 # translated by Paul Batchie # please send corrections and enhancements to pbpublic (at) gmail.com. -1. Foreword ~~~~~~~ The description of the script language is relevant not only to Korrnews, but also to CopyIf, because both use the same Engine, Practical differences in the linguistic range exist normally when a function applies only to one of the programs. Besides that case, the descriptions are based on Korrnews, Special CopyIf commands are found in the CopyIf.txt. 0. CONTENTS ~~~~~~~~~ 1. General 2. The concrete possibilities 2.1 Defining additional headers, modifying headers or deleting headers 2.2 "Wildcards", Variables, String Functions, Numeric Functions 2.3 Bodyheader use/delete 2.4 Introductions, Lines & Signatures 2.5 Text-Body processes 2.6 Changing options 2.7 IF conditions 2.8 Flow Control (Gosub, Goto, For/Next, Quit, Do Include) 2.9 Interaction with the User 2.10 Special Commands 2.11 Debugging 2.12 Multi-Part-Postings/Mails 3. Syntax 1. GENERAL ~~~~~~~ The exact name of the Header.def file can be changed in the options, but the file must be in the "Workpath", with the default being the Korrnews directory. The analysis of the Header.Def statements takes place before any "Bodyheader" entry, thus a header can be defined at the start of the text of the body, with "X-Sowieso=Wert" or "@Sowieso=Wert". Comments are allowed, with each line beginning with ";", "#" or ":". Long lines can be spread over several lines by placing a "_" at the end of all but the last line. To clarify the terms used, here is the structure of a Mail or a News: ----------- I. Header II. Body a) BodyHeader b) Introduction c) text d) Lines e) -- {sigdash is "-- " - that is, 'dash, dash, space'} f) Sig ----------- Example: ----------- I. Message-ID: <3375981e.18152730@news.netway.at> Date: Sat, 10 May 1997 16:32:11 GMT newsgroup: de.newusers.questions From: habol@netway.at (Hans Boldrino) ... II. a) X-Homepage: http://home.knuut.de/tgl/ X-Virus: Oh no b) Hello everybody! c) Development of a Newbie At the beginning of February of this year (49), I got caught up to recent times, with an Internet account. But in sequence... d) Greetings and hello! Hans e) -- f) de.* short form for "all de-hierarchies and groups" de.all synonym for "de.*" de.!alt short form for "de.* except de.alt" 2. THE CONCRETE POSSIBILITIES 2.1 DEFINING ADDITIONAL HEADERS, MODIFYING HEADERS OR DELETING HEADERS ------------------------------------------------------------------ The basic function of Header.def consists of easily adding permanent headers to messages by writing the desired entries into the file. As well, the statement Set Header = value is allowed and, for legibility's sake, also recommended. If the header exists, it's current contents are replaced by the new contents, at it's original position. Conversion of 8-bit characters to ISO-8859-1/QP can be done by Korrnews automatically. Unnecessary headers can be deleted by using Delete Header or an empty specification. Example: Set Header X-Newsreader: Forte Agent 32Bit (with Hamster and patches) Set Header X-Homepage = http://www.Ich.bin.toll.de Delete Header X-Mailreader This will replace the X-Newsreader header, insert an X-Homepage header and delete the X-Mailreader header, if it exists. The alternative way looks like this: X-Newsreader: Forte Agent 32Bit (with Hamster and patches) X-Homepage: http://www.Ich.bin.toll.de X-Mailreader: It is sometimes useful to have multi-line headers, such as for "X-Face" headers. These are defined as follows: 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 The indentation is possible because KorrNews checks the depth of the indentation of the first line and adds the same number of blanks to the beginning of all further lines. Basic headers should be unique so there is no possibility to directly set the From-Header. An exception to this would be the "!RCPT TO" header in the distribution headers of Mails. In order to be able to deal with multiple copies of a header, Korrnews considers two cases: - "Delete Header ABC" deletes, as opposed to "ABC:", not only the first, but all copies of the ABC header. - the instruction "Append Header ABC: blah" deletes no existing ABC header, but attaches the new header behind the existing one or - if no ABC header exists - corresponds to a "Set Header ABC: blah" instruction. Meanwhile, for systematic processing the following order are available still: set [raw] HeaderContent = ... supports from the numeric function Headerlines and the Stringfunctions HeaderName (nr), HeaderContent (No) and RawHeaderContent (No). 2.2 "Wildcards", Variables, String Functions, Numeric Functions -------------------------------------------------------------- 2.2.1 "WILDCARDS": Wildcards are always enclosed in percentage signs and permit the use of a header with the setting of another header, a Sig, or the like. One can also use string functions, which will be described later, within Wildcards. Wildcard uses: - settings of headers, among other things - block statements (signatures, macros etc.) In most other cases "String Expressions" are used; they have the same abilities but have, IMHO, a more meaningful syntax. In order not to complicate pure header settings, the Wildcard syntax is still maintained. But now for concrete examples... In order to easily add onto the original x-newsreader-header, the following statement can be used: X-newsreader: %Header(X-Newsreader)% (plus Hamster & Korrnews) or to set an In-Reply-To header for XNews, use the following: X-In-Reply-to: %Last(Header(References))% The individual statements such as Last, Header etc. are described later, but the statement "Header" should be relatively obvious. In order to use "genuine" percentage signs in a Wildcard statement, one can either use "raw" items or, for each percentage sign, use two of them consecutively: Set Header X-Parts-Per-Thousand: must be 25%% per litre! If the String Expressions are used, they can be surrounded with "%" Set Header X-Equal: The author is %Header(From)%, states he! Or one can use the following just as well: Set Header X-Equal: %"The author is " + Header(From) + ", says he!"% 2.2.2 VARIABLES Variables have these additional uses: - Expressions can be longer and used several times with less typing - statuses can be saved in order to be used many times later in If instructions. - strings can be constructed in order to then be assigned to a header. The script language knows the following variable types: String: character strings, length practically arbitrary Integer: whole numbers between approx.-4 billions and 4 billions Float: floating point numbers in double exactness Boolean: Either true or false For compatibility reasons String variables can be declared without special declaration, a simple "set", the delivery as a parameter or the use in a For thread declares them automatically. With the "Var" command Variables are declared, and if necessary also an initial value or the validity can be indicated. To declare a String variable %Subject% and with the Header field "Subject" preselected, type the following: Var %Subject%: String = Header("Subject") One can also declare several variables and even several variables of different types at once: Var %Anz%, %Tr%: Integer, %Sum%, %DS%: Float, %Flag%: Boolean = true If variables are defined within Subs, these are apply only to the execution the Sub and are deleted afterwards automatically. Global variables, however, are not changed. Global variables are all variables invested outside by Subs or also variables in Subs if these are put on with the addition "global": Sub Init Var global %Subject%: String = Header("Hello") Var global %Fup%: String = Header("FollowUp-To") Var global %NGs%: Integer = Count(",", Header(Newsgroups)) + 1 end sub For illustration: Var %Test%: String %Test% = "Hello" Gosub Test Do Show Info %Test% Sub Test Var %Test%: Integer = 42 Do Show Info Str(%Test%) end sub "42" displays first, then "hello". Conversions between the different variable types are possible with corresponding functions (Val, Str, IStr, BoolToStr...), Str is practically always required for the issue of numbers. The normal setting or changing of an existing variable looks so: %Group% = Header(Newsgroups) %Programer% = "Thomas G. Liesner" %Signame% = "This is made by" + Extract("^[^ ]+", %Programer%) + "!" %QuotedLines% = MatchedLines('^>') For compatibility reasons a "set" can be set before it: set %ZitierteZeilen% = MatchedLines (' ^ > ') the use of Wildcards looks so: X-the-programmer: is called of %Programer%! ***These "Wildcard" expressions are usable only in Header assignments and set/end-instructions.*** Apart from that the script language of "normal" computer language corresponds: variables are applied where their type fits or are made fitting by auxiliary functions like Val or Str. A special case for compatibility reasons is For, which accepts String as well as numeric variables. However, correctly interpreting these functions occurs only in connection with conditions. 2.2.3 STRING FUNCTIONS: Conversions: ------------ Lower(...) changes the string to lower case Upper(...) changes the string to upper case DecodeISO(...) changes an ISO-8859-1/QP encoded header into a "normal" string with 8-bit characters. 8BitTo7Bit(...) changes 8-bit characters into the appropriate ASCII codes („ => ae, á => ss,...) DosToWin(...) Changes DOS umlauts (and other special characters) to fitting marks in the Windows font. WinToDos (...) Changes Windows umlauts (and other special characters) to fitting marks in the DOS font. Str(...,...,...) changes the Numerical Expressions transferred as the first parameter into a string. The optional second numeric parameter determines the number of characters. The optional third parameter determines the number of post-decimal places; if absent, 2 places are displayed. IStr(...) changes a Numerical Expressions into a string (without NK places). BoolToStr(Bed.) the result of the transferred condition is converted into a string and thus permits the direct allocation of a condition to a variable. EscRegExp(...) if one uses a header, etc. as a RexExp, one can avoid inadvertent side effects by means of this function, which masks out all special characters ("." => "\.", etc.) Chr(...) changes the specified Numerical Expressions into the corresponding ASCII/ANSI character. FillChar(..., ...) copies the first parameter as often as has been indicated by the second numeric parameter. FillChar ('+ -', 3) would become therefore " + - + - + - ". LTrim (...) All blanks or Tabs removedfrom the front up to the first other mark. RTrim (...) All blanks or Tabs removed from the back up to the first other mark. Trim (...) Combined LTrim and RTrim. String Disassembly / alterations: -------------------------- First(...) extracts the first item of the string. If the string has commas, the section before the first comma (e.g. newsgroup header with Crosspostings) is extracted. If the string begins with "<" and ends with ">", the first "<...>" pair is extracted (e.g. References header). Last(...) extracts the last item of the string, the opposite of "First" Adress(...) works on - like the following two functions - the Mail address in the From or Reply-To header. Adress tries to extract only the actual address, so "Hans Hirni " returns "abc@def.gh" Name(...) tries to extract the complete name, so "Hans Hirni " returns "Hans Hirni" FirstName(...) Tries to extract only the first name, so "Hans Hirni " returns "Hans" MakeAdress(...,...)combines the passed name and Mail address into a From/Reply-To/To compatible Expressions of the form "Name
". Considers special cases in the name (Punkte, Anfhrungsstriche) Extract(...,...) if the first parameter is a Regular Expression (corresponds to the Regular Expression in Hamster) and is found in the second parameter, the appropriate section is returned, otherwise an empty string is returned. Extract("a.*e", "Hallenbau") returns "alle" Left (......) Supplies from the first parameter first x mark back, besides, x stands for the second parameter. Right (......) Supplies from the first parameter last x mark back, besides, x stands for the second parameter. CutLeft(...,...) removes the number of characters indicated by the second parameter from the left of the string passed as the first parameter. CutLeft("Re: Ups", 3) returns "Ups". CutRight(...,...) removes the number of characters indicated by the second parameter from the right of the string passed as the first parameter. CutRight("Re: Ups", 3) returns "Re: ". Line(...,...) the first parameter indicates the line number, the second one contains the text. As a result the wished line is returned, with a nonexistent line number an empty string. The counting begins with 1 and ends with CountLines (String). Replace(...,..,...)replaces in the first parameter all occurences of the second parameter (interpreted as a RexExp!) with the third parameter. WordWrap(...,...,...)Supplies if necessary the broken first parameter back. The second numeric parameter returns the maximally allowed number of lines, the third parameter indicates the entry to be applied to the second line (as a String). Posting specific: ----------------- Header(...) supplies the value of the indicated header HeaderName(Nr) demanded about his(its) name (No) supplies the name of the Headers HeaderContent(Nr) demanded about his(its) position (No) supplies the content of the Headers RawHeaderContent(Nr)demanded about his(its) position (No) supplies the if necessary still coded content of the Headers demanded about his(its) position BodyHeader(...) supplies the value of the indicated BodyHeaders, see next point. Full [raw] Header [without Headername1, ...] without parameters and at present only meaningful in certain conditions, returns the entire Headers as a character string. In order to exclude certain headers, the "without" specification can be used. Full [raw] Body without parameters and at present only meaningful in certain conditions, returns the entire Textbody, up to the signature, as a character string. Full [raw] Sig[nature] without parameters and at present only meaningful in certain conditions, returns the complete Signature as a character string. Full Article/Posting/Mail supplies the entire text in "raw" format as a string Filename supplies the filenames of the up-to-date processed postings Path supplies the path in which Korrnews looks for postings Bodyline(...) supplies contents of the xth line of the Textbody; a number or a numerical expression must be supplied as parameters. Available lines do not return the delivery of an empty string. External data: -------------- ReadIniStr() reads the section, keys and a default value (used if the key does not exist) from the INI file passed as a parameter. GetDateTime(...) permits selecting the current time or the current date. The following substitute symbols are permitted in the format string: "yy" or "yyyy" is for year, "m", "mm" for month, "d", "dd" for day, "h", "hh" for hour, "n", "nn" for minute, "ss", "s" for seconds and "hh", "h" for 100ths of seconds. c indicates the date in the short format of the Windows settings and the time in the long format of the Windows settings. D indicates the day as a number without leading zero (1-31). dd indicates the day as a number with leading zero (1-31). ddd indicates the day as an abbreviation and applies, besides, for the choice of the abbreviations the Windows settings. dddd indicates the day as an entire(complete) name, also here the current Windows settings are used. ddddd indicates the date in the short format of the Windows settings. dddddd indicates the date in the long format of the Windows settings. m indicates the month as a number without leading zero (1-12). Follows Bezeichner m directly according to the information h or hh, if the minute is indicated instead of the month. mm indicates the month as a number with leading zero (01-12). If the Bezeichner mm follows directly according to the information h or hh, the minute is indicated instead of the month. mmm indicates the month as an abbreviation and applies, besides, the Windows settings for the Bezeichner. mmmm Indicates the month as an entire(complete) name and applies, besides, the Windows settings for the Bezeichner. yy the year indicates as a two-digit number (00-99). yyyy indicates the year as a four-digit number (0000-9999). h indicates the hour without leading zero (0-23). hh indicates the hour with leading zero (00-23). n indicates the minute without leading zero (0-59). nn indicates the minute with leading zero (00-59). s indicates the second without leading zero (0-59). ss indicates the second with leading zero (00-59). z indicates the Millisecond without leading zeros (0-999). zzz indicates the Millisecond with leading zeros (000-999). t indicates the time in the short format of the Windows settings. tt indicates the time in the long format of the Windows settings. am/pm To applied the 12-hours format for the leading Bezeichner h or hh and points 'am' for times before 12 o'clock noon or 'pm' for times after 12 o'clock noon. The Bezeichner am/pm can be indicated in large or small or mixed font and is indicated accordingly. a/p applied the 12-hours format for the leading Bezeichner h or hh and indicates 'a' for times before 12 o'clock at noon or 'p' for times after 12 o'clock at noon. The Bezeichner a/p can be indicated in large or small or mixed font and is indicated accordingly. ampm applied the 12-hours format for the leading Bezeichner h or hh and points instead of to the contractions been careful in the Windows settings. / If the date separator been careful in the Windows settings applies. : if the time separator vorgeshene in the Windows settings Applies. 'xx'/"xx" in half or whole quotation marks included marks do not have an effect on the formatting and are indicated as given. Example: GetDateTime("dd.mm.yyyy") on 1.4.2000 => "01.04.2000" Constants: ---------- CRLF corresponds to a Carriage-Return TAB corresponds to a TAB SigDel corresponds to a sigdash: "-- " User inputs: ------------ Input (.,.,.) permits the input of a string by input box. The parameters that must be passed are the dialog title, a request for input and a variable name. Other: ------ Version returns the current version number; functions only starting from V2.86 2.2.4 NUMERIC FUNCTIONS: Additional commands can be described using string functions and numeric parameters. These can be quite complex. Naturally, pure constants can be used: Delete Bodylines from 10 to 20 As can calculations: If Bodylines > 0 then Do show Info ('Average Characters per Line: ' + _ Str( Len( Full Body ) / Bodylines , 5, 2 ) And naturally numerical variables: Var %SubjLen%: Integer = Len(header(Subject)) If %SubjLen% > 100 then Do Show Info "A bisserl langer Betreff..." Calculations can be the basic operations of arithmetic, brackets, the normal arithmetic functions mentioned in the syntax, the power function (^) and the following auxiliary functions: Count (String, String) returns the number of occurrences of the first string in the second string. Ord (String) returns the ASCII value of the first mark of the Strings, 0 with an empty String. Pos (String, String) gives the position of the first string in the second; 0, if the String it is not found. Len [gth] (String) Gives the length of a Strings Val (String) Changes a String Expression to a number, for formulae work. Trunc (number) returns the number without post-comma places. Random (number) returns a ganzzahlige chance number between 0 and 1. Mail/News-specific functions: ============================= PartCount If returns the number of the MIMEpart, for a normal Posting the return value is 1. MatchedLines (RegExp) returns the number of lines which contain the indicated RegExp. Bodylines returns the number of lines in the Textbody. Headerlines returns the number of lines in the Header. Siglines returns the number of lines in the Signature. Introlines returns the number of lines in the Intro. CountLines (String) returns the number of lines in the handed over String NextMatchedLine (number, RexExp) returns the first line number in which the RegExp is found, it is searched from the line number handed over as the first parameter. 2.3. BODYHEADER USE/DELETE --------------------- Bodyheaders are pseudo-headers defined in the Body of the posting. After Korrnews has processed Header.def, it automatically transfers any Bodyheaders into actual headers and then deletes them from the Body. There are quite a range of applications for them within Header.def. Settings using a Bodyheader within the Wildcard form %BodyHeader(Bezeichnung)% are attainable and thus both variables and "correct" Header can be set. In addition, the main use might be the possibility of controlling Header.def. A small example using the If instruction will hopefully make things clearer: 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 This block works on a set Bodyheader named "Fup" and sets "FollowUp-To" according to the headers and completes, if necessary, the "Newsgroups" header for the current group. In order to have Bodyheader be only a temporary function and not really be posted, the statement Delete Bodyheader prevents the usual transfer into an actual header from taking place. 2.4 INTRODUCTIONS, LINES & SIGNATURES --------------------------------- - Introductions are lines which are inserted at the beginning of the posting, - Lines are lines that are to be inserted between text and signature or to be added to the end of the text - and the signature is a text block inserted at the end of the posting, which is visuaally separated from the text by means of the switch ("-- "). The syntax is alike in all cases, with a special feature that affects only the signature: when adding, Korrnews automatically checks to see if several signatures are contained either in the message or the signature file (by testing SigTrenner including Sigtrenner without blanks) and - if more than one exists - selects one randomly. When adding, there are two basic alternatives: New setting or attaching. Which alternative is used depends on whether the "Set" or "Append" statement is used in the call. As well, there are three ways of transferring contents: in the Header.def as a block: ( Set | Append ) [raw] (Sig[nature] | Line[s] | Introduction ) line #1 line #2 line #3 line #4 end Examples: If Header(Newsgroups) contains "test" set Intro ignore - noreply - ignore end endif Set Sig name: Unknown age: I have greeting: Tschuess end in the Header.def as single lines: Set Signature = "my signature is brief" Append Sig = "(or maybe not?)" or from an external file, so that in Header.def there is only a reference: Set Sig from "sigs.txt" Set Lines from "greeting.txt" If the Sig file or the Sig block contains "--" lines, Korrnews interprets this to mean that several Sigs are contained there. Under normal conditions, Korrnews will randomly pick one. In order to use a specific Sig, the following syntax is used: Set Sig #12 from "many_sigs.txt" or If BodyHeader(X-Sigfile) > "" Set Sig # Val("0"+BodyHeader(X-SigNr)) from Bodyheader(X-Sigfile) endif The second case will - if the Bodyheader X-Sigfile was set - analyze a possibly set Bodyheader X-SigNr, set a zero in front of it so that a missing Bodyheader does not cause an error, and converts the Zusammengesetze into a number. With X-Sigfile: jokes.txt X-SigNr: 3 at the start of a Posting, the third signature from "jokes.txt" is attached to the Posting by Korrnews. Please keep in mind the netiquette limit of 4 lines of 80 characters per line maximum per individual signature. By the way, Korrnews makes sure that Lines, Intros and Sigs are not repeated several times by comparing the respective lines with the text which can be used and making with identity no modifications. With Delete Sig Delete Intro Delete Lines additions can be taken back. For queries there is "HasSig" and for special comparisons there are ChangedSig, ChangedIntro, ChangedLines and Siglines and Introlines, if one wants to know the number of lines in the message. 2.5 TEXT-BODY PROCESSES ----------------- There are two instructions for modifying the actual text: Do Replace ( first | last | all ) with [ in ( Body | Lines | Sig | Intro ) ] _ [ from ] [ to ] Thus modificatons can be done directly in the text. The search string is a regular string as often is found in Hamster. Example: With Do Replace first ":" to "Frank Mueller wrote in :". In order to limit the area, the first and/or last lines to be examined can be specified - for QP coded texts, section lines are not counted as part of the text. If the Textbody is not to be searched, the search can also be done on Lines, Signature or the up-to-date adjusted introduction block: Set Sig # This was set with Korrnews # not a bad # way to go # !! end Do Replace all "^#" with "" in Sig A special case is still "Do Replace ... in %Variable%": with this version, specifying the first/last setting in a variable is possible, which is not feasible with the string function Replace. However, the from/to specification is not considered. A similar function is the instruction: Set macro ... end If one wanted to have, for example, an automatic greeting, one can use the following: Set macro "#greeting#" Touche', to you Paul! end If then in the Posting War's actually here already. #greeting# occurs, the above instructions change it to: War's actually already. Touche', to you Paul! (Note: macro token must be at start of line) Another obvious macro would be #spoiler#. One should be sure to make certain that inadvertent replacements do not occur, since the selected macro name could also occur alone in a line. For special cases there is: Set Bodyline(LineNum) = ... for modifying lines; Delete Bodylines xx to xx or Delete Bodyline xx to delete certain lines, and Insert Bodyline LineNum = ... to insert individual lines. Delete between ( first | last ) , , [, ] deletes the first or last text block, whose initial line corresponds to the first, and final line to the second, RegExp string. If the first search string is empty and is the first suitable text block to be deleted, everything up to the second RegExp will be deleted. If the second search string is empty and is the last suitable text block to be deleted, everything starting from the first RegExp is deleted. The condition determines whether the beginning and final line of the block is also to be deleted, and the optional last String Expression is inserted in place of the replaced string. This function is useful, for example, to remove advertising blocks from mailing lists. 2.6 CHANGING OPTIONS ---------------- With the instruction Set Option Designation = "Value" the INI options for the current Korrnews run be temporarly (!) modified at any time. However, permanent modifications are not possible in this manner, thus contrary to "Do Write IniStr". If, for example, one normally uses a signature file but doesn't want to use it in a certain group, one would use the following statement: Set Option SigFile = The names of the options are listed both in the HTML help file and also in the Korrnews.ini file. Note: the names of the options can change in future versions of Korrnews. In principle I am for consistancy, but there are no guarantees. 2.7 IF CONDITIONS ------------- In order to offer more flexibility, it is possible to make lines dependant upon conditions. The basic form is: If [then] ... [else if ...] [else ...] endif The Else-If and Else branches are optional and it is recommeded that any "..." statements begin with indentations, for the sake of clarity. IF conditions can also be nested, with up to 15 levels permitted. The is also a short version, if one only need to execute one instruction: If then Here are some concrete examples: Fix the Agent bug of not putting quotation marks around the name in From: If Header "From" equals "Thomas G. Liesner " From: "Thomas G. Liesner" endif changes: From: Thomas G. Liesner to: From: "Thomas G. Liesner" Unnecessary Reply-To delete: If Header(From) contains Header(Reply-To) Delete Header Reply-To endif Set a special Reply-To in test groups: If header "newsgroup" contains "test" ; input own FQDN for please. Reply-To=botanswer@ endif Deletes specified BodyHeader only if used: If BodyHeader "HeaderOk" Is Empty ... else ; Tracks smear Delete BodyHeader HeaderOk endif Set group-dependent Reply-To: ; Only if it has the correct Mail address: If Lower(Header(From)) contains Lower("TGL") If Not Header "Newsgroups" is empty ;input own FQDN for please. Reply-To=Answer.from.%First(Header(Newsgroups))@ else Reply-To=Mailanswer@ endif endif Avoid storage in google.com for certain groups: Set %NG% = Header(Newsgroups) If ("dear ATS" IN %NG%) or (%NG% contains "sex") then X-No-Archive: Yes Post particularly safety-consciously in certain groups: If Header(Newsgroups) = "de.soc.zensur" X-No-Archive: Yes X-PGP: ... endif in some groups use the dnq project Sig: 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 If the FollowUp-To is set, insert a note above the Sig: Note above the Sig, if one set FollowUp-To: If Header "FollowUp-To" > "" If Header "Newsgroups" contains "," Set Lines X-Post to %Str(Count(',', Header(Newsgroups)))% groups, FollowUp-To %Header(FollowUp-To)% end else Set Lines FollowUp-To %Header(FollowUp-To)% end endif endif 2.7.2 Boolean Functions The complete outline is in the description of syntax at the end, but here is a list of the boolean special functions: Constant -------- True is for "Yes"/"True". False is for "No"/"False". Posting specific -------------------- HasSig[nature] returns "True" if a signature exists or was attached by script. Has8BitChars returns "True" if in the Posting there seems to be characters with the 8th bit set, like umlauts, etc. Part type is Supplies the "True" if the type of the current MIMEpart is like the . For the following Bezeichner are allowed: Unknown, text, Plaintext, UnknownText, HTML, Binary, Application, audio, image, video. PartEncoding is Supplies the "True" if the Encoding of the current MIMEpart is like the . For the following Bezeichner are allowed: quoted-printable, qp, 8 bits, 8 bits, 8 bits, base64, ascii, 7 bits, 7 bits, 7 bits, unknown. Status queries -------------- Changed returns "True" if past scripts caused major modifications of the Posting. ChangedLines returns "True" if attached lines were defined by "Set/Append Lines". ChangedSig[nature] returns "True" if Sig statements were executed. ChangedIntro[duction] returns "True" if the introduction was set by "Set/Append Intro". VarExists (variable name) returns "True" if the variable has been put on. User response ------------- Ask (..., ...) returns "True" if the user acknowledges the yes-button of the displayed Messagebox. The parameter is the text which will be used as the title of the Messagebox. Abort (..., ...) returns "True" if the user acknowledges the abort-button of the displayed Messagebox. The parameter is the text which will be used as the title of the Messagebox. Other --------- FileExists (...) Tests whether the given(indicated) file name exists. Provided that no path is given(indicated), KN tests in the current catalogue. Conversion ---------- StrToBool converts a string into a boolean value and permits the Yes/No value to be used as a variable again in a condition by means of "BootToStr". 2.8 FLOW CONTROL (GOSUB, GOTO, FOR/NEXT, QUIT, DO INCLUDE) ------------------------------------------------------ Use the following statement in order to store a function module externally: Do Include This statement is executed while loading the script file, so one could also use the function: Set Sig Do Include "sigs.txt" end The contents of the file are treated exactly the same as though they were originally in the script. The file name - if no absolute path is indicated - is relative to the work directory. With Gosub it is possible to branch into the specified "Sub". Example: Gosub Name Gosub Name Quit Sub Name ... endsub Sub Name2 ... endsub In order to be able to use parameters, the following syntax can be used: After Gosub Combine "This and", "that", %Temp% Gosub Combine %Temp%, " - that is all", %Temp% Sub Combine (%one%, %two%, Var %Summary%) Set %Summary% = %one% + " " + %two% endsub the value "This and that - that is all" will be in the variable %Temp%. The "Var" permits modifying an existing variable. String functions or variables and constants are permitted as non-Var parameters. There are two versions of the For / Next statement that can be used to execute an instruction several times: For %i% = 1 to 10 .... Next and For %i% = 1 to 10 do ... The first and final values can be calculations or variables (accessed by "Val(%Variable%)") and with "Step", the increment can be selected at will: For %Countdown% = 10 to 1 step -1 ... Next The variable must be from the integer, Float or String types, the latter is in there for compatibility reasons. Should the variable not have been defined before by "Var", she is declared as a String variable. The While/Wend statement which will not run through if necessary at all if the condition is not fulfilled from the beginning: While ... Wend Turn the Repeat/Until statement which has at least a run, because the condition is tested only at the end. With fulfillment of the condition the thread breaks off: Repeat ... Until And the loop which does only in connection with a demolition order sense: Endless ... If then ... Loop As instructions stand Goto - which can leave if necessary also several threads suddenly-, continue (which might not be very meaningful with this thread, however) and break to the disposal: ; From "@" "at" do 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% ; check Only own text... Var %i%: Integer For %i% = 1 to Bodylines If Bodyline(%i%) begins with ">" then Continue ... Next Repeat :MainThread ... While ... ... For ... ... If ... then Goto MainThread If ... then Goto NotHere... Next ... Wend ... Until ... :NotHere Goto can be also applied outside by threads to jump over certain parts, however, normally the renunciation of Goto leads to more readable scripts. The jump aims of Goto must be introduced with a colon and should be in each case unique, because KN would jump apart from that always on the first fitting label. Loops can naturally also be stacked, however the extensive use of loops is not recommended for simple reasons of performance, since interpretation of the script language is not as fast as a genuine programming language. The instruction "Quit" terminates the script and is necessary when using Subs, since otherwise the error message "unknown quantities instruction 'Sub...'" would be generated. 2.9 INTERACTION WITH THE USER ------------------------- The function Do Show Info [, ] permits output to a Message box, with the script continuing only after acknowledgement. With Do Show Info "A bit excessively quoted, oder?", "Nur ein Hinweis..." for example, one can refer to somewhat excessive quoting. Audio alerts can be made with: Do Play Wave "trouble.wav" If processing should be continued only after playing the Wav, it can simply be suspended with: Do Play Wave "trouble.wav" and wait In order to react to user inputs, the following can be used: If Ask ( [, [, [ , ] can be used to call external programs that run synchronously (the script pauses until the called program ends) or asynchronously (the script continues to run parallel to the called program), and any needed parameters may be passed. Thus: Do Run "Notepad.exe", "header.def" would load "header.def" into Notepad. Do ( Open | Print ) is a special case, which opens or prints the indicated document asynchronously with the appropriate application, if the appropriate associations are defined in Windows. Do Sort Header , , ... permits sorting headers to your own taste. Do Sort Header Newsgroups, FollowUp-To, From, Reply-To would ensure that the headers mentioned come first - non-existent headers are simply ignored - with the remaining headers following them in their original order. Do Repair OEQuoting corresponds to the configuration option "Kammquoting repair", and can naturally be used conditionally in contrast to the option: If Lower(Header(X-Newsreader)) contains "outlook" then Do Repair OEQuoting the function is called only if the appropriate header entry refers to OE. Do Write IniStr file, Paragraph, Key, Value is the opposite of ReadIniStr and permits the setting of values in an INI file. Do Write text file file, String writes the String (which can be absolutely consisting of several lines in case of a variable o.ä.) in the given(indicated) text file, besides, a possibly already existing file is headed. Do Convert BoxQuotes number implements aimed a certain box ratio-definition. Delete empty Lines at end removes blank lines at the end of the post. Delete Blanks at final of Lines deletes blank spaces at the line ends, provided that no Sig-Trenner. Do Convert Header to 8 bit decodes all Header in 8 bits, but is meaningful exclusively for receiving mails or CopyIf and Reader without MIME Support, going out Postings and mails may not become with 8-bit Headern rausgeschickt! Do Convert Encoding to [qp | 8 bits | base64 | 7 bit] converts the current MIMEpart in the wished coding. Do Convert HTML to text converts HTML in text, a double application is not recommended. Do Convert OEBeginBug prevents if necessary the recognition of alleged Attachments with OE. Do Optimize BodyCharset searches for the smallest possible font for the current MIMEpart and sets the MIME Header correspondingly. Do Optimize Bodycharset searches for the smallest possible font for all MIME-part and sets the MIME Header correspondingly. Do Optimize MIMEHeader codes Header with 8-bit mark and optimizes if necessary MIMEcodings to optimize the recognition by other Reader. 2.11 DEBUGGING --------- If Korrnews bumps with "stop", (almost) the same dialogue appears as with mistakes which it allows to see current variable values u.ä. If Only_KN is applied, the stop instruction is inadmissible. 2.12 Multi-Part-Postings/mails ------------------------- For the administration of MIME-MULTI-PART-POSTINGS only few commands are necessary, because all other instructions automatically work with the just opposed MIME part. Do Select Part Activates the corresponding MIME part, by means of the numeric function PartCount The number of the MIME part can be saved. With Do Save Part [, [, (Rename | overwrite | Nothing)]] a MIME part can be stored as an external file and the original is replaced with a link to the produced file. The last two parameters are optional and in their absence the default is determined by the settings of the current configuration. The last parameter indicates the reaction if a file with the indicated name already exists and the name also contains no wildcard (*): If PartType is video and Partfilename > "" Do Save Part Partfilename, " c:\Anhaenge\video\", Overwrite endif If all Attachments of the type video / irgenwas are stored in the fitting path, files of the same name should automatically overwrite themselves. With Delete part because a MIME part can be deleted, then the text appears as a substitute to the original content and is meant as a reason for the deletion. An example use bzgl. Multi-Part-Postings/mails it looks like: 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 Partfilename, " c:\tmp\", false endif If PartType is plaintext Gosub standardtreatment endif Next Quit Sub standardtreatment ... end sub The examination of the Parttype is strongly recommended in connection with MIME PART, because, e.g., Base64 coding after 8bit can lead to the loss of the content by contained zero bytes in connection with Attachments. 3. SYNTAX ~~~~~~ Header.def is organized line by line, so there must be a way to differentiate between block structures, which extend over several lines, and "normal" statements. There are the following block structures: Sub | ... 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 There are also the following special cases: Do Include this statement executed outside of the normal operational sequence, thus cause accesses to variables automatically errors. :Label Labels may not be placed within If-Blocks/Statements, firstly because the number of Endif's may no longer be right and secondly because the label may not be found. "normal" statements can, if necessary, extend over several lines, which is particularly useful with longer conditions, by ending each line with a "_"; such lines are then internally joined into one large line and then treated like a normal line. The individual items are so defined: Statement := ( Do Select Part | Delete part because | Do Save Part [ , [ , ( Nothing | Rename | Overwrite ) ] ] | [Set Header]
( = | : ) ( ) | Set Header
from | 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 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 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 Boxquotes | 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 Show Info [, ] | Do Play Wave [ and wait ] | Do Include | If then | For = to [ Step ] do | break | Gosub [ ( | ) [, ...] ] | Return | Goto