1
0
mirror of https://bitbucket.org/Dennis07/lina-components.git synced 2024-11-24 08:02:12 +02:00
lina-components/Source/uWebCtrls.pas
Dennis07 1c2743e97b Version 1.0 DEV 1.11
Signed-off-by: Dennis07 <den.goehlert@t-online.de>
2014-10-08 02:09:31 +02:00

351 lines
8.9 KiB
ObjectPascal

unit uWebCtrls;
//////////////////////////////////////
/// Lina Web Controls Unit ///
/// **************************** ///
/// (c) 2014 Dennis Göhlert a.o. ///
//////////////////////////////////////
interface
uses
{ Standard-Units }
SysUtils, Classes,
{ Indy-Units }
idHTTP, idSSLOpenSSL, idComponent,
{ Andere Package-Units }
uBase, uSysTools;
type
{ Fehlermeldungen }
EInvalidWebAddress = class(Exception);
type
{ Ereignisse }
TDownloadWorkEvent = procedure(Sender: TObject; AWorkMode: TWorkMode) of object;
TDownloadWorkBeginEvent = procedure(Sender: TObject; AWorkMode: TWorkMode) of object;
TDownloadWorkEndEvent = procedure(Sender: TObject; AWorkMode: TWorkMode) of object;
type
{ Hilfsklassen }
TWebProtocol = String[8];
TWebProtocols = array[1..5] of TWebProtocol;
type
{ Hauptklassen }
TDownload = class(TComponent)
private
{ Private-Deklarationen }
idHTTPObject: TidHTTP;
SSLHandler: TIdSSLIOHandlerSocketOpenSSL;
FAbout: TComponentAbout;
FAddress: String;
FProgress: Int64;
FProgressMax: Int64;
FSSL: Boolean;
{ Ereignisse }
FWorkEvent: TDownloadWorkEvent;
FWorkBeginEvent: TDownloadWorkBeginEvent;
FWorkEndEvent: TDownloadWorkEndEvent;
{ Methoden }
procedure SetAddress(Value: String);
procedure idHTTPObjectWork(ASender: TObject; AWorkMode: TWorkMode; AWorkCount: Int64);
procedure idHTTPObjectWorkBegin(ASender: TObject; AWorkMode: TWorkMode; AWorkCountMax: Int64);
procedure idHTTPObjectWorkEnd(ASender: TObject; AWorkMode: TWorkMode);
protected
{ Protected-Deklarationen }
procedure Prepare;
public
{ Public-Deklarationen }
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
{ Fortschritt }
function GetProgress: Int64;
function GetProgressMax: Int64;
function GetProgressPercent: Byte;
{ Herunterladen }
function GetText: String;
procedure SaveToFile(const FileName: TFileName);
procedure SaveToStream(var Stream: TStream);
published
{ Published-Deklarationen }
{ Ereignisse }
property OnWork: TDownloadWorkEvent read FWorkEvent write FWorkEvent;
property OnWorkBegin: TDownloadWorkBeginEvent read FWorkBeginEvent write FWorkBeginEvent;
property OnWorkEnd: TDownloadWorkEndEvent read FWorkEndEvent write FWorkEndEvent;
{ Eigenschaften }
property About: TComponentAbout read FAbout;
property Address: String read FAddress write SetAddress;
property SSL: Boolean read FSSL write FSSL default False;
end;
var
WebProtocols: TWebProtocols;
WebProtocolsSimple: TWebProtocols;
WebProtocolsSpecial: TWebProtocols;
procedure InitializeProtocols;
function ValidProtocol(const Protocol: TWebProtocol; const Protocols: TWebProtocols): Boolean;
function StrIsURL(const S: String): Boolean;
procedure Register;
const
{ Web-Protokolle }
WP_HTTP: TWebProtocol = 'http://';
WP_HTTPS: TWebProtocol = 'https://';
WP_FTP: TWebProtocol = 'ftp://';
WP_CALL: TWebProtocol = 'callto:';
WP_MAIL: TWebProtocol = 'mailto:';
{ Meta-Daten }
DownloadComponent_Name = 'Download';
DownloadComponent_Version = 1.0;
DownloadComponent_Copyright = 'Copyright © 2014';
DownloadComponent_Author = 'Dennis Göhlert a.o.';
implementation
procedure Register;
begin
RegisterComponents(ComponentsPage,[TDownload]);
end;
procedure InitializeProtocols;
begin
WebProtocols[1] := WP_HTTP;
WebProtocols[2] := WP_HTTPS;
WebProtocols[3] := WP_FTP;
WebProtocols[4] := WP_CALL;
WebProtocols[5] := WP_MAIL;
WebProtocolsSimple[1] := WP_MAIL;
WebProtocolsSimple[2] := WP_CALL;
WebProtocolsSpecial[1] := WP_HTTP;
WebProtocolsSpecial[2] := WP_HTTPS;
WebProtocolsSpecial[3] := WP_FTP;
end;
function ValidProtocol(const Protocol: TWebProtocol;
const Protocols: TWebProtocols): Boolean;
var
Index: 1..5;
begin
InitializeProtocols;
Result := False;
for Index := Low(Protocols) to High(Protocols) do
begin
if Protocols[Index] = Protocol then
begin
Result := True;
Exit;
end;
end;
end;
function StrIsURL(const S: String): Boolean;
{ Ein einfacher (iterativer) Parser, der überprüfen soll, ob ein String die
Anforderungen an eine URL-Internetadresse erfüllt.
Hier sei gesagt, dass dies KEINE vollständige Prüfung ist, sondern nur die
wichtigsten Kriterien beinhaltet.
Außerdem wird auch nicht überprüft, ob eine Adresse verfügbar ist. }
const
//Diese Zeichen sind zwar erlaubt, dürfen jedoch nicht doppelt hintereinander vorkommen
InvalidDoubleChars = [':','.'];
var
Index: Integer;
DomainLength: Integer;
Protocol: TWebProtocol;
ProtocolValid: Boolean;
DoubleSlashRequired: Boolean;
begin
Result := True;
ProtocolValid := False;
DoubleSlashRequired := False;
DomainLength := 0;
Protocol := '';
for Index := 1 to Length(S) do
begin
if (S[Index] in InvalidDoubleChars) and
(S[Index] = S[Index - 1]) then
begin
Result := False;
Exit;
end;
if (S[Index] in Spaces) or
((S[Index] = ':') and (ProtocolValid = True)) then
begin
Result := False;
Exit;
end;
if ProtocolValid = False then
begin
Protocol := Protocol + S[Index];
if S[Index] = ':' then
begin
ProtocolValid := True;
if ValidProtocol(Protocol,WebProtocolsSimple) = False then
begin
DoubleSlashRequired := True;
Continue;
end;
end;
if S[Index] = '/' then
begin
Result := False;
Exit;
end;
end else
begin
if S[Index] = '/' then
begin
if DoubleSlashRequired = True then
begin
Protocol := Protocol + S[Index];
DoubleSlashRequired := False;
end else
begin
if S[Index - 1] = '/' then
begin
if ValidProtocol(Protocol + S[Index],WebProtocolsSpecial) = False then
begin
Result := False;
Exit;
end else
begin
Protocol := Protocol + S[Index];
end;
end;
end;
end else
begin
if (DoubleSlashRequired = True) or ((S[Index - 1] = '/') and (S[Index - 2] <> '/') and (DomainLength = 0)) then
begin
Result := False;
Exit;
end else
begin
DomainLength := DomainLength + 1;
end;
end;
end;
end;
Result := (ProtocolValid and (DomainLength > 3));
end;
constructor TDownload.Create(AOwner: TComponent);
begin
inherited;
FAbout := TComponentAbout.Create(DownloadComponent_Name,DownloadComponent_Version,DownloadComponent_Copyright,DownloadComponent_Author);
idHTTPObject := TidHTTP.Create(Self);
idHTTPObject.HandleRedirects := True;
idHTTPObject.OnWork := idHTTPObjectWork;
idHTTPObject.OnWorkBegin := idHTTPObjectWorkBegin;
idHTTPObject.OnWorkEnd := idHTTPObjectWorkEnd;
SSLHandler := TIdSSLIOHandlerSocketOpenSSL.Create(Self);
SSL := False;
end;
destructor TDownload.Destroy;
begin
FAbout.Free;
inherited;
end;
procedure TDownload.SetAddress(Value: String);
begin
if (StrIsURL(Value) = True) or (Length(Value) = 0) then
begin
FAddress := Value;
end else
begin
raise EInvalidWebAddress.Create('"' + Value + '" is not a valid URL address');
end;
end;
procedure TDownload.idHTTPObjectWork(ASender: TObject; AWorkMode: TWorkMode; AWorkCount: Int64);
begin
FProgress := AWorkCount;
if Assigned(OnWork) then
begin
OnWork(Self,AWorkMode);
end;
end;
procedure TDownload.idHTTPObjectWorkBegin(ASender: TObject; AWorkMode: TWorkMode; AWorkCountMax: Int64);
begin
FProgressMax := AWorkCountMax;
if Assigned(OnWorkBegin) then
begin
OnWorkBegin(Self,AWorkMode);
end;
end;
procedure TDownload.idHTTPObjectWorkEnd(ASender: TObject; AWorkMode: TWorkMode);
begin
if Assigned(OnWorkEnd) then
begin
OnWorkEnd(Self,AWorkMode);
end;
end;
function TDownload.GetProgress: Int64;
begin
Result := FProgress;
end;
function TDownload.GetProgressMax: Int64;
begin
Result := FProgressMax;
end;
function TDownload.GetProgressPercent: Byte;
begin
if FProgressMax > 0 then
begin
Result := (FProgress div FProgressMax) * 100;
end else
begin
{ Bei aktivierter SSL-Verschlüsselung wird keine insgesamte Dateigröße
übermittelt. Deshalb wird hier eine 0 angegeben, um das Ergebnis nicht
undefiniert zu lassen. }
Result := 0;
end;
end;
function TDownload.GetText: String;
begin
Prepare;
Result := idHTTPObject.Get(Address);
end;
procedure TDownload.SaveToFile(const FileName: TFileName);
var
FS: TFileStream;
begin
Prepare;
FS := TFileStream.Create(FileName,fmCreate or fmShareDenyWrite);
try
idHTTPObject.Get(Address,FS);
finally
FS.Free;
end;
end;
procedure TDownload.SaveToStream(var Stream: TStream);
begin
Prepare;
idHTTPObject.Get(Address,Stream);
end;
procedure TDownload.Prepare;
begin
if SSL = True then
begin
idHTTPObject.IOHandler := SSLHandler;
end else
begin
idHTTPObject := nil;
end;
end;
end.