AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Tutorials Indy 10 HTTP(S) Protokoll

Indy 10 HTTP(S) Protokoll

Ein Tutorial von geskill · begonnen am 29. Apr 2011 · letzter Beitrag vom 30. Jan 2020
Antwort Antwort
Seite 1 von 2  1 2   
Benutzerbild von geskill
geskill
Registriert seit: 17. Feb 2007
.
Worum geht es hier?
Die Indy Komponenten bieten eine gute Möglichkeit um HTTP(S) Verbindungen zu ermöglichen. Wenn du also Informationen an eine Webseite senden oder empfangen willst bist du hier genau richtig.

Inhalt
  1. HTTP Komponente
    • Allgemeines
    • Daten Empfangen
    • Daten Senden
    • Request Einstellungen
    • Response Informationen
    • Weitere Einstellungen
  2. Cookies
  3. Gzip
  4. SSL
  5. HTTP Proxy / SOCKS 4, 5
  6. Konklusion
  7. Tools
    • WireShark
    • FireFox Web Developer

1. HTTP Komponente
Allgemeines
Die Komponente findet ihr in der Tool-Palette unter "Indy Clients". Dort klickt ihr auf TIdHTTP (Weltkugel) und zieht dies auf euer Formular. Delphi bindet nun automatisch eine Reihe von Units ein wichtig ist dabei IdHTTP, diese Datei enthält alle benötigten Methoden. Alternativ kann man die Klasse auch zur Laufzeit erstellen, ich bevorzuge diese Methode und gebe deshalb alle Beispiele so an.

Daten Empfangen
Die TIdHTTP-Klasse stellt eine Funktion GET zur Verfügung, damit lässt sich der komplette Quellcode von einer Webseite empfangen:
Delphi-Quellcode:
uses
  IdHTTP;
// ...

var
  ResponseStr: string;
begin
  with TIdHTTP.Create(nil) do
    try
      // Empfange den Quellcode
      ResponseStr := Get('http://www.delphipraxis.net/');

      // in den neueren Indy Releases (10.5.8+) erfolgt das Encoding automatisch,
      // vorher musste man sich behelfen (mit einem TMemoryStream oder TStringStream)
      // dazu: http://forums2.atozed.com/viewtopic.php?f=7&t=25756

      // Mache hier irgendwas mit dem Quellcode
      DoSomething(ResponseStr);
    finally
      Free;
    end;
Daten Senden
Zum Senden von Daten wie Login Informationen oder Dateien bietet die Klasse eine Funktion POST. Es gibt nun 3 verschiedene Möglichkeiten, wie man die Daten sendet. Entweder mit einer TStringList, wenn man keine Dateien senden muss, aber bestimmte Formularfelder ansprechen möchte. Wenn man eine API ansprechen möchte z.B. Google Blogger dann sendet man, ohne ein spezielles Formularfeld anzusprechen oder man nutzt die Klasse TIdMultiPartFormDataStream aus der Unit IdMultipartFormData. Oft ist es auch so, dass die Seite vorgibt, wie die Daten gesendet werden müssen. Im HTML Quelltext sollte man im form-Tag auf das Attribut "enctype" achten.
Hier stand mal das man keine TStringList benutzen sollte und stattdessen einen TStringStream und dann die Werte selber codieren sollte, dass ist bei alten Indy Versionen notwendig, in den aktuelleren kann man dies aber auch getrost Indy überlassen - so geht's:
Delphi-Quellcode:
uses
  IdGlobalProtocols, IdHTTP;
// ...

var
  Params: TStringList;
  Enc: TEncoding;
  ResponseStr: string;
begin
  with TIdHTTP.Create(nil) do
    try
      // der ContentType beschreibt in welchem Format die Daten an
      // den Server gesendet werden
      Request.ContentType := 'application/x-www-form-urlencoded';

      Params := TStringList.Create;
      try
        with Params do
        begin
          Add('vb_login_username=' + AccountName);
          Add('vb_login_password=' + AccountPassword);
          Add('securitytoken=guest');
          Add('do=login');
          Add('vb_login_md5password=');
          Add('vb_login_md5password_utf=');
          Add('cookieuser=1');
          Add('s=');
        end;

        // Request.CharSet vorher setzten: z.B: ISO-8859-1
        Enc := CharsetToEncoding(Request.CharSet);
        try
          // Daten senden
          ResponseStr := Post('http://www.delphipraxis.net/login.php?do=login', Params, Enc);
        finally
          Enc.Free;
        end;

      finally
        Params.Free;
      end;
    finally
      Free;
    end;
Delphi-Quellcode:
uses
  IdGlobalProtocols, IdHTTP;
// ...

var
  Data: TStringStream;

  ResponseStr: string;
begin
  with TIdHTTP.Create(nil) do
    try
      Request.ContentType := 'application/atom+xml';
      with Request.CustomHeaders do
      begin
        Add('GData-Version: 2');
        Add('Authorization: GoogleLogin auth=' + {Hier käme ein Autorisierungswert rein});
      end;

      // Hier kann auch TStringStream.Create('', CharsetToEncoding(Request.CharSet)) genutzt werden
      Data := TStringStream.Create('', CP_UTF8);
      try
        Data.WriteString( newPageXMLDoc() ); // interne Funktion zum erstellen der API Requests

        Request.CharSet := 'UTF-8';
        
        ResponseStr := Post('http://www.blogger.com/feeds/' + BloggerSettings.id + '/posts/default', Data);
      finally
        Data.Free;
      end;

  // Wenn ResponseCode = 201 dann war das Eintragen erfolgreich.
Delphi-Quellcode:
uses
  IdHTTP, IdMultipartFormData, IdGlobalProtocols;
// ...

var
  Params: TIdMultiPartFormDataStream;
  ResponseStr: string;

  _filename: string;
begin
  with TIdHTTP.Create(nil) do
    try
      // der ContentType beschreibt in welchem Format die Daten an
      // den Server gesendet werden
      Request.ContentType := 'multipart/form-data';

      Params := TIdMultiPartFormDataStream.Create;
      try
        with Params do
        begin
          // Für kleinere Text oder Zahlenwerte, wo man sicher gehen kann, dass es
          // nicht zu Kodierungsproblemen kommen kann bietet sich diese Methode an
          AddFormField('einfachertext', 'text');

          // In der neueren Version ist diese Funktion zwar deprecated, aber um wirklich
          // sicher zu gehen, dass die Daten richtig Kodiert sind verwende ich diese Variante.
          // Der erste Parameter gibt den Elementnamen und der letze den Elementwert an.
          // für alte Indy's: AddObject('text_in_utf8', '', '', TStringStream.Create('text', TEncoding.UTF8));

          // Ab den aktuellen Funktioniert dies analog:
          AddFormField('text_in_utf8', 'text', 'UTF-8').ContentTransfer := 'binary';

          // zu ContentTransfer: http://stackoverflow.com/questions/7189794/indy-adds-at-every-72nd-char-with-multi-part-form-data-post

          // Das äquivalent zu oben nur für Webseiten die im ISO-8859-1 kodiert sind
          // für alte Indy's: AddObject('text_in_ascii', '', '', TStringStream.Create('text', TEncoding.ASCII));
          AddFormField('text_in_ascii', 'text', 'ISO-8859-1').ContentTransfer := 'binary';

          // Wie versprochen kann man hiermit auch Dateien senden, damit der MIME-
          // Type passt sollte man die GetMIMETypeFromFile() Funktion aus der Unit
          // IdGlobalProtocols verwenden.
          AddFile('file', _filename, GetMIMETypeFromFile(_filename));
        end;

        // Daten senden
        ResponseStr := Post('http://deineseite.com/', Params);

      finally
        Params.Free;
      end;
    finally
      Free;
    end;
Request Einstellungen
Der HTTP Client sendet beim Empfangen oder Senden von Daten nebenher noch weitere Informationen. Eine haben wir eben schon kennengelernt, den ContentType. Die Definition von diesen Werten ist eigentlich optional, jedoch gibt es viele Server die Probleme mit den Standardangaben haben.
Delphi-Quellcode:
with TIdHTTP.Create(nil) do
  try
    // Die Accept Angabe definiert, welche Formen von Daten der Client akzeptiert
    Request.Accept := 'text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1';
    // Der AcceptCharSet Wert definiert, welche Zeichen-Formate der Client akzeptiert
    Request.AcceptCharSet := 'iso-8859-1, utf-8, utf-16, *;q=0.1';
    // Die AcceptEncoding Angabe definiert, welche Kompressionsformate der Client akzeptiert
    Request.AcceptEncoding := 'deflate, identity, *;q=0';
    Request.Connection := 'Keep-Alive';
    // Der Referer definiert, auf welcher Webseite wir zuvor waren. Gerade dieser Wert
    // wird gerne von Webseiten abgefragt um ungewünschte Bots zu blocken.
    Request.Referer := 'http://deineseite.com/';
    // Die Client Erkennung, um sich zu tarnen benutze ich gerne den Opera User-Agent
    Request.UserAgent := 'Opera/9.80 (Windows NT 6.1; U; de) Presto/2.5.22 Version/10.51';
//...
Response Informationen
Wenn man den Quelltext von einer Webseite empfängt werden noch weitere Protokoll Informationen gesendet.
Delphi-Quellcode:
//...

        ResponseStr := Get('http://www.delphipraxis.net/');

        // eine Mögliche Form der Weiterleitung an eine andere Adresse oder Unterseite
        // ist der Location-Header.
        ShowMessage(Response.Location);

        // Natürlich hat man auch auf die ganzen Statuscodes einen Zugriff (á la 404 Not Found) mit
        // Response.ResponseCode und Response.ResponseText

        // Alle Header Informationen kann man so Ausgeben:
        ShowMessage(Response.RawHeaders.Text);

//...
Weitere Einstellungen
Neben den ganzen Header Informationen kann man natürlich noch Timeouts und beispielsweise das Verhalten bei Weiterleitungen definierten.
Delphi-Quellcode:
with TIdHTTP.Create(nil) do
  try
    // Behandle Weiterleitungen (Standard = False)
    HandleRedirects := True;
    // Leite Maximal X mal weiter (Standard = 15)
    // Meistens reicht eine Weiterleitung, mehr ist oft nur Trafficwaste
    RedirectMaximum := 1;

    // Zeit in Millisekunden, wie lange gewartet wird, bis...
    // ...der Client zum Server verbunden ist
    ConnectTimeout := 5000; // 5 Sekunden
    // ...der Client alle geforderten Daten vom Server gelesen hat
    ReadTimeout := 15000; // 15 Sekunden
//...
2. Cookies
Hiermit handelt es sich nicht um das Problem, dass es keine Kekse gibt, sondern um kleine Dateien, die eine Webseite auf dem Client erstellt um Daten wie z.b. eine Sitzung's-ID zu speichern. Auch die HTTP Komponente unterstützt dies. Dazu reicht diese Einstellung:
Delphi-Quellcode:
uses
  IdHTTP, IdURI;
//...

with TIdHTTP.Create(nil) do
  try
    // der Cookie Manager wird nun automatisch angelegt
    AllowCookies := True;
    

    // Man kann natürlich Cookies auch modifizieren:

    //... irgendwelche Daten werden empfangen, dabei setzt der Server Cookies

    with CookieManager.CookieCollection do
      for I := 0 to Count - 1 do // alle Cookies durchsuchen
        if ('CookieName' = Cookies[I].CookieName) then
        begin
          MacheWasMitDemCookieWert(Cookies[I].Value);
          break;
        end;

    // Cookies werden so erstellt:
    // TIdURI Klasse aus: IdURI
    CookieManager.AddServerCookie('werbung_aus=1', TIdURI.Create('http://www.delphipraxis.net/'));

//...
Hinweis: Die Cookie Implementation ist erst seit 10.5.8 wirklich alterstauglich.

3. Gzip
Je umfangreicher die Webseite, desto mehr Quelltext muss geladen werden und umso länger dauert dies auch. Mit Gzip kann, wenn der Server das unterstützt der Datenaustausch komprimiert werden. Dazu muss zusätzlich die Unit IdCompressorZLib eingebunden werden.
Delphi-Quellcode:
uses
  IdHTTP, IdCompressorZLib;
// ...

with TIdHTTP.Create(nil) do
  try
    Compressor := TIdCompressorZLib.Create(nil); // Beim Freigeben der HTTP Komponente wird der Compressor mit freigegeben.

    // Nun dürfen wir im AcceptEncoding definieren, dass gzip Unterstützt wird
    Request.AcceptEncoding := 'deflate, gzip, identity, *;q=0';

    // Manche Server machen Probleme mit der Kompression, sodass es zu Fehlern kommen kann,
    // diese kann man leicht abfangen, die Dekompression klappte bei mir jedoch immer richtig.
    try
      // Bei Indy Versionen älter 10.5.8 muss man hierbei immer mit Streams arbeiten, weil sonst werden die Daten nicht dekomprimiert:
      // Post('http://deineseite.com/', Params, ReplyData); // ReplyData vom Typ TMemoryStream
      // ReplyData.Position := 0; nicht vergessen :)
      // ResponseStr := ReadStringAsCharset(ReplyData, Response.Charset);

      QuellcodeStringVariable := Post('http://deineseite.com/', Params);
    except
      on E: EDecompressionError do
        ; // Mache nichts (ich weiß das sieht nicht professionell aus)
      // Weitere Fehlerbehandlungen
    end;
//...
4. SSL
Das HTTPS Protokoll verschlüsselt den kompletten Datenverkehr. Vorab: Hierfür werden die passenden Versionen der libeay32.dll und ssleay32.dll Bibliothek benötigt. Die aktuelle Version findet man immer in diesem Thema. Die DLLs müssen ins root-Verzeichnis eurer Applikation. Zusätzlich müssen wir die Unit IdSSLOpenSSL einbinden.
Delphi-Quellcode:
uses
  IdHTTP, IdSSLOpenSSL;
// ...

with TIdHTTP.Create(nil) do
  try
    IOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
//...
5. HTTP Proxy / SOCKS 4, 5
Was ich euch hier zeigen möchte ist eine Kombi-Lösung für die verschiedenen Proxy Varianten, d.h. man sollte sich eine eigene Proxy Klasse schreiben mit einem Proxy-Typ, der dann generell alles ermöglicht. Damit dies auch in Kombination mit SSL funktioniert habe ich auch dies eingebaut. Natürlich könnte man, wenn man wirklich nur SOCKS 5 benötigt das dementsprechend vereinfachen, aber wie gesagt, hier ein flexibles Beispiel:
Delphi-Quellcode:
uses
  IdHTTP, IdSSLOpenSSL, IdSocks;
// ...

var
  FIdSSLIOHandlerSocketOpenSSL: TIdSSLIOHandlerSocketOpenSSL;
  FIdSocksInfo: TIdSocksInfo;
begin
  with TIdHTTP.Create(nil) do
    try
      FIdSSLIOHandlerSocketOpenSSL := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
      with FIdSSLIOHandlerSocketOpenSSL.SSLOptions do
      begin
        Method := sslvTLSv1_2;
        SSLVersions := [sslvTLSv1_2];
      end;
      FIdSocksInfo := TIdSocksInfo.Create(nil);

      if { SOCKS wird benutzt ??? } then
        with FIdSocksInfo do
        begin
          Host := 'Server';
          Port := 8080; // Beispiel Port

          if { SOCKS Version = ??? } then
             Version := svSocks4
           else
             Version := svSocks5;

          case { RequireAuthentication ??? } of
            True:
              Authentication := saUsernamePassword;
            False:
              Authentication := saNoAuthentication;
          end;

          Username := 'AccountName';
          Password := 'AccountPassword';

          // Nun SOCKS aktivieren
          Enabled := True;
        end
        else // normale HTTP-Proxy wird benutzt
          with ProxyParams do
          begin
            ProxyServer := 'Server';
            ProxyPort := 80; // Beispiel Port
            BasicAuthentication := True; // RequireAuthentication ???
            ProxyUsername := 'AccountName';
            ProxyPassword := 'AccountPassword';
          end;

      // Erst dem SSL-Handler die Mögliche Proxy/SOCKS Konfiguration zuweisen
      // andersrum greift es nicht!
      FIdSSLIOHandlerSocketOpenSSL.TransparentProxy := FIdSocksInfo;

      // Jetzt der HTTP Komponente zuweisen
      IOHandler := FIdSSLIOHandlerSocketOpenSSL;
//...
6. Konklusion
Wie man sieht unterstützt die HTTP Komponente alle nötigen Funktionen eines Browsers. Ich höre/lese immer wieder, dass eine Webseite nicht auslesen werden kann, weil die Komponente kein JavaScript unterstützt. Diese Aussage kann ich zwar nicht widerlegen, jedoch ist mir noch keine Webseite unter den Nagel gekommen, wo die Komponente an ihre Grenzen gestoßen ist.

Wenn ihr jetzt also selber viele Teile hiervon benötigt, empfehle ich eine eigene Klasse zu schreiben, die von TIdHTTP erbt. Darin setzt ihr alle Voreinstellungen, damit man das nicht bei jeder Verwendung machen muss (okay eigentlich selbstverständlich nur ..., ja genau).

7. Tools
WireShark
Bei der Client/Server Kommunikation können sehr leicht Fehler auftreten, meistens weiß man aber nicht so genau, was überhaupt übertragen wurde, deshalb kann ich jetzt nun schon aus langjähriger Erfahrung dieses umfangreiche und kostenlose Programm empfehlen.
Filter:
Damit man nur den HTTP Datenverkehr angezeigt bekommt.
Code:
http && (http.response.code != 0) || (tcp.dstport == 80)
FireFox Web Developer
Ich bin wohl der letzte Mensch der freiwillig dauerhaft diesen Browser benutzen würde, jedoch gibt es dafür ein wunderbares Plugin, welches von einer beliebigen Webseite alle Formularfelder sauber in einer strukturierten Tabelle anzeigen kann. Sprich man muss sich nicht mehr durch den Quelltext-Dschungel kämpfen.

Da dies nun mein erstes Tutorial ist, hoffe ich, dass nicht allzu viel falsch gemacht wurde
.

Geändert von geskill (30. Okt 2015 um 00:14 Uhr) Grund: Updated to TLS 1.2 SSL.
 
Benutzerbild von rollstuhlfahrer
rollstuhlfahrer

 
Delphi 7 Professional
 
#2
  Alt 29. Apr 2011, 20:26
Sieht super aus. Den Teil mit GZip werde ich unbedingt mal testen, um zu wissen, ob der Server auf dem ich rumspiele das auch gescheit verwendet.

Noch ein Wort zu SSL: Es werden die DLLs benötigt, die zur Version von INDY passen. So bin ich ganz froh, die DLLs für INDY9 noch zu haben, dass das mit meinem Delphi und dem Grundkomponentensatz geht.

Bernhard
Bernhard
  Mit Zitat antworten Zitat
Chriscode
 
#3
  Alt 17. Jul 2012, 21:01
Sehr hilfreich,
vielen Dank.

Eine kleine Ergänzung:
Die Geschichte mit dem automatischen Konvertieren durch idhttp geht nur mit aktuellen Indy Komponenten. Mit den 150er hat es noch nicht funktioniert, jetzt mit 160 schon.

Also für alle die sich wundern warum der zusätzliche Parameter nicht möglich ist -> Indy Update.

Für das Tutorial noch einmal meinen herzlichen Dank an den Ersteller.
Chris
  Mit Zitat antworten Zitat
Benutzerbild von Back2Code
Back2Code

 
Delphi XE7 Professional
 
#4
  Alt 4. Sep 2013, 09:18
Mir hat das Tutorial auch sehr viel zeigen können. Vieles davon lässt sich sehr schwierig googlen und ist selbst dann nicht immer ersichtlich was überhaupt jetzt damit gemeint ist da man hauptsächlich auch viele Themen zu alten Indy Versionen findet.
  Mit Zitat antworten Zitat
Christoph64

 
Delphi 10.2 Tokyo Professional
 
#5
  Alt 9. Sep 2018, 17:24
Hallo,

ich bin neu hier, deswegen weiss ich nicht, ob es noch Sinn macht auf ein so altes Thema zu antworten, aber ich versuche es einfach mal. Vielleicht kann mir ja einer weiterhelfen.

Ich versuche mit der neusten Delphi version Tokio 10.2 eine Anwendung zu Programmieren, die eine HTTPS Webseite liest, was ich aber leider nicht hinbekomme. Es liegt wohl auch daran das mir das basis wissen dazu fehlt. Ich kann problemlos eine HTTP Seite mit derr Anwendung lesen.

Kann mir jemand weiterhelfen ?
Eine Frage z.B habe ich, benötige ich bei Delphi 10.2 immer noch die libeay32.dll und ssleay32.dll Bibliothek, oder sind die mitlerweile im Delphi integriert.

Wäre nett, wenn ich eine info bekommen würde.
Christoph Keil
  Mit Zitat antworten Zitat
Redeemer

 
Delphi 2009 Professional
 
#6
  Alt 9. Sep 2018, 18:12
Seit XE8 gibt es Delphi-Referenz durchsuchenSystem.Net.HttpClientComponent.TNetHTTPClient, der eine Windows-API verwendet. Bei einfachen GET-Requests würde ich Delphi-Referenz durchsuchenVcl.ExtActns.TDownloadURL benutzen, das es seit Urzeiten gibt und einfach zu verwenden ist.

Indy benötigt weiterhin OpenSSL.
Janni
  Mit Zitat antworten Zitat
Benutzerbild von KodeZwerg
KodeZwerg

 
Delphi 11 Alexandria
 
#7
  Alt 9. Sep 2018, 21:25
Eine ganz brauchbare Resource für OpenSSL mit anderen Libraries findest Du hier.

Ich selbst habe auch positive Erfahrung mit der Overbyte (ICS) Variante gemacht, falls einem pures Indy zu wenig bietet/zu schwer ist einzusetzen, da ist eine sehr steile Lernkurve bei wenig Programmierung geboten. Also falls alle Stricke reißen, einfach mal da reinschnuppern, ist sehr Neueinsteiger-freundlich will ich damit sagen.

Das hier zugrunde liegende Tutorial, gute Arbeit, genug und nachvollziehbar erklärt, Danke dafür.
  Mit Zitat antworten Zitat
Christoph64

 
Delphi 10.2 Tokyo Professional
 
#8
  Alt 11. Sep 2018, 17:23
Danke erst einmal ich schaue mir das jetzt mal in ruhe an, was ich nun zum download der https Seite nehmen werde.
Die beiden Möglichkeiten von Redeeemer gefallen mir.

Also Danke Euch beiden.
Christoph Keil
  Mit Zitat antworten Zitat
Hobbycoder
 
#9
  Alt 11. Sep 2018, 17:35
Seit XE8 gibt es Delphi-Referenz durchsuchenSystem.Net.HttpClientComponent.TNetHTTPClient, der eine Windows-API verwendet. Bei einfachen GET-Requests würde ich Delphi-Referenz durchsuchenVcl.ExtActns.TDownloadURL benutzen, das es seit Urzeiten gibt und einfach zu verwenden ist.

Indy benötigt weiterhin OpenSSL.
Kommen die beiden erstgenannten Möglichkeiten ohne OpenSSL-DLL's aus?
  Mit Zitat antworten Zitat
Rolf Frei

 
Delphi 11 Alexandria
 
#10
  Alt 12. Sep 2018, 12:25
Ja. Um OpenSSL würde ich, wenn möglich, einen grossen Bogen machen. Die System.Net Funktionen laufen nativ auf Windows und brauchen daher kein OpenSSL.

Habe damit aber das Problem, dass es bei Redirects (301/302) keine Möglichkeit zu geben scheint, die wirklich gelesene URL zu ermitteln. Die Funktinon ist also recht eingeschränkt. Ich muss für meine Anwendung wissen wie die zurückgelieferte URL denn nun genau gelautet hat. Habe keine Weg gefunden da an die nötige Info zu gelangen.
  Mit Zitat antworten Zitat
Themen-Optionen Tutorial durchsuchen
Tutorial durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 13:19 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz