AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Netzwerke Delphi Indy Http Download+Fortschritt als Funktion geht nicht
Thema durchsuchen
Ansicht
Themen-Optionen

Indy Http Download+Fortschritt als Funktion geht nicht

Ein Thema von Hybrid · begonnen am 19. Apr 2006 · letzter Beitrag vom 20. Nov 2008
Antwort Antwort
Hybrid

Registriert seit: 29. Okt 2005
7 Beiträge
 
#1

Indy Http Download+Fortschritt als Funktion geht nicht

  Alt 19. Apr 2006, 17:44
Hallo erstmal.

Ich habe ein Problem mit diesem Beispiel
http://www.delphipraxis.net/internal...ct.php?t=56872

Ich wollte jetzt nicht den Library Eintrag mit Fragen vollspammen.

Wenn ich aus dem Source der Beim Button-OnClick ausgeführt wird eine neue Prozedur mache und diese dann mit einem Button zweimal hintereinander ausführe bekomm ich immmer einen ReadTimeout vom idHttp.
Wenn ich allerdings nur eine Datei zum Download angebe und dann zweimal auf den Button klicke, geht es...

Sieht vielleicht jemand wo das Problem liegt?


Tut mir Leid wegen dem riesigen Source-Block, aber man kann ja zur Not auch auf "Zusammenfalten" klicken


Hier der Source:
Delphi-Quellcode:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ComCtrls, StdCtrls, IdBaseComponent, IdComponent,
  IdTCPConnection, IdTCPClient, IdHTTP;

type
  THaupt = class(TForm)
    IdHTTP: TIdHTTP;
    Status: TLabel;
    SpeedLabel: TLabel;
    Progress: TProgressBar;
    Button1: TButton;
    procedure IdHTTPWork(Sender: TObject; AWorkMode: TWorkMode;
      const AWorkCount: Integer);
    procedure IdHTTPWorkBegin(Sender: TObject; AWorkMode: TWorkMode;
      const AWorkCountMax: Integer);
    procedure Download(AFile :String);
    procedure Button1Click(Sender: TObject);
  private
    { Private-Deklarationen }
    FTime: Longword; //Beide Variablen werden für die kb/sec anzeige gebraucht
    FBytes: Longword; // --"--
  public
    { Public-Deklarationen }
  end;

var
  Haupt: THaupt;

const
  cFileSplitSize : Int64 = 40*1024; //40 KB größe stücke wird die Datei zerhackt
  URL = 'Http://IrgendWoImNetz/';

implementation

{$R *.dfm}

function GetSizeName(const Size : int64): String;
begin
  Result := 'Fehler';
  if Size = -1 then exit;
  if Size < 1024 then
  begin
    Result := inttostr(Size)+' Byte';
    exit;
  end;
  if (1024 <= Size) and (Size < 1048576) then
  begin
    Result := floattostr((round((Size/1024)*100))/100)+' KB';
    exit;
  end;
  if (1048576 <= Size) and (Size < 1099511627776) then
  begin
    Result := floattostr((round((Size/1048576)*100))/100)+' MB';
    exit;
  end;
  if Size > 1099511627776 then
  begin
    Result := floattostr((round((Size/1099511627776)*100))/100)+' GB';
  end;
end;

procedure THaupt.IdHTTPWorkBegin(Sender: TObject; AWorkMode: TWorkMode;
      const AWorkCountMax: Integer);
begin
  FTime := GetTickCount;
  FBytes := 0;
  Application.ProcessMessages;
end;

procedure THaupt.IdHTTPWork(Sender: TObject; AWorkMode: TWorkMode;
      const AWorkCount: Integer);
begin
  if not((GetTickCount - FTime) <= 0) then
  begin
    try
      SpeedLabel.caption := Format('%.2f KB/s', [(AWorkCount - FBytes) / (GetTickCount - FTime)]);
    except
    end;
  end;
  FTime := GetTickCount;
  FBytes := AWorkCount;
  Application.ProcessMessages;
end;

procedure THaupt.Download(AFile :String);
var
  BytesKopiert, BytesInsgesamt : int64;
  lStream: TFileStream;
begin
  //Initialiesieren
  Status.Caption := '';
  BytesKopiert := 0;
  Progress.Position := 0;
  //In edit 1 steht die downzuladene Datei (z.b. [url]http://www.server.com/datei.dat[/url])
  Status.Caption := 'Prüfe Header';
  // Durch die zwei nächsten Befehle wird die Größe ermittelt und ihn der Variable BytesInsgesamt abgespeichert
  IdHTTP.Head(URL+AFile);
  BytesInsgesamt := IdHTTP.Response.ContentLength;
  //Wenn die Indy Komponente -1 zurückgibt dann bedeutet es des der die Dateigröße nicht zu verfügung
  //stellt uns somit kann die Datei ganz normall heruntergeladen werden (ohne Fortschrittsanzeige)
  if BytesInsgesamt = -1 then
  begin
    Status.Caption := 'Normalles herunterladen';
    Status.Caption := 'Erstelle Datei';
    //In Edit 2 steht welche Datei (z.b. C:\datei.dat)
    //Datei erstellen
    lStream:=TFileStream.Create('.\'+AFile, fmCreate or fmShareDenyNone);
    try
      //und "normal" herunterladen
      idHTTP.Get(URL+AFile, lStream);
    finally
      if Assigned(lStream) then lStream.Free; //FileStream freigeben wenn gesetzt
    end;
    //Alles auf fertig stellen
    Status.Caption := 'Fertig';
    SpeedLabel.caption := 'Fertig';
    exit;
  end;
  //Also wenn wir hier angelangt sind dann bedeutet es der Server hat uns die Dateigröße zur Verfügung gestellt.
  Progress.Max := BytesInsgesamt;
  Status.Caption := 'Erstelle Datei';
  //In Edit 2 steht welche Datei (z.b. C:\datei.dat)
  //Datei erstellen
  lStream:=TFileStream.Create('.\'+AFile, fmCreate or fmShareDenyNone);
  lStream.Position := 0;
  try
    repeat
      // Damit sich das Programm nicht aufhängt
      Application.ProcessMessages;
      //Nun setzen wir den Start nach die bereits kopierten Bytes
      IdHTTP.Request.ContentRangeStart := BytesKopiert;
      //Hier wird gebrüft ob die restlichen Bytes größer sind als cFileSplitSize
      if (BytesInsgesamt-BytesKopiert) > cFileSplitSize then
      begin
        //Hier wird einmal die cFileSplitSize eingestellt
        IdHTTP.Request.ContentRangeEnd := BytesKopiert+cFileSplitSize-1;
      end
      //Den rest der Datei
      else IdHTTP.Request.ContentRangeEnd := BytesInsgesamt;
      Application.ProcessMessages;
      //Den eingesttelten Teil herunterladen und ihn die Datei speichern
      IdHTTP.Get(URL+AFile, lStream);
      //Progress und Status aktualliesieren
      Progress.Position := BytesKopiert;
      Status.Caption := GetSizeName(BytesKopiert)+'/'+GetSizeName(BytesInsgesamt);
      //BytesKopiert weiter setzen
      BytesKopiert := BytesKopiert+cFileSplitSize;
    until (BytesKopiert >= BytesInsgesamt); //Schleife beenden wenn datei fertig
  finally
    if Assigned(lStream) then lStream.Free; //FileStream freigeben wenn gesetzt
  end;
  //Alles auf fertig stellen
  Status.Caption := 'Fertig';
  SpeedLabel.caption := 'Fertig';
  Progress.Position := 100;
end;

procedure THaupt.Button1Click(Sender: TObject);
begin
  download('DateiNr1'); // Meine Dateien sind im Schnitt 500KB groß
  download('DateiNr2');
end;

end.
Schonmal danke für die Hilfe.
  Mit Zitat antworten Zitat
mestro
(Gast)

n/a Beiträge
 
#2

Re: Indy Http Download+Fortschritt als Funktion geht nicht

  Alt 29. Aug 2006, 21:19
also bei mir läufts.

ich hab nur nen paar schönheitsfehler beseitigt...
Wie das Tauschen der Zeilen
Delphi-Quellcode:
      //BytesKopiert weiter setzen
      BytesKopiert := BytesKopiert+cFileSplitSize;

      //Progress und Status aktualliesieren
      Progress.Position := BytesKopiert;
      Status.Caption := GetSizeName(BytesKopiert)+'/'+GetSizeName(BytesInsgesamt);
oder den Progressbar am ende auf max setzen.
  Progress.Position := BytesInsgesamt; ich habe allerdings festgestellt, das zu kleine Downloadblöcke die geschwindigkeit derbe hemmen.
leider ist das schon bei 100Kb bemerkbar, nur bei 1x DSL wird das leider schon verdammt träge mit der aktuallisierung.
die geschwindigkeitsanziege hingegen ist dabei noch flink unterwegs

hab vorher noch die was mit indy gemacht.

cya
  Mit Zitat antworten Zitat
Benutzerbild von gsh
gsh

Registriert seit: 24. Okt 2004
1.542 Beiträge
 
Delphi XE Architect
 
#3

Re: Indy Http Download+Fortschritt als Funktion geht nicht

  Alt 29. Aug 2006, 22:14
Hi das ist mein CodeLib eintrag ... des nächste mal kannst du mir ruhig eine pn schicken
so ich glaub ich hab deinen fehler gefunden:
lStream:=TFileStream.Create('.\'+AFile, fmCreate or fmShareDenyNone); Des hast du zweimal drinnen ... wenn du die procedure aufrufst dann will er eine Datei auf den Pfad ".\DateiNr1" anlegen, korriger mich wenn ich mich täusche aber das kann nicht gehen. Du musst bei deiner Procedure noch einen zweiten Paramter ein bauen (z.b. "FilePath : String") und dann den Stream mit
lStream:=TFileStream.Create(FilePath, fmCreate or fmShareDenyNone); initialiesieren.

So müsste es gehen
Alex
"Sage nicht alles, was du weißt, aber wisse alles, was du sagst!" Matthias Claudius
"Wer sich über Kritik ärgert, gibt zu, daß er sie verdient hat." Tacitus
  Mit Zitat antworten Zitat
Benutzerbild von Testy
Testy

Registriert seit: 2. Mär 2007
56 Beiträge
 
Delphi 7 Enterprise
 
#4

Re: Indy Http Download+Fortschritt als Funktion geht nicht

  Alt 19. Jul 2007, 10:21
Hallo! Ich will hiermit (siehe Quelltext) eine 513kb Große exe-Datei runterladen! Bei 480kb beendet er den Download und zeigt fertig an! Die Datei die er bis dahin runtergeladen hat, ist 4 MB groß!
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var
  BytesKopiert, BytesInsgesamt : int64;
  lStream: TFileStream;
begin
  //Initialiesieren
  Status.Caption := '';
  BytesKopiert := 0;
  Progressbar1.Position := 0;
  //In edit 1 steht die downzuladene Datei (z.b. [url]http://www.server.com/datei.dat[/url])
  Status.Caption := 'Prüfe Header';
  // Durch die zwei nächsten Befehle wird die Größe ermittelt und ihn der Variable BytesInsgesamt abgespeichert
  IdHTTP1.Head('http://wwww....roject1.exe');
  BytesInsgesamt := IdHTTP1.Response.ContentLength;
  //Wenn die Indy Komponente -1 zurückgibt dann bedeutet es des der die Dateigröße nicht zu verfügung
  //stellt uns somit kann die Datei ganz normall heruntergeladen werden (ohne Fortschrittsanzeige)
  if BytesInsgesamt = -1 then
  begin
    Status.Caption := 'Normalles herunterladen';
    Status.Caption := 'Erstelle Datei';
    //In Edit 2 steht welche Datei (z.b. C:\datei.dat)
    //Datei erstellen
    lStream:=TFileStream.Create('c:\Project1.exe', fmCreate or fmShareDenyNone);
    try
      //und "normal" herunterladen
      idHTTP1.Get('http://www...Project1.exe', lStream);
    finally
      if Assigned(lStream) then lStream.Free; //FileStream freigeben wenn gesetzt
    end;
    //Alles auf fertig stellen
    Status.Caption := 'Fertig';
    Speedlabel.caption := 'Fertig';
    exit;
  end;
  //Also wenn wir hier angelangt sind dann bedeutet es der Server hat uns die Dateigröße zur Verfügung gestellt.
  Progressbar1.Max := BytesInsgesamt;
  Status.Caption := 'Erstelle Datei';
  //In Edit 2 steht welche Datei (z.b. C:\datei.dat)
  //Datei erstellen
  lStream:=TFileStream.Create('c:\Project1.exe', fmCreate or fmShareDenyNone);
  lStream.Position := 0;
  try
    repeat
      // Damit sich das Programm nicht aufhängt
      Application.ProcessMessages;

      //Hier wird gebrüft ob die restlichen Bytes größer sind als cFileSplitSize
      if (BytesInsgesamt-BytesKopiert) > cFileSplitSize then
      begin
        //Hier wird einmal die cFileSplitSize eingestellt
        IdHttp1.Request.ContentRangeEnd := BytesKopiert+cFileSplitSize-1;
      end
      else IdHttp1.Request.ContentRangeEnd := BytesInsgesamt;
      Application.ProcessMessages;
      //Den eingesttelten Teil herunterladen und ihn die Datei speichern
      IdHTTP1.Get('http://www...Project1.exe', lStream);
      //Progress und Status aktualliesieren
      Progressbar1.Position := BytesKopiert;
      Speedlabel.Caption := GetSizeName(BytesKopiert)+'/'+GetSizeName(BytesInsgesamt);
      //BytesKopiert weiter setzen
      BytesKopiert := BytesKopiert+cFileSplitSize;
    until (BytesKopiert >= BytesInsgesamt); //Schleife beenden wenn datei fertig
  finally
    if Assigned(lStream) then lStream.Free; //FileStream freigeben wenn gesetzt
  end;
  //Alles auf fertig stellen
  Status.Caption := 'Fertig';
  Status.caption := 'Fertig';
  Progressbar1.Position := 100;
end;
Wäre super wenn ihr mir helfen könnt!

Danke!
  Mit Zitat antworten Zitat
Benutzerbild von gsh
gsh

Registriert seit: 24. Okt 2004
1.542 Beiträge
 
Delphi XE Architect
 
#5

Re: Indy Http Download+Fortschritt als Funktion geht nicht

  Alt 19. Jul 2007, 16:00
schau dir des tutorial noch mal an
hab was ändern muss da die indys aus irgendeinen grund des nicht mehr auf diese weiße unterstützen wie du hast
Alex
"Sage nicht alles, was du weißt, aber wisse alles, was du sagst!" Matthias Claudius
"Wer sich über Kritik ärgert, gibt zu, daß er sie verdient hat." Tacitus
  Mit Zitat antworten Zitat
Benutzerbild von Testy
Testy

Registriert seit: 2. Mär 2007
56 Beiträge
 
Delphi 7 Enterprise
 
#6

Re: Indy Http Download+Fortschritt als Funktion geht nicht

  Alt 20. Jul 2007, 07:39
Habe ich versucht. Aber ich bekomme hier
IdHttp.Request.Range := Format('%d-%d', [BytesInsgesamt, (BytesKopiert+cFileSplitSize-1)]); das er Range nicht kennt (unbekannter Bezeichner)!
Wenn ich 'Request.ContentRangeEnd' mache, gehts erstmal von der Syntax. Aber mit dem nicht kompletten Download-Problem!

Gruß!
  Mit Zitat antworten Zitat
polarwolf

Registriert seit: 6. Jan 2008
Ort: Bei Hamburg
10 Beiträge
 
Delphi 7 Personal
 
#7

Re: Indy Http Download+Fortschritt als Funktion geht nicht

  Alt 26. Feb 2008, 20:53
Ich habe das programm zum laufen bekommen und das auch mit mehr als 2 Dateien.

Bei mir war das Problem, dass der Header anscheinend nicht neu geladen werden konnte weil der alte noch drine war.
Beim neuladen ga es eine Fehlermeldung.
Also habe ich

idhttp.Request.Clear; vor

idhttp.Head(meineurlplusdatei); gepackt


Für die Copy - Paste Programmierer Hier meine lösung

Delphi-Quellcode:
//Initialiesieren
  Status.Caption := '';
  BytesKopiert := 0;
  Progress.Position := 0;
  Status.Caption := 'Prüfe Header';
  // Durch die zwei nächsten Befehle wird die Größe ermittelt und ihn der Variable BytesInsgesamt abgespeichert
  idhttp.Request.Clear;
  IdHTTP.Head(meineurlplusdatei);
  BytesInsgesamt := IdHTTP.Response.ContentLength;
  //Wenn die Indy Komponente -1 zurückgibt dann bedeutet es des der die Dateigröße nicht zu verfügung
  //stellt uns somit kann die Datei ganz normall heruntergeladen werden (ohne Fortschrittsanzeige)
  if BytesInsgesamt = -1 then
  begin
    Status.Caption := 'Normalles herunterladen';
    Status.Caption := 'Erstelle Datei';
    //Datei erstellen
    lStream:=TFileStream.Create(Hauptprogrammpfadplusdatei, fmCreate or fmShareDenyNone);
    try
      //und "normal" herunterladen
      idHTTP.Get(meineurlplusdatei, lStream);
    finally
      if Assigned(lStream) then lStream.Free; //FileStream freigeben wenn gesetzt
    end;
    //Alles auf fertig stellen
    Status.Caption := 'Fertig';
    SpeedLabel.caption := 'Fertig';
    exit;
  end;
  //Also wenn wir hier angelangt sind dann bedeutet es der Server hat uns die Dateigröße zur Verfügung gestellt.
  Progress.Max := BytesInsgesamt;
  Status.Caption := 'Erstelle Datei';
  //Datei erstellen
  lStream:=TFileStream.Create(Hauptprogrammpfadplusdatei, fmCreate or fmShareDenyNone);
  lStream.Position := 0;
  try
    repeat
      // Damit sich das Programm nicht aufhängt
      Application.ProcessMessages;
      //Nun setzen wir den Start nach die bereits kopierten Bytes
      IdHTTP.Request.ContentRangeStart := BytesKopiert;
      //Hier wird gebrüft ob die restlichen Bytes größer sind als cFileSplitSize
      if (BytesInsgesamt-BytesKopiert) > cFileSplitSize then
      begin
        //Hier wird einmal die cFileSplitSize eingestellt
        IdHTTP.Request.ContentRangeEnd := BytesKopiert+cFileSplitSize-1;
      end
      //Den rest der Datei
      else IdHTTP.Request.ContentRangeEnd := BytesInsgesamt;
      Application.ProcessMessages;
      //Den eingesttelten Teil herunterladen und ihn die Datei speichern
      IdHTTP.Get(meineurlplusdatei, lStream);
      //BytesKopiert weiter setzen
      BytesKopiert := BytesKopiert+cFileSplitSize;

      //Progress und Status aktualliesieren
      Progress.Position := BytesKopiert;
      Status.Caption := GetSizeName(BytesKopiert)+'/'+GetSizeName(BytesInsgesamt);
    until (BytesKopiert >= BytesInsgesamt); //Schleife beenden wenn datei fertig
  finally
    if Assigned(lStream) then lStream.Free; //FileStream freigeben wenn gesetzt
  end;
  //Alles auf fertig stellen
  Status.Caption := 'Fertig';
  SpeedLabel.caption := 'Fertig';
  Progress.Position := BytesInsgesamt;
Martin
  Mit Zitat antworten Zitat
diso

Registriert seit: 21. Sep 2007
6 Beiträge
 
#8

Re: Indy Http Download+Fortschritt als Funktion geht nicht

  Alt 19. Nov 2008, 15:29
warum macht ihr euch das leben schwer?

idHttp.Response.ContentStream.Position gibt an wie viel bytes aktuell gedownloaded sind.

geändertes quellcode:

Delphi-Quellcode:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient, IdHTTP,
  StdCtrls, ComCtrls;

type
  TForm1 = class(TForm)
    Progress: TProgressBar;
    SpeedStatus: TLabel;
    Status: TLabel;
    Edit1: TEdit;
    Edit2: TEdit;
    IdHTTP: TIdHTTP;
    Button1: TButton;
    procedure IdHTTPWork(ASender: TObject; AWorkMode: TWorkMode;
      AWorkCount: Integer);
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    BytesInsgesamt: Integer;
    FTime: Longword; //Beide Variablen werden für die kb/sec anzeige gebraucht
    FBytes: Longword; // --"--
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}
function GetSizeName(const Size : int64): String;
begin
  Result := 'Fehler';
  if Size = -1 then exit;
  if Size < 1024 then
  begin
    Result := inttostr(Size)+' Byte';
    exit;
  end;
  if (1024 <= Size) and (Size < 1048576) then
  begin
    Result := floattostr((round((Size/1024)*100))/100)+' KB';
    exit;
  end;
  if (1048576 <= Size) and (Size < 1099511627776) then
  begin
    Result := floattostr((round((Size/1048576)*100))/100)+' MB';
    exit;
  end;
  if Size > 1099511627776 then
  begin
    Result := floattostr((round((Size/1099511627776)*100))/100)+' GB';
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  lStream: TFileStream;
begin
  Status.Caption := 'Prüfe Header';
  Application.ProcessMessages;
  IdHTTP.Head(Edit1.Text);
  BytesInsgesamt := IdHTTP.Response.ContentLength;
  Status.Caption := GetSizeName(BytesInsgesamt);
  Progress.Max := BytesInsgesamt;
  Application.ProcessMessages;
  
  lStream:= TFileStream.Create(Edit2.Text, fmCreate);
  
  idHTTP.Get(edit1.Text, lStream);

  lStream.Free;
  progress.Position := progress.Max;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
edit2.Text := ExtractFilePath(ParamStr(0))+'Test.Dat';
end;

procedure TForm1.IdHTTPWork(ASender: TObject; AWorkMode: TWorkMode;
  AWorkCount: Integer);
begin
  if not((GetTickCount - FTime) <= 0) then
  begin
    try
      SpeedStatus.caption := Format('%.2f KB/s', [(AWorkCount - FBytes) / (GetTickCount - FTime)]);
    except
    end;
  end;
  FTime := GetTickCount;
  FBytes := AWorkCount;
  Progress.Position := idHttp.Response.ContentStream.Position;
  Application.ProcessMessages;
end;

end.
  Mit Zitat antworten Zitat
Benutzerbild von inherited
inherited

Registriert seit: 19. Dez 2005
Ort: Rosdorf
2.022 Beiträge
 
Turbo Delphi für Win32
 
#9

Re: Indy Http Download+Fortschritt als Funktion geht nicht

  Alt 19. Nov 2008, 15:52
idHttp.Response.ContentStream.Position
Ist das Threadsafe?
Nikolai Wyderka

SWIM SWIM HUNGRY!
Neuer Blog: hier!
  Mit Zitat antworten Zitat
Volle

Registriert seit: 25. Nov 2003
Ort: Stuttgart
100 Beiträge
 
Delphi 7 Personal
 
#10

Re: Indy Http Download+Fortschritt als Funktion geht nicht

  Alt 20. Nov 2008, 06:41
Hoi,

nur mal ne frage am rande:

warum verwendet ihr nicht einfach aWorkcount und Aworkcountmax?
ich denke das ist immernoch die einfachste variante oder?
cYa n' sTay [ S ! C ]
  Mit Zitat antworten Zitat
Antwort Antwort


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 09:40 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