|
@@ -14,17 +14,12 @@
|
|
|
**********************************************************************}
|
|
|
unit fphttpclient;
|
|
|
|
|
|
-{ ---------------------------------------------------------------------
|
|
|
- Todo:
|
|
|
- * Proxy support ?
|
|
|
- ---------------------------------------------------------------------}
|
|
|
-
|
|
|
{$mode objfpc}{$H+}
|
|
|
|
|
|
interface
|
|
|
|
|
|
uses
|
|
|
- Classes, SysUtils, ssockets, httpdefs, uriparser, base64;
|
|
|
+ Classes, SysUtils, ssockets, httpdefs, uriparser, base64, sslsockets;
|
|
|
|
|
|
Const
|
|
|
// Socket Read buffer size
|
|
@@ -42,6 +37,7 @@ Type
|
|
|
// Use this to set up a socket handler. UseSSL is true if protocol was https
|
|
|
TGetSocketHandlerEvent = Procedure (Sender : TObject; Const UseSSL : Boolean; Out AHandler : TSocketHandler) of object;
|
|
|
TSocketHandlerCreatedEvent = Procedure (Sender : TObject; AHandler : TSocketHandler) of object;
|
|
|
+ THTTPVerifyCertificateEvent = Procedure (Sender : TObject; AHandler : TSSLSocketHandler; var aAllow : Boolean) of object;
|
|
|
|
|
|
TFPCustomHTTPClient = Class;
|
|
|
|
|
@@ -79,6 +75,7 @@ Type
|
|
|
FOnHeaders: TNotifyEvent;
|
|
|
FOnPassword: TPasswordEvent;
|
|
|
FOnRedirect: TRedirectEvent;
|
|
|
+ FOnVerifyCertificate: THTTPVerifyCertificateEvent;
|
|
|
FPassword: String;
|
|
|
FIOTimeout: Integer;
|
|
|
FConnectTimeout: Integer;
|
|
@@ -98,6 +95,7 @@ Type
|
|
|
FOnGetSocketHandler : TGetSocketHandlerEvent;
|
|
|
FAfterSocketHandlerCreated : TSocketHandlerCreatedEvent;
|
|
|
FProxy : TProxyData;
|
|
|
+ FVerifySSLCertificate: Boolean;
|
|
|
function CheckContentLength: Int64;
|
|
|
function CheckTransferEncoding: string;
|
|
|
function GetCookies: TStrings;
|
|
@@ -113,7 +111,8 @@ Type
|
|
|
Procedure ExtractHostPort(AURI: TURI; Out AHost: String; Out APort: Word);
|
|
|
Procedure CheckConnectionCloseHeader;
|
|
|
protected
|
|
|
-
|
|
|
+ // Called with TSSLSocketHandler as sender
|
|
|
+ procedure DoVerifyCertificate(Sender: TObject; var Allow: Boolean); virtual;
|
|
|
Function NoContentAllowed(ACode : Integer) : Boolean;
|
|
|
// Peform a request, close connection.
|
|
|
Procedure DoNormalRequest(const AURI: TURI; const AMethod: string;
|
|
@@ -305,9 +304,6 @@ Type
|
|
|
// Maximum chunk size: If chunk sizes bigger than this are encountered, an error will be raised.
|
|
|
// Set to zero to disable the check.
|
|
|
Property MaxChunkSize : SizeUInt Read FMaxChunkSize Write FMaxChunkSize;
|
|
|
- // Called On redirect. Dest URL can be edited.
|
|
|
- // If The DEST url is empty on return, the method is aborted (with redirect status).
|
|
|
- Property OnRedirect : TRedirectEvent Read FOnRedirect Write FOnRedirect;
|
|
|
// Proxy support
|
|
|
Property Proxy : TProxyData Read GetProxy Write SetProxy;
|
|
|
// Authentication.
|
|
@@ -319,6 +315,11 @@ Type
|
|
|
Property Connected: Boolean read IsConnected;
|
|
|
// Keep-Alive support. Setting to true will set HTTPVersion to 1.1
|
|
|
Property KeepConnection: Boolean Read FKeepConnection Write SetKeepConnection;
|
|
|
+ // SSL certificate validation.
|
|
|
+ Property VerifySSLCertificate : Boolean Read FVerifySSLCertificate Write FVerifySSLCertificate;
|
|
|
+ // Called On redirect. Dest URL can be edited.
|
|
|
+ // If The DEST url is empty on return, the method is aborted (with redirect status).
|
|
|
+ Property OnRedirect : TRedirectEvent Read FOnRedirect Write FOnRedirect;
|
|
|
// If a request returns a 401, then the OnPassword event is fired.
|
|
|
// It can modify the username/password and set RepeatRequest to true;
|
|
|
Property OnPassword : TPasswordEvent Read FOnPassword Write FOnPassword;
|
|
@@ -330,6 +331,8 @@ Type
|
|
|
Property OnGetSocketHandler : TGetSocketHandlerEvent Read FOnGetSocketHandler Write FOnGetSocketHandler;
|
|
|
// Called after create socket handler was created, with the created socket handler.
|
|
|
Property AfterSocketHandlerCreate : TSocketHandlerCreatedEvent Read FAfterSocketHandlerCreated Write FAfterSocketHandlerCreated;
|
|
|
+ // Called when a SSL certificate must be verified.
|
|
|
+ Property OnVerifySSLCertificate : THTTPVerifyCertificateEvent Read FOnVerifyCertificate Write FOnVerifyCertificate;
|
|
|
end;
|
|
|
|
|
|
|
|
@@ -357,6 +360,10 @@ Type
|
|
|
Property OnHeaders;
|
|
|
Property OnGetSocketHandler;
|
|
|
Property Proxy;
|
|
|
+ Property VerifySSLCertificate;
|
|
|
+ Property AfterSocketHandlerCreate;
|
|
|
+ Property OnVerifySSLCertificate;
|
|
|
+
|
|
|
end;
|
|
|
|
|
|
EHTTPClient = Class(EHTTP);
|
|
@@ -366,8 +373,6 @@ Function DecodeURLElement(Const S : String) : String;
|
|
|
|
|
|
implementation
|
|
|
|
|
|
-uses sslsockets;
|
|
|
-
|
|
|
resourcestring
|
|
|
SErrInvalidProtocol = 'Invalid protocol : "%s"';
|
|
|
SErrReadingSocket = 'Error reading data from socket';
|
|
@@ -585,13 +590,21 @@ end;
|
|
|
|
|
|
function TFPCustomHTTPClient.GetSocketHandler(const UseSSL: Boolean): TSocketHandler;
|
|
|
|
|
|
+Var
|
|
|
+ SSLHandler : TSSLSocketHandler;
|
|
|
+
|
|
|
begin
|
|
|
Result:=Nil;
|
|
|
if Assigned(FonGetSocketHandler) then
|
|
|
FOnGetSocketHandler(Self,UseSSL,Result);
|
|
|
if (Result=Nil) then
|
|
|
If UseSSL then
|
|
|
- Result:=TSSLSocketHandler.GetDefaultHandler
|
|
|
+ begin
|
|
|
+ SSLHandler:=TSSLSocketHandler.GetDefaultHandler;
|
|
|
+ SSLHandler.VerifyPeerCert:=FVerifySSLCertificate;
|
|
|
+ SSLHandler.OnVerifyCertificate:=@DoVerifyCertificate;
|
|
|
+ Result:=SSLHandler;
|
|
|
+ end
|
|
|
else
|
|
|
Result:=TSocketHandler.Create;
|
|
|
if Assigned(AfterSocketHandlerCreate) then
|
|
@@ -945,6 +958,12 @@ begin
|
|
|
end;
|
|
|
end;
|
|
|
|
|
|
+procedure TFPCustomHTTPClient.DoVerifyCertificate(Sender: TObject; var Allow: Boolean);
|
|
|
+begin
|
|
|
+ If Assigned(FOnVerifyCertificate) then
|
|
|
+ FOnVerifyCertificate(Self,Sender as TSSLSocketHandler,Allow);
|
|
|
+end;
|
|
|
+
|
|
|
function TFPCustomHTTPClient.GetCookies: TStrings;
|
|
|
begin
|
|
|
If (FCookies=Nil) then
|