unit ftpprothandler; {$IFDEF FPC} {$mode delphi}{$H+} {$ENDIF} interface uses {$IFNDEF NO_FTP} IdFTP, IdFTPList, //for some diffinitions with FTP list IdAllFTPListParsers, //with FTP, this links in all list parsing classes. IdFTPListParseTandemGuardian, //needed ref. to TIdTandemGuardianFTPListItem property IdFTPListTypes, //needed for ref. to TIdUnixBaseFTPListItem property IdFTPListParseVMS, //needed for ref. to TIdVMSFTPListItem property ; IdIOHandler, IdTCPConnection, IdIOHandlerStack, {$ifdef usezlib} IdCompressorZLib, //for deflate FTP support {$endif} IdLogEvent, //for logging component {$ENDIF} prothandler, Classes, SysUtils, IdURI; {$IFDEF VER200} {$DEFINE STRING_IS_UNICODE} // 'String' type is Unicode now {$ENDIF} {$IFDEF VER210} {$DEFINE STRING_IS_UNICODE} // 'String' type is Unicode now {$ENDIF} {$IFDEF VER220} {$DEFINE STRING_IS_UNICODE} // 'String' type is Unicode now {$ENDIF} type TFTPProtHandler = class(TProtHandler) protected FPort : Boolean; {$IFNDEF NO_FTP} procedure OnSent(ASender: TComponent; const AText: string; const AData: string); procedure OnReceived(ASender: TComponent; const AText: string; const AData: string); procedure MakeHTMLDirTable(AURL : TIdURI; AFTP : TIdFTP); procedure OnDataChannelCreating(ASender: TObject; ADataChannel: TIdTCPConnection); procedure OnDataChannelDestroy(ASender: TObject; ADataChannel: TIdTCPConnection); procedure OnDirParseStart(ASender : TObject); procedure OnDirParseEnd(ASender : TObject); {$ENDIF} public class function CanHandleURL(AURL : TIdURI) : Boolean; override; procedure GetFile(AURL : TIdURI); override; constructor Create; property Port : Boolean read FPort write FPort; end; implementation uses IdGlobal; class function TFTPProtHandler.CanHandleURL(AURL : TIdURI) : Boolean; begin {$IFDEF NO_FTP} Result := False; {$ELSE} Result := UpperCase(AURL.Protocol)='FTP'; {$ENDIF} end; constructor TFTPProtHandler.Create; begin inherited Create; FPort := False; end; procedure TFTPProtHandler.GetFile(AURL : TIdURI); {$IFDEF NO_FTP} begin {$ELSE} //In this procedure, URL handling has to be done manually because the //the FTP component does not handle URL's at all. var LStr : TMemoryStream; LIO : TIdIOHandlerStack; LF : TIdFTP; LDI : TIdLogEvent; {$ifdef usezlib} LC : TIdCompressorZLib; {$endif} LIsDir : Boolean; i : Integer; begin LIsDir := False; LDI := TIdLogEvent.Create; LF := TIdFTP.Create; {$ifdef usezlib} LC := TIdCompressorZLib.Create; if LC.IsReady then begin LF.Compressor := LC; end; {$endif} try LDI.Active := True; LDI.LogTime := False; LDI.ReplaceCRLF := False; LDI.OnReceived := OnReceived; LDI.OnSent := OnSent; LIO := TIdIOHandlerStack.Create; LIO.Intercept := LDI; LF.IOHandler := LIO; LF.Passive := not FPort; LF.UseMLIS := True; LF.Host := AURL.Host; LF.Password := AURL.URLDecode(AURL.Password); LF.Username := AURL.URLDecode(AURL.Username); LF.IPVersion := AURL.IPVersion; LF.Password := AURL.Password;; if LF.Username = '' then begin LF.Username := 'anonymous'; LF.Password := 'pass@httpget'; end; if AURL.Document = '' then begin LIsDir := True; end; LStr := TMemoryStream.Create; if FVerbose then begin LF.OnDataChannelCreate := OnDataChannelCreating; LF.OnDataChannelDestroy := OnDataChannelDestroy; LF.OnDirParseStart := OnDirParseStart; LF.OnDirParseEnd := OnDirParseEnd; end; LF.Connect; try LF.ChangeDir(AURL.Path); //The thing is you can't always know if it's a file or dir. if not LIsDir then try LF.Get(AURL.Document,LStr,True); LStr.SaveToFile(AURL.Document); except LIsDir := True; end; if LIsDir then begin LF.List; if FVerbose then begin for i := 0 to LF.ListResult.Count -1 do begin WriteLn({$IFDEF FPC}stdout{$ELSE}output{$ENDIF},LF.ListResult[i]); end; end; MakeHTMLDirTable(AURL,LF); end; finally LF.Disconnect; FreeAndNil(LStr); end; finally FreeAndNil(LF); {$ifdef usezlib} FreeAndNil(LC); {$endif} FreeAndNil(LIO); FreeAndNil(LDI); end; {$ENDIF} end; {$IFNDEF NO_FTP} procedure TFTPProtHandler.MakeHTMLDirTable(AURL : TIdURI; AFTP : TIdFTP); { This routine is in this demo to show users how to use the directory listing from TIdFTP. } var i : integer; LTbl : TStringList; LTmp : String; procedure WriteTableCell(const ACellText : String; AOutput : TStrings); begin if ACellText = '' then begin AOutput.Add('
Name | '); LTbl.Add('Type | '); LTbl.Add('Size | '); LTbl.Add('Date | '); LTbl.Add('Permissions | '); LTbl.Add('Owner | '); LTbl.Add('Group | '); LTbl.Add('
---|---|---|---|---|---|---|