Announcement

Collapse
No announcement yet.

DLL statt aspx im IIS Starten?

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • DLL statt aspx im IIS Starten?

    Hallo zusammen,

    ich habe eine bisschen wirre frage

    es geht um folgendes.
    Ich bin gerade an einer Applikation am vorbereiten und mir stellt sich eine frage die mir wichtig ist.

    Diese Applikation besteht aus 2 elementen, zum einten die ausführende applikation, die die Webseiten darstellt und eine Administrator applikation, um die erste Applikation zu verwalten.

    ich möchte aber bei der Admin applikation keine aspx seiten erstellen sondern alles per code generieren lassen.
    Eventuell auch die erste Applikation.

    Ist es möglich direkt im IIS die DLL zu starten, die alle seiten beinhaltet die generiert werden sollen nach dem aufruf?
    Bsp: http://www.domain.com/admin soll die dll aufrufen. Oder http://www.domain.com soll die Applikation aufrufen.

    sicher fragt ihr euch wobei der sinn dahinter liegt? Es wird so sein das die Administration vielmals verbessert und ausgeweitet wird und ich danach nur noch die DLL zur verfügen stellen möchte damit die Benutzer keine änderungen an den seiten machen können, und damit ich nur noch die dll updaten muss.

    Ich habe das schon bei einer Applikation gesehen, nur war diese DLL in C++ geschrieben und nicht mit C# und ich möchte einfach wissen ob und wie es möglich ist.

    Gruss Andreas

  • #2
    Hallo,

    ja das ist möglich. Dazu muss die DLL allerdings als klassiche DLL die vom IIS von einer ISAPI-DLL erwarteten exportierten Funktionen implementieren: <br>
    a) GetExtensionVersion <br>
    b) HttpExtensionProc

    Weil aber eine derartige Umsetzung in C# keinen Sinn macht, kann ich nur mit einem Delphi-Beispiel dienen:
    <pre>
    <font color="#003399"><i>{ ************************************************** **************
    Source File Name : SQLDB.DPR
    Typ : DLL-Projekt (ISAPI)
    Autor : Andreas Kosch
    Erstellt am : 01.06.98
    Compiler : Delphi 3.02
    Betriebssystem : Windows 95
    Beschreibung : Generisches ISAPI-Modul für den Datenbank-
    zugriff auf die SQLBase-Newsgroup-Datenbank.
    Revisionen : -
    ************************************************** ************** }</i></font>

    <b>library</b> SQLDB;

    <b>uses</b>
    Windows, SysUtils, ISAPI, IniFiles, DB, DBTables, Classes;

    <font color="#003399"><i>{ exportierte ISAPI-Funktion GetExtensionVersion }</i></font>

    <b>function</b> GetExtensionVersion(<b>var</b> Ver: THSE_VERSION_INFO): BOOL; <b>stdcall</b>;
    <b>begin</b>
    Ver.dwExtensionVersion := $00010000; <font color="#003399"><i>// 1.0 support</i></font>
    Ver.lpszExtensionDesc := <font color="#9933CC">'Delphi 3.02 ISAPI DLL'</font>; <font color="#003399"><i>// Description</i></font>
    Result := True;
    <b>end</b> ;

    <font color="#003399"><i>{ exportierte ISAPI-Funktion HttpExtensionProc muß threadsicher sein,
    d.h. es sind keine globalen Variablen für Daten zulässig. Daher wird
    alles über den für jeden Thread separt gültigen Stack erledigt. }</i></font>

    <b>function</b> HttpExtensionProc(<b>var</b> ECB: TEXTENSION_CONTROL_BLOCK): DWORD; <b>stdcall</b>;
    <b>var</b>
    Data : AnsiString;
    IniFile : <b>String</b>; <font color="#003399"><i>// Pfad wird aus Alias-Verzeichnis ermittelt</i></font>

    <font color="#003399"><i>{ Daten der zugeordneten Tabellenspalte auslesen }</i></font>

    <b>function</b> Value(<b>const</b> Field: ShortString): ShortString;
    <b>var</b>
    i: Integer;
    len: Byte absolute Result;
    <b>begin</b>
    Len := 0;
    i := Pos(<font color="#9933CC">'&amp;'</font> + Field + <font color="#9933CC">'='</font>,Data);
    <b>if</b> i = 0 <b>then</b> <b>begin</b>
    i := Pos(Field + <font color="#9933CC">'='</font>,Data);
    <b>if</b> i &gt; 1 <b>then</b> i := 0
    <b>end</b>
    <b>else</b> Inc(i); <font color="#003399"><i>// '&amp;'-Zeichen überspringen</i></font>
    <b>if</b> i &gt; 0 <b>then</b> <b>begin</b>
    Inc(i,Length(Field)+1);
    <b>while</b> Data[i] &lt;&gt; <font color="#9933CC">'&amp;'</font> <b>do</b> <b>begin</b>
    <b>if</b> <b>not</b> (Data[i] <b>in</b> [#10,#13]) <b>then</b> <b>begin</b> <font color="#003399"><i>// CR/LF ignorieren</i></font>
    Inc(Len);
    Result[Len] := Data[i]
    <b>end</b>
    <b>else</b> <b>begin</b> <font color="#003399"><i>// CR/LF -&gt; #32</i></font>
    <b>if</b> (Len = 0) <b>or</b> (Result[Len] &lt;&gt; #32) <b>then</b> <b>begin</b>
    Inc(Len);
    Result[Len] := #32
    <b>end</b>
    <b>end</b>;
    Inc(i)
    <b>end</b>
    <b>end</b>;
    <b>while</b> (Len &gt; 0) <b>and</b> (Result[len] = #32) <b>do</b> Dec(len)
    <b>end</b>;

    <font color="#003399"><i>{ Zeichenkette in Integerwert konvertieren }</i></font>

    <b>function</b> ValueAsInteger(<b>const</b> Field: ShortString): Integer;
    <b>begin</b>
    <b>try</b>
    Result := StrToInt(Value(Field))
    <b>except</b>
    Result := 0
    <b>end</b>
    <b>end</b>;

    <b>procedure</b> GenerateContents(<b>var</b> Str: <b>String</b>);

    <font color="#003399"><i>{ Buttonleiste generieren:
    a) neuer Datensatz : POST, CANCEL
    b) Anzeigemodus : FIRST, PREV, NEXT, LAST, INSERT, DELETE, REFRESH }</i></font>

    <b>procedure</b> DataSetTable(DataSet: TDataSet; NewRec: Boolean);
    <b>const</b>
    Int: <b>array</b>[1..9] <b>of</b> Char = <font color="#9933CC">'123456789'</font>;
    <b>var</b>
    i,j,col,items : Integer;
    option : ShortString;
    <b>begin</b>
    <b>if</b> NewRec <b>then</b> <b>begin</b>
    Str := Str + <font color="#9933CC">'&lt;INPUT TYPE=SUBMIT NAME=Action VALUE=Post&gt;'</font>#13#10;
    Str := Str + <font color="#9933CC">'&lt;INPUT TYPE=SUBMIT NAME=Action VALUE=Cancel&gt;'</font>#13#10
    <b>end</b>
    <b>else</b> <b>begin</b>
    Str := Str + <font color="#9933CC">'&lt;INPUT TYPE=SUBMIT NAME=Action VALUE=First&gt;'</font>#13#10;
    Str := Str + <font color="#9933CC">'&lt;INPUT TYPE=SUBMIT NAME=Action VALUE=Prev&gt;'</font>#13#10;
    Str := Str + <font color="#9933CC">'&lt;INPUT TYPE=SUBMIT NAME=Action VALUE=Next&gt;'</font>#13#10;
    Str := Str + <font color="#9933CC">'&lt;INPUT TYPE=SUBMIT NAME=Action VALUE=Last&gt;'</font>#13#10;
    Str := Str + <font color="#9933CC">'&amp;nbsp;'</font>#13#10;
    Str := Str + <font color="#9933CC">'&lt;INPUT TYPE=SUBMIT NAME=Action VALUE=Insert&gt;'</font>#13#10;
    Str := Str + <font color="#9933CC">'&lt;INPUT TYPE=SUBMIT NAME=Action VALUE=Delete&gt;'</font>#13#10;
    Str := Str + <font color="#9933CC">'&amp;nbsp;'</font>#13#10;
    <font color="#003399"><i>// Suchbutton z.Zt. auskommentiert</i></font>
    <font color="#003399"><i>//Str := Str + '&lt;INPUT TYPE=SUBMIT NAME=Action VALUE=Find&gt;'#13#10;</i></font>
    <font color="#003399"><i>//Str := Str + '&lt;INPUT TYPE=SUBMIT NAME=Action VALUE=Query&gt;'#13#10;</i></font>
    <font color="#003399"><i>//Str := Str + '&amp;nbsp;'#13#10;</i></font>
    Str := Str + <font color="#9933CC">'&lt;INPUT TYPE=SUBMIT NAME=Action VALUE=Refresh&gt;'</font>#13#10;
    <b>end</b>;
    Str := Str + <font color="#9933CC">'&lt;INPUT TYPE=RESET VALUE=Reset&gt;'</font>#13#10;
    Str := Str + <font color="#9933CC">'&lt;P&gt;'</font>#13#10;
    <b>with</b> DataSet <b>do</b> <b>begin</b>
    <b>if</b> NewRec
    <font color="#003399"><i>// neuer Datensatz -&gt; Autoincrementfeld ist unbekannt</i></font>
    <b>then</b> Str := Str + <font color="#9933CC">'&lt;INPUT TYPE=HIDDEN NAME=&quot;'</font> +
    Fields[0].FieldName + <font color="#9933CC">'&quot; VALUE=&quot;-1&quot;&gt;'</font>#13#10
    <font color="#003399"><i>// vorhandener Datensatz -&gt; Primärschlüsselwert merken</i></font>
    <b>else</b> Str := Str + <font color="#9933CC">'&lt;INPUT TYPE=HIDDEN NAME=&quot;'</font> +
    Fields[0].FieldName + <font color="#9933CC">'&quot; VALUE=&quot;'</font> +
    Fields[0].AsString + <font color="#9933CC">'&quot;&gt;'</font>#13#10;
    Str := Str + <font color="#9933CC">'&lt;TABLE BGCOLOR=BBBBBB BORDER&gt;&lt;TR&gt;'</font>#13#10;
    col := 0;
    <font color="#003399"><i>// auf INI zugreifen</i></font>
    <b>with</b> TIniFile.Create(IniFile) <b>do</b>
    <b>try</b>
    <font color="#003399"><i>// erste Spalte (Primärschlüssel) ist versteckt</i></font>
    <b>for</b> i := 1 <b>to</b> FieldCount - 1 <b>do</b> <b>begin</b>
    <b>if</b> Fields[i].DataType = ftMemo <b>then</b> <b>begin</b>
    <font color="#003399"><i>// Memofeld</i></font>
    Str := Str + <font color="#9933CC">'&lt;/TR&gt;&lt;TR&gt;&lt;TD COLSPAN=3&gt;'</font>;
    col := 3;
    <b>end</b>
    <b>else</b>
    <font color="#003399"><i>// kein Memofeld</i></font>
    <b>if</b> Fields[i].Size &gt; 99 <b>then</b> <b>begin</b>
    <font color="#003399"><i>// langes Zeichenfeld</i></font>
    Inc(col,2);
    <b>if</b> col &gt; 3 <b>then</b> <b>begin</b>
    Str := Str + <font color="#9933CC">'&lt;/TR&gt;&lt;TR&gt;'</font>;
    col := 2
    <b>end</b>;
    Str := Str + <font color="#9933CC">'&lt;TD COLSPAN=2&gt;'</font>
    <b>end</b>
    <b>else</b> <b>begin</b>
    <font color="#003399"><i>// kurzes Zeichenfeld</i></font>
    Inc(col);
    <b>if</b> col &gt; 3 <b>then</b> <b>begin</b>
    Str := Str + <font color="#9933CC">'&lt;/TR&gt;'</font>#13#10<font color="#9933CC">'&lt;TR&gt;'</font>;
    col := 1
    <b>end</b>;
    Str := Str + <font color="#9933CC">'&lt;TD&gt;'</font>
    <b>end</b>;
    Str := Str + <font color="#9933CC">'&lt;B&gt;'</font> + ReadString(Fields[i].FieldName, <font color="#9933CC">'Name'</font>,
    Fields[i].FieldName) + <font color="#9933CC">'&lt;/B&gt;&lt;BR&gt;'</font>;
    <font color="#003399"><i>// Einträge zu dieser Tabellenspalte in der INI ?</i></font>
    items := ReadInteger(Fields[i].FieldName,<font color="#9933CC">'Items'</font>,0);
    <b>if</b> items = 0 <b>then</b> <b>begin</b>
    <font color="#003399"><i>// kein Eintrag in der INI</i></font>
    <b>if</b> Fields[i].DataType = ftMemo <b>then</b> <b>begin</b>
    Str := Str + <font color="#9933CC">'&lt;TEXTAREA NAME=&quot;'</font> + Fields[i].FieldName +
    <font color="#9933CC">'&quot; ROWS=18 COLS=80&gt;'</font>;
    <b>if</b> <b>not</b> NewRec <b>then</b>
    Str := Str + Fields[i].AsString;
    Str := Str + <font color="#9933CC">'&lt;/TEXTAREA&gt;'</font>
    <b>end</b>
    <b>else</b> <b>begin</b>
    <font color="#003399"><i>// kein Memo -&gt; wie groß ist das Feld ?</i></font>
    <b>if</b> Fields[i].Size &gt; 99 <b>then</b>
    Str := Str + <font color="#9933CC">'&lt;INPUT TYPE=text NAME=&quot;'</font> +
    Fields[i].FieldName + <font color="#9933CC">'&quot; SIZE=64'</font>
    <b>else</b>
    <b>if</b> Fields[i].Size = 0 <b>then</b>
    Str := Str + <font color="#9933CC">'&lt;INPUT TYPE=text NAME=&quot;'</font> +
    Fields[i].FieldName + <font color="#9933CC">'&quot; SIZE=30'</font>
    <b>else</b>
    Str := Str + <font color="#9933CC">'&lt;INPUT TYPE=text NAME=&quot;'</font> +
    Fields[i].FieldName + <font color="#9933CC">'&quot; SIZE='</font> +
    IntToStr(Fields[i].Size);
    <b>if</b> <b>not</b> NewRec <b>then</b>
    Str := Str + <font color="#9933CC">' VALUE=&quot;'</font> + Fields[i].AsString + <font color="#9933CC">'&quot;'</font>;
    Str := Str + <font color="#9933CC">'&gt;'</font>
    <b>end</b>
    <b>end</b>
    <b>else</b> <b>begin</b>
    <font color="#003399"><i>// Eintrag in der INI vorhanden !</i></font>
    Str := Str + <font color="#9933CC">'&lt;SELECT NAME=&quot;'</font> + Fields[i].FieldName + <font color="#9933CC">'&quot;&gt;'</font>;
    <b>for</b> j:=1 <b>to</b> items <b>do</b> <b>begin</b>
    option := ReadString(Fields[i].FieldName,
    <font color="#9933CC">'Item'</font> + Int[j], Int[j]);
    <b>if</b> (<b>not</b> NewRec) <b>and</b> (option = Fields[i].AsString) <b>then</b> <font color="#003399"><i>{ selected }</i></font>
    Str := Str + <font color="#9933CC">'&lt;OPTION SELECTED VALUE=&quot;'</font> + option +
    <font color="#9933CC">'&quot;&gt;'</font> + option + <font color="#9933CC">' '</font>
    <b>else</b>
    Str := Str + <font color="#9933CC">'&lt;OPTION VALUE=&quot;'</font> + option + <font color="#9933CC">'&quot;&gt;'</font> + option + <font color="#9933CC">' '</font>
    <b>end</b>;
    Str := Str + <font color="#9933CC">'&lt;/SELECT&gt;'</font>
    <b>end</b>;
    Str := Str + <font color="#9933CC">'&lt;/TD&gt;'</font>
    <b>end</b>;
    Str := Str + <font color="#9933CC">'&lt;/TR&gt;'</font>#13#10
    <b>finally</b>
    Str := Str + <font color="#9933CC">'&lt;/TABLE&gt;'</font>#13#10;
    Free
    <b>end</b>
    <b>end</b>
    <b>end</b>;

    <font color="#003399"><i>{ Pfad der INI-Datei aus den Alias-Daten auslesen }</i></font>

    <b>function</b> GetAliasPath(<b>const</b> Alias: <b>string</b>): <b>string</b>;
    <b>var</b>
    ParamList: TStringList;
    <b>begin</b>
    ParamList:=TStringList.Create;
    <b>try</b>
    Session.GetAliasParams(Alias, ParamList);
    Result:=ParamList.Values[<font color="#9933CC">'PATH'</font>];
    <b>finally</b>
    ParamList.Free;
    <b>end</b>;
    <b>end</b>;

    <font color="#003399"><i>// Hauptteil von procedure GenerateContents(var Str: String);</i></font>
    <b>const</b>
    _DatabaseName = <font color="#9933CC">'CgiSQL'</font>; <font color="#003399"><i>// Aliasname der BDE</i></font>
    _TableName = <font color="#9933CC">'sqlmemo.db'</font>; <font color="#003399"><i>// Tabellenname</i></font>
    Action: <b>String</b>[7] = <font color="#9933CC">''</font>;
    <b>var</b>
    Table: TTable;
    Session: TSession; <font color="#003399"><i>// Multithreading-BDE</i></font>
    iPrimaryKey,i: Integer; <font color="#003399"><i>// Primärschlüsselfeld</i></font>
    NoChange: Boolean;
    <b>begin</b>
    Str := <font color="#9933CC">''</font>;
    Action := <font color="#9933CC">''</font>;
    ShortDateFormat := <font color="#9933CC">'DD.MM.YYYY'</font>;
    <font color="#003399"><i>// neue Session für die BDE anlegen (Multithreading)</i></font>
    Session := TSession.Create(<b>nil</b>);
    Session.AutosessionName := True;
    Session.Active := True;
    <font color="#003399"><i>// neue TTable-Instanz anlegen, verwendet die neue Session</i></font>
    Table := TTable.Create(<b>nil</b>);
    Table.SessionName := Session.SessionName;
    <b>with</b> Table <b>do</b>
    <b>try</b>
    Active := False;
    TableType := ttParadox;
    DatabaseName := _DatabaseName; <font color="#003399"><i>// Zugriff über Aliasname</i></font>
    TableName := _TableName;
    Open; <font color="#003399"><i>// Datenbanktabelle öffnen</i></font>
    <font color="#003399"><i>// Kopf der Startseite zusammenbauen</i></font>
    IniFile := GetAliasPath(_DatabaseName) + <font color="#9933CC">'\sqldb.ini'</font>;
    Str := <font color="#9933CC">'&lt;HTML&gt;'</font>#13#10;
    <b>with</b> TIniFile.Create(IniFile) <b>do</b>
    <b>try</b>
    Str := Str + <font color="#9933CC">'&lt;HEAD&gt;'</font>#13#10;
    Str := Str + <font color="#9933CC">'&lt;TITLE&gt;'</font> + ReadString(_TableName,<font color="#9933CC">'Name'</font>,<font color="#9933CC">''</font>) +
    <font color="#9933CC">'&lt;/TITLE&gt;'</font>#13#10;
    Str := Str + <font color="#9933CC">'&lt;/HEAD&gt;'</font>#13#10;
    Str := Str + <font color="#9933CC">'&lt;BODY BGCOLOR=AAAAAA&gt;'</font>#13#10;
    Str := Str + <font color="#9933CC">'&lt;CENTER&gt;'</font>#13#10;
    Str := Str + <font color="#9933CC">'&lt;H1&gt;'</font>;
    Str := Str + <font color="#9933CC">'&lt;IMG SRC=&quot;'</font> + ReadString(_TableName,<font color="#9933CC">'Bitmap'</font>,<font color="#9933CC">''</font>) + <font color="#9933CC">'&quot;&gt;'</font>;
    Str := Str + ReadString(_TableName, <font color="#9933CC">'Name'</font>, <font color="#9933CC">''</font>);
    Str := Str + <font color="#9933CC">'&lt;/H1&gt;'</font>#13#10;
    Str := Str + <font color="#9933CC">'&lt;FORM METHOD=POST ACTION=&quot;'</font> +
    ReadString(_TableName, <font color="#9933CC">'Action'</font>, <font color="#9933CC">''</font>) + <font color="#9933CC">'&quot;&gt;'</font>#13#10
    <b>finally</b>
    Free
    <b>end</b>;
    First;
    <font color="#003399"><i>// übergebenen Primärschlüssel ermitteln und suchen</i></font>
    iPrimaryKey := ValueAsInteger(<font color="#9933CC">'RecID'</font>);
    <b>if</b> iPrimaryKey &gt; 0
    <b>then</b> FindKey([iPrimaryKey])
    <b>else</b> First;
    <font color="#003399"><i>// auszuführende Aktion bestimmen</i></font>
    <b>if</b> Action = <font color="#9933CC">''</font>
    <b>then</b> Action := Value(<font color="#9933CC">'Action'</font>);
    <b>if</b> Action = <font color="#9933CC">''</font>
    <b>then</b> Action := <font color="#9933CC">'First'</font>;
    <font color="#003399"><i>// ausführen</i></font>
    <b>if</b> Action = <font color="#9933CC">'First'</font>
    <b>then</b> First
    <b>else</b> <b>if</b> Action = <font color="#9933CC">'Next'</font>
    <b>then</b> Next
    <b>else</b> <b>if</b> Action = <font color="#9933CC">'Prev'</font>
    <b>then</b> Prior
    <b>else</b> <b>if</b> Action = <font color="#9933CC">'Last'</font>
    <b>then</b> Last
    <b>else</b> <b>if</b> (Action = <font color="#9933CC">'Find'</font>) <b>or</b> (Action = <font color="#9933CC">'Query'</font>)
    <b>then</b> <b>begin</b>
    <font color="#003399"><i>// ToDo: spezielles Suchformular</i></font>
    <b>end</b>
    <b>else</b> <b>if</b> Action = <font color="#9933CC">'Delete'</font>
    <b>then</b> Delete
    <b>else</b> <b>if</b> Action = <font color="#9933CC">'Insert'</font>
    <b>then</b> <font color="#003399"><i>// überspringen</i></font>
    <b>else</b> <b>if</b> Action = <font color="#9933CC">'Post'</font>
    <b>then</b> <b>begin</b>
    First;
    iPrimaryKey := 0;
    <b>while</b> <b>not</b> Eof <b>do</b> <b>begin</b>
    <b>if</b> Fields[0].AsInteger &gt; iPrimaryKey
    <b>then</b> iPrimaryKey := Fields[0].AsInteger;
    Next
    <b>end</b>;
    Inc(iPrimaryKey);
    Insert;
    Fields[0].AsInteger := iPrimaryKey;
    <b>for</b> i := 1 <b>to</b> FieldCount - 1 <b>do</b>
    Fields[i].AsString := Value(Fields[i].FieldName);
    Post
    <b>end</b>
    <b>else</b> <b>if</b> Action = <font color="#9933CC">'Cancel'</font>
    <b>then</b>
    <b>else</b>;
    Str := Str + <font color="#9933CC">'&lt;P&gt;&lt;B&gt;'</font> + Action + <font color="#9933CC">'&lt;/B&gt;&lt;P&gt;'</font>;
    <font color="#003399"><i>// HTML-Formular mit den Datenfeldern generieren</i></font>
    DataSetTable(Table,Action = <font color="#9933CC">'Insert'</font>);
    Close
    <b>finally</b>
    Str := Str + <font color="#9933CC">'&lt;/FORM&gt;'</font>#13#10;
    Str := Str + <font color="#9933CC">'&lt;/BODY&gt;'</font>#13#10;
    Str := Str + <font color="#9933CC">'&lt;/HTML&gt;'</font>#13#10;
    Free
    <b>end</b>;
    Session.Free; <font color="#003399"><i>// Session wieder freigeben</i></font>
    Session := <b>nil</b>;
    Table := <b>nil</b> <font color="#003399"><i>// TTable wieder freigeben</i></font>
    <b>end</b>;

    <font color="#003399"><i>// Hauptteil von function HttpExtensionProc</i></font>
    <b>var</b>
    i : Integer;
    Str : AnsiString;
    <b>begin</b>
    Str := <font color="#9933CC">''</font>;
    <b>try</b>
    <b>try</b>
    <font color="#003399"><i>// ECB input data</i></font>
    <b>if</b> StrPas(ECB.lpszMethod) = <font color="#9933CC">'POST'</font>
    <b>then</b> Data := StrPas(ECB.lpbData)
    <b>else</b> Data := ECB.lpszQueryString;
    <b>if</b> (Length(Data) &gt; 1) <b>and</b>
    (Data[Length(Data)] = #0) <b>then</b> Delete(Data,Length(Data),1);
    i := 0;
    <b>while</b> i &lt; Length(Data) <b>do</b> <b>begin</b>
    Inc(i);
    <b>if</b> Data[i] = <font color="#9933CC">'+'</font> <b>then</b> Data[i] := <font color="#9933CC">' '</font>;
    <b>if</b> Data[i] = <font color="#9933CC">'%'</font> <b>then</b> <b>begin</b>
    <font color="#003399"><i>// Sonderzeichen</i></font>
    Str := <font color="#9933CC">'$00'</font>;
    Str[2] := Data[i+1];
    Str[3] := Data[i+2];
    Delete(Data,i+1,2);
    Data[i] := Chr(StrToInt(Str))
    <b>end</b>
    <b>end</b>;
    <b>if</b> i &gt; 0
    <b>then</b> Data[i+1] := <font color="#9933CC">'&amp;'</font>
    <b>else</b> Data := <font color="#9933CC">'&amp;'</font>;
    <font color="#003399"><i>// ECB output data initialisieren</i></font>
    ECB.lpszLogData := <font color="#9933CC">'SQLMemo - die Newsgroupdatenbank'</font>;
    ECB.dwHTTPStatusCode := 200;
    <font color="#003399"><i>// HTML-Seite dynamisch erstellen</i></font>
    <b>try</b>
    GenerateContents(Str);
    <b>except</b>
    <b>on</b> E: Exception <b>do</b>
    Str := Str + <font color="#9933CC">'&lt;P&gt;IN&lt;P&gt;&lt;HR&gt;&lt ;P&gt;'</font> + E.ClassName + <font color="#9933CC">' '</font> + E.Message
    <b>end</b>;
    <b>except</b>
    <b>on</b> E: Exception <b>do</b>
    Str := Str + <font color="#9933CC">'&lt;P&gt;OUT&lt;P&gt;&lt;HR&gt;&l t;P&gt;'</font> + E.ClassName + <font color="#9933CC">' '</font> + E.Message
    <b>end</b>;
    <b>finally</b>
    <font color="#003399"><i>// ECB output data zusammenstellen</i></font>
    Str := Format(<font color="#9933CC">'HTTP/1.0 200 OK'</font>#13#10 +
    <font color="#9933CC">'Content-Type: text/html'</font>#13#10 +
    <font color="#9933CC">'Content-Length: %d'</font>#13#10 +
    <font color="#9933CC">'Content:'</font>#13#10#13#10<font color="#9933CC">'%s'</font>, [Length(Str), Str]);
    i := Length(Str);
    ECB.WriteClient(ECB.ConnID, Pointer(Str), i, 0)
    <b>end</b>;
    Result := HSE_STATUS_SUCCESS
    <b>end</b>;

    <b>exports</b>
    GetExtensionVersion,
    HttpExtensionProc;

    <b>begin</b>
    IsMultiThread := True; <font color="#003399"><i>// Sessions der BDE !!!</i></font>
    <b>end</b>.
    </pre&gt

    Comment

    Working...
    X