home *** CD-ROM | disk | FTP | other *** search
- unit Ftp;
-
- {
- Monster FTP VCL 0.4.7
- written by Chen Yu (monster)
-
- E-Mail: mftp@21cn.com ICQ UIN: 6740755
- Homepage: http://homepages.msn.com/RedmondAve/mftp/
-
- Suggestions and bug reports are warm welcomed.
-
- Notes:
-
- * You can use it free because it is terms of the GNU Library
- General Public License.
-
- * Original code was based on TStarFTP and TStarSock from Tony BenBrahim's
- freenet 2.0.
-
- * Many thanks to Brad Stowers (http://www.delphifreestuff.com/),
- Hector Vega Arvide (hvega@cabonet.net.mx), Chris Godwin,
- Kaufman Alex (http://pages.infinit.net/kaufman/Index.htm) and other people
- who give me a lot of good advise.
-
- * If you modified the code, please send me a copy via email so that
- I can improve the component.
-
- * You can modify mftp.inc to make a special version of Monster FTP
- other than the default one.
-
- * Some methods like FileSetAttr are not supported by all ftp servers.
- }
-
- interface
-
- uses Classes, Windows, Messages, SysUtils, Forms, ExtCtrls,
- WinSock, FtpSock, FtpData, FtpCache, FtpMisc, FtpParse, FtpIndex;
-
- {$I mftp.inc}
-
- const
- FTP_AVAILABLE = WM_USER + 2;
- // FTP_ERROR = WM_USER + 3;
- FTP_READY = WM_USER + 4;
-
- type
- FtpInfo = (ftpServerConnected, ftpServerDisconnected, ftpResolvingAddress,
- ftpTraceIn, ftpTraceOut, ftpAlreadyBusy, ftpSupportResume,
- {$ifndef NODEBUG}ftpDebug,{$endif} ftpDataTrace, ftpReady, ftpTransferDone,
- ftpDirectoryRefresh, ftpLoggedIn, ftpFileSize,
- ftpStartListing, ftpListingParsed, ftpBannerAvailable,
- ftpNotSupportResume, ftpRetrying, ftpAddressResolved,
- ftpNothing, ftpRetryFinished, ftpSearchStopped,
- ftpTransferPutStart, ftpTransferPutFinish,
- ftpTransferResume, ftpTransferGetStart, ftpTransferGetFinish);
-
- FtpError = (ftpNone, ftpNetworkDown, ftpInvalidAddress, ftpInternalError,
- ftpGeneralWinsockError, ftpConnAborted, ftpConnReset, ftpConnectTimeOut,
- ftpOutofSockets, ftpNetworkUnreachable, ftpAddressNotAvailable,
- ftpConnectionRefused, ftpProtocolError, ftpCanceled, ftpUnknown,
- ftpAddressResolutionError, ftpPrematureDisconnect,
- ftpHostUnreachable, ftpNoServer, ftpNoProxyServer,
- ftpFileOpen, ftpFileWrite, ftpFileRead, ftpFileNotFound,
- ftpTimeOut, ftpServerDown, ftpAccessDenied, ftpDataError,
- ftpResumeFailed, ftpPermissionDenied, ftpBadURL,
- ftpTransferType, ftpTransferPort, ftpTransferFatalPort, ftpTransferGet, ftpTransferPut,
- ftpTransferFatalError, ftpTransferResumeFailed);
-
- TMFtpInfoNeeded = (niAccount, niHost, niLocalFile, niOverwrite,
- niPassword, niUser);
-
- TMFtpTransferType = (AsciiTransfer, BinaryTransfer);
-
- TMFtpLastAction = (ftplaNone, ftplaLOGIN, ftplaCWD, ftplaMKD, ftplaMKDS,
- ftplaRMD, ftplaRMDS, ftplaRM, ftplaRMS, ftplaGETIndexFile,
- ftplaGET, ftplaGETS, ftplaPUT, ftplaPUTS,
- ftplaLIST, ftplaREN, ftplaRENS,
- ftplaCDUP, ftplaResolveLinks,
- ftplaNOOP, ftplaSearch, ftplaTransfer, ftplaTransfers);
-
- TMFtpProxyType = (proxyNone, proxyHost, proxyHostUser, proxyOpen, proxySite,
- proxyUserSite);
-
- TMFtpServerType = (ftpstAutoDetect, ftpstDefault,
- ftpstUNIX, ftpstULTRIX, ftpstClix, ftpstChameleon,
- ftpstNCSA, ftpstQVT, ftpstBSD, ftpstSunOS,
- ftpstVmsMultinet, ftpstVmsUcx, ftpstMVS, ftpstVM, ftpstVMVPS,
- ftpstMSFTP, ftpstNetTerm, ftpstServU, ftpstWFTPD, ftpWarFTPD,
- ftpstNetware, ftpstNetPresenz);
-
- TMFtpInfoEvent = procedure (Sender: TObject; info: FtpInfo; addinfo: String) of object;
- TMFtpErrorEvent = procedure (Sender: TObject; error: FtpError; addinfo: String) of object;
- TMFtpFileFoundEvent = procedure (Sender: TObject; FileFound: MFtpFileInfo; Location: String; Directory: Boolean) of object;
- TMFtpInfoNeededEvent = procedure (Sender: TObject; need: TMFtpInfoNeeded; var Value: String) of object;
-
- TFtpProc = procedure(Line: String) of object;
-
- TMFtpBFParm = record
- Depth: Integer;
- ScanSymLink: Boolean;
- StartDir: String;
- WildCard: String;
- end;
-
- TMFtp = class(TMSocket)
- private
- pcount: Integer;
- NTimer: TTimer;
-
- {$ifdef USE_RETRYING_TIMER}
- RTimer: TTimer;
- {$endif}
-
- FBusy: Boolean;
- FDBusy: Boolean;
- FMBusy: Boolean;
- FMFinished: Boolean;
- FMAborted: Boolean;
- FMultiThreaded: Boolean;
-
- URLMode: Integer;
- FUrl: String;
-
- FtpServer: String;
- FtpPort: Integer;
- FProxyServer: String;
- FProxyPort: Integer;
- FPassive: Boolean;
- FProxyType: TMFtpProxyType;
-
- FSupportResume: Boolean;
- FSupportNOOP: Boolean;
- FSupportSize: Boolean;
-
- FUser, FPass, FAcct: String;
- FPUser, FPPass: String;
-
- FRetries: Integer;
- FRetryI: Word;
- FRemain: Integer;
-
- FList, TempList, Visited: TStrings;
- FBFParm: TMFtpBFParm;
-
- FSP: Integer;
-
- FFiles: TMFtpFileInfoList;
- FDirectories: TMFtpFileInfoList;
- TFiles: TMFtpFileInfoList;
- TDirectories: TMFtpFileInfoList;
-
- FFile: String;
- FIFile: String;
- FSelection: String;
- FDirectory: String;
- FCDirectory: String;
- FIDirectory: String;
- FSDirectory: String;
-
- FFileMask: String;
-
- FCache: Boolean;
- FCacheE: Integer;
- FFromCache: Boolean;
-
- FType: TMFtpServerType;
-
- FMode: TMFtpTransferType;
-
- Bytes, TrTime, StartTime: Longword;
-
- TotalBytesToSend: Longint;
- FStartPoint: Integer;
-
- FtpInfoEvt: TMFtpInfoEvent;
- FOnError: TMFtpErrorEvent;
- FOnFileFound: TMFtpFileFoundEvent;
- FOnReady: TNotifyEvent;
- NeedInfo: TMFtpInfoNeededEvent;
-
- NextP, PassiveP: TFtpProc;
-
- Intermediate: Boolean;
- Response: String;
- PartialLine: String;
- DataPartialLine: String;
- FLastLine: String;
-
- FBanner: TStrings;
- FBannerStore: String;
-
- ControlLoggedIn: Boolean;
- ControlConnected: Boolean;
- FDoingListing: Boolean;
- FSuccess: Boolean;
- FTransferSuccess: Boolean;
- FAsync: Boolean;
- FileOpened: Boolean;
- DataConnected: Boolean;
- OnHold, TransferAborted: Boolean;
- Aborted, BAborted,
- {$ifndef USE_RETRYING_TIMER}
- SRetry: Boolean;
- {$endif}
-
- Rnto: String;
- DataFile: TFileStream;
-
- FVersion, DummyS: String;
-
- TransMode: String;
- FTransferToFtp: TMFtp;
- FTransferFromFtp: TMFtp;
- FTransferResume: Boolean;
- FSourceName, FTargetName: String;
- FTransferCounter, TempInt: Integer;
-
- OprDir: String;
-
- FLoggedIn, FDirectoryChanged,
- FDirectoryCreated, FFileRenamed,
- FDirectoryDeleted, FFileDeleted,
- FIndexFileReceived, FFileReceived,
- FFtpQuit, FFtpBusy, FAborted,
- FFileStored, FListingDone, FResolved,
- FFileTransferred: TNotifyEvent;
- FtpLastAction: TMFtpLastAction;
- ReadyPort, ReadyMain,
- ReadyCWD, ReadyList: Boolean;
-
- InBuffer: Array [0..IN_BUFFER_SIZE] of Char;
- OutBuffer: Array [0..OUT_BUFFER_SIZE] of Char;
-
- ListeningSocket,
- DataSocket: TMSocket;
-
- FError: FtpError;
- errs: String;
-
- CurrentMode: String;
-
- DownloadSize: Integer;
- UploadSize: Integer;
-
- NOnFtpError: Array [1..MAX_HANDLERS] of TMFtpErrorEvent;
- NOnFtpInfo: Array [1..MAX_HANDLERS] of TMFtpInfoEvent;
- NEvents: Array [1..EVENT_COUNT, 1..MAX_HANDLERS] of TNotifyEvent;
-
- function CheckError: Boolean;
- function CheckStatus: Boolean;
-
- procedure DataDoListing(sender: TObject);
- procedure DataListConnected(sender: TObject);
- procedure DataListDisconnected(sender: TObject);
- procedure DataRetrFile(sender: TObject);
- procedure DataStorFile(sender: TObject); {BDS}
- procedure DataFileDisconnected(sender: TObject);
- procedure DataStorConnected(sender: TObject);
-
- procedure Proceed(Line: String; P: TFtpProc);
- procedure FtpProcess(Line: String);
- procedure LoginMain;
-
- procedure UpdateCache;
-
- procedure MyCloseFile;
- function MyEOF: Boolean;
-
- procedure NTimerTimer(Sender: TObject);
-
- {$ifdef USE_RETRYING_TIMER}
- procedure RTimerTimer(Sender: TObject);
- {$endif}
-
- procedure SetInterval(I: Word);
- function GetInterval: Word;
-
- function GetStartPoint: Longword;
-
- procedure SetAsync(B: Boolean);
- procedure SetRetries(I: Integer);
- procedure SetTransferMode(M: String; P: TFtpProc);
-
- procedure UserMessageHandler(var Message: TMessage);
-
- procedure DoFtpInfo(info: FtpInfo; add: String = '');
- procedure DoFtpError(e: FtpError);
- procedure Ready;
-
- function SetupDataPort: String;
- procedure SetupDataPortPassive(S: String);
-
- procedure DoRetry;
- procedure DidConnect(Sender: TObject);
- procedure DoDisconnect(Sender: TObject);
- procedure DoRead(Sender: TObject);
- function RecvText: String;
-
- function GetUrl: String;
- procedure SetUrl(S: String);
-
- procedure RefreshB;
-
- procedure FatalError(e: FtpError);
- procedure TimedOut(Sender: TObject);
-
- procedure fpChmod(Line: String);
-
- procedure fpBuildFileList(Flag: Boolean);
-
- procedure fpCWD(Line: String);
- procedure fpCWD2(Line: String);
-
- procedure fpDeleteDirectory(Line: String);
-
- procedure fpDownload(Line: String);
- procedure fpDownload2(Line: String);
- procedure fpDownload3(Line: String);
- procedure fpDownload4a(Line: String);
- procedure fpDownload4b(Line: String);
- procedure fpDownload5a(Line: String);
- procedure fpDownload5b(Line: String);
-
- procedure fpList(Line: String);
- procedure fpList2(Line: String);
- procedure fpList3(Line: String);
-
- procedure fpLogin(Line: String);
- procedure fpLogin2(Line: String);
- procedure fpLogin3(Line: String);
- procedure fpLogin4(Line: String);
- procedure fpLogin5(Line: String);
-
- procedure fpLoginProxyHost(Line: String);
- procedure fpLoginProxyOpen(Line: String);
- procedure fpLoginProxySite(Line: String);
- procedure fpLoginProxySite2(Line: String);
- procedure fpLoginProxySite3(Line: String);
-
- procedure fpNOOP(Line: String);
-
- procedure fpPreparePassive(Line: String);
-
- procedure fpProcessGeneral(Line: String);
-
- procedure fpProcessURL(Line: String);
- procedure fpProcessURL2(Line: String);
- procedure fpProcessURL3(Line: String);
-
- procedure fpQuit(Line: String);
-
- procedure fpRename(Line: String);
- procedure fpRename2(Line: String);
-
- procedure fpResolveLinks(Line: String);
-
- procedure fpSetinitialDirectory(Line: String);
- procedure fpSetinitialDirectory2(Line: String);
-
- procedure fpTestREST(Line: String);
- procedure fpTestSystemType(Line: String);
-
- procedure fpTransfer(Line: String);
- procedure fpTransfer2(Line: String);
- procedure fpTransfer3(Line: String);
- procedure fpTransfer3b(Line: String);
- procedure fpTransfer4b(Line: String);
- procedure fpTransfer5(Line: String);
- procedure fpTransfer6(Line: String);
- procedure fpTransfer6b(Line: String);
- procedure fpTransfer7b(Line: String);
- procedure fpTransfer8(Line: String);
- procedure fpTransferFinished;
-
- procedure fpUpload(Line: String);
- procedure fpUpload2(Line: String);
- procedure fpUpload3(Line: String);
- procedure fpUpload4a(Line: String);
- procedure fpUpload4b(Line: String);
- procedure fpUpload5a(Line: String);
- procedure fpUpload5b(Line: String);
- protected
- procedure LookupNameDone; override;
-
- function ProcessMessage: Boolean;
- procedure ProcessMessages;
- public
- constructor Create(AOwner: TComponent); override;
- destructor Destroy; override;
-
- procedure BuildFileList(Parameter: TMFtpBFParm);
-
- procedure CreateDirectory(dir: String); overload;
- procedure CreateDirectory(dirs: TStrings); overload;
-
- procedure DeleteDirectory(dir: String); overload;
- procedure DeleteDirectory(dirs: TStrings); overload;
-
- procedure DeleteFile(filename: String); overload;
- procedure DeleteFile(files: TStrings); overload;
-
- procedure GetFile(RemoteFile, LocalFile: String); overload;
- procedure GetFile(RemoteFiles, LocalFiles: TStrings); overload;
-
- procedure MoveFile(filename, newdir: String); overload;
- procedure MoveFile(files: TStrings; newdir: String); overload;
-
- procedure PutFile(LocalFile, RemoteFile: String); overload;
- procedure PutFile(LocalFiles, RemoteFiles: TStrings); overload;
-
- procedure RenameFile(oldname, newname: String); overload;
- procedure RenameFile(oldnames, newnames: TStrings); overload;
-
- procedure TransferFile(SourceFile, TargetFile: String; TargetFTP: TMFtp); overload;
- procedure TransferFile(SourceFiles, TargetFiles: TStrings; TargetFTP: TMFtp); overload;
-
- procedure IssueCommand(Command: String; OnDone: TFtpProc = nil);
- procedure ChangeDirectory(name: String);
- procedure ChangeToParentDirectory;
-
- procedure LoadIndexFile(Filename: String);
- procedure ResolveLinks;
-
- procedure Login;
- procedure Quit;
- procedure Refresh;
-
- procedure Abort;
- procedure StopTransfer; { internal use, do not call it directly }
-
- procedure CallNEvents(EventType: Integer);
-
- procedure FileSetAttr(filename: String;
- OwnerRead, OwnerWrite, OwnerExecute,
- GroupRead, GroupWrite, GroupExecute,
- PublicRead, PublicWrite, PublicExecute: Boolean);
-
- function RegisterNotifyEvent(EventType: Integer; P: TNotifyEvent): Integer;
- function RegisterErrorEvent(P: TMFtpErrorEvent): Integer;
- function RegisterInfoEvent(P: TMFtpInfoEvent): Integer;
-
- procedure UnRegisterNotifyEvent(EventType: Integer; i: Integer);
- procedure UnRegisterErrorEvent(i: Integer);
- procedure UnRegisterInfoEvent(i: Integer);
-
- function FileExists(filename: String): Integer;
- function DirectoryExists(dir: String): Integer;
-
- property Listing: TStrings read FList;
- property Files: TMFtpFileInfoList read FFiles;
- property Directories: TMFtpFileInfoList read FDirectories;
-
- property URL: String read GetUrl write SetUrl;
-
- property BytesTransferred: Longword read Bytes write Bytes;
- property StartPoint: Longword read GetStartPoint;
- property TransferTime: Longword read TrTime;
-
- property Busy: Boolean read FBusy;
- {$warnings off} {avoiding warning here}
- property Connected: Boolean read ControlConnected;
- {$warnings on}
- property DoingListing: Boolean read FDoingListing;
- property FromCache: Boolean read FFromCache;
- property Success: Boolean read FSuccess;
- property SupportResume: Boolean read FSupportResume;
-
- property Error: FtpError read FError;
-
- property CurrentDirectory: String read FDirectory;
- property LastReply: String read FLastLine;
- property Selection: String read FSelection;
- property Banner: TStrings read FBanner;
- published
- property Asynchronous: Boolean read FAsync write SetAsync;
- property MultiThreaded: Boolean read FMultiThreaded write FMultiThreaded;
-
- property NoopInterval: Word read GetInterval write SetInterval;
-
- property Username: String read FUser write FUser;
- property Password: String read FPass write FPass;
- property Account: String read FAcct write FAcct;
- property ProxyUsername: String read FPUser write FPUser;
- property ProxyPassword: String read FPPass write FPPass;
-
- property Retries: Integer read FRetries write SetRetries;
- property RetryInterval: Word read FRetryI write FRetryI;
-
- property ServerType: TMFtpServerType read FType write FType;
- property InitialDirectory: String read FIDirectory write FIDirectory;
-
- property FileMask: String read FFileMask write FFileMask;
-
- property Cache: Boolean read FCache write FCache;
- property CacheExpire: Integer read FCacheE write FCacheE;
-
- property TransferMode: TMFtpTransferType read FMode write FMode;
-
- property ProxyType: TMFtpProxyType read FProxyType write FProxyType;
- property ProxyServer: String read FProxyServer write FProxyServer;
- property ProxyPort: Integer read FProxyPort write FProxyPort;
- property Passive: Boolean read FPassive write FPassive;
-
- property OnFtpInfo: TMFtpInfoEvent read FtpInfoEvt write FtpInfoEvt;
- property OnFtpNeedInfo: TMFtpInfoNeededEvent read NeedInfo write NeedInfo;
- property OnFtpReady: TNotifyEvent read FOnReady write FOnReady;
- property OnFtpError: TMFtpErrorEvent read FOnError write FOnError;
- property OnLoggedIn: TNotifyEvent read FLoggedIn write FLoggedIn;
- property OnDirectoryChanged: TNotifyEvent read FDirectoryChanged write FDirectoryChanged;
- property OnDirectoryCreated: TNotifyEvent read FDirectoryCreated write FDirectoryCreated;
- property OnDirectoryDeleted: TNotifyEvent read FDirectoryDeleted write FDirectoryDeleted;
- property OnFileDeleted: TNotifyEvent read FFileDeleted write FFileDeleted;
- property OnFileFound: TMFtpFileFoundEvent read FOnFileFound write FOnFileFound;
- property OnIndexFileReceived: TNotifyEvent read FIndexFileReceived write FIndexFileReceived;
- property OnFileReceived: TNotifyEvent read FFileReceived write FFileReceived;
- property OnFileStored: TNotifyEvent read FFileStored write FFileStored;
- property OnListingDone: TNotifyEvent read FListingDone write FListingDone;
- property OnFileRenamed: TNotifyEvent read FFileRenamed write FFIleRenamed;
- property OnFtpQuit: TNotifyEvent read FFtpQuit write FFtpQuit;
- property OnFileTransferred: TNotifyEvent read FFileTransferred write FFileTransferred;
- property OnFtpBusy: TNotifyEvent read FFtpBusy write FFtpBusy;
- property OnAborted: TNotifyEvent read FAborted write FAborted;
- property OnResolvedLinks: TNotifyEvent read FResolved write FResolved;
-
- property Version: String read FVersion write DummyS;
-
- {provided by TMSock}
- property Port;
- property Server;
- property TimeOut;
- end;
-
- const
- WM_Proceed = WM_USER + 1;
-
- implementation
-
- {$R *.res}
-
- constructor TMFtp.Create;
- begin
- inherited Create(AOwner);
-
- NTimer := TTimer.Create(Self);
- SetInterval(30);
-
- {$ifdef USE_RETRYING_TIMER}
- RTimer := TTimer.Create(Self);
- {$endif}
-
- FList := TStringList.Create;
- FBanner := TStringList.Create;
-
- FDirectories := TMFtpFileInfoList.Create;
- FFiles := TMFtpFileInfoList.Create;
- TDirectories := TMFtpFileInfoList.Create;
- TFiles := TMFtpFileInfoList.Create;
-
- ListeningSocket := TMSocket.Create(Self);
- DataSocket := TMSocket.Create(Self);
-
- NTimer.OnTimer := NTimerTimer;
-
- {$ifdef USE_RETRYING_TIMER}
- RTimer.OnTimer := RTimerTimer;
- {$endif}
-
- CustomMessage := UserMessageHandler;
-
- FVersion := 'Monster FTP 0.4.7';
-
- CurrentMode := '';
- URLMode := 0;
-
- FFromCache := False;
-
- FMFinished := True;
- FMAborted := False;
-
- BAborted := False;
-
- OnConnected := DidConnect;
- OnDisconnected := DoDisconnect;
- OnReadReady := DoRead;
- OnTimeOut := TimedOut;
-
- {fill in default values}
- FUser := 'anonymous';
- FPass := 'guest@mftp.org';
- Port := 21;
- FProxyPort := 21;
- FProxyType := proxyNone;
- FMode := BinaryTransfer;
- FCache := True;
- FCacheE := 7;
- FAsync := True;
- FRetries := 3;
- FRetryI := 15;
- FMultiThreaded := False;
- end;
-
- destructor TMFtp.Destroy;
- begin
- DataSocket.Destroy;
- ListeningSocket.Destroy;
- CloseSocket(Socket);
-
- FreeAndNil(FList);
- FreeAndNil(FBanner);
-
- FFiles.MyFree;
- FDirectories.MyFree;
- TFiles.MyFree;
- TDirectories.MyFree;
-
- FreeAndNil(NTimer);
-
- {$ifdef USE_RETRYING_TIMER}
- FreeAndNil(RTimer);
- {$endif}
-
- inherited Destroy;
- end;
-
- procedure TMFtp.UserMessageHandler;
- begin
- case Message.Msg of
- FTP_AVAILABLE:
- begin
- FBusy := False;
- NTimer.Enabled := False;
- ControlLoggedIn := False;
-
- if Assigned(FFtpQuit) then FFtpQuit(Self);
- CallNEvents(8);
-
- if UrlMode = 1 then Login;
- end;
- // FTP_ERROR: if Assigned(FOnError) then FOnError(Self, FtpError(Message.WParam), 'Error');
- FTP_READY:
- begin
- if FMFinished then
- begin
- FBusy := False;
- NTimer.Enabled := True;
-
- if FMAborted then
- begin
- FMAborted := False;
- if Assigned(FAborted) then FAborted(Self);
- CallNEvents(13);
- end;
-
- if Assigned(FOnReady) then FOnReady(Self);
- CallNEvents(9);
- end
- else
- FMBusy := False;
-
- if TransferAborted then
- begin
- DataSocket.Disconnect;
- ListeningSocket.Disconnect;
- TransferAborted := False;
- end;
- case FtpLastAction of
- ftplaLogin:
- begin
- FtpLastAction := ftplaNone;
- ControlLoggedIn := True;
- SRetry := True;
- if Assigned(FLoggedIn) then FloggedIn(Self);
- CallNEvents(11);
- end;
- ftplaCDUP, ftplaCWD:
- begin
- FtpLastAction := ftplaNone;
- if Assigned(FDirectoryChanged) then FDirectoryChanged(Self);
- CallNEvents(1);
- end;
- ftplaMKD, ftplaMKDS:
- begin
- if FMFinished then
- begin
- FtpLastAction := ftplaNone;
- if Assigned(FDirectoryCreated) then FDirectoryCreated(Self);
- CallNEvents(2);
- end;
- end;
- ftplaRMD, ftplaRMDS:
- begin
- if FMFinished then
- begin
- FtpLastAction := ftplaNone;
- if Assigned(FDirectoryDeleted) then FDirectoryDeleted(Self);
- CallNEvents(3);
- end;
- end;
- ftplaRM, ftplaRMS:
- begin
- if FMFinished then
- begin
- FtpLastAction := ftplaNone;
- if Assigned(FFileDeleted) then FFileDeleted(Self);
- CallNEvents(4);
- end;
- end;
- ftplaGETIndexFile:
- begin
- FtpLastAction := ftplaNone;
- if ParseIndexFile(FIFile, FDirectories, FFiles) then
- begin
- UpdateCache;
-
- if Assigned(FIndexFileReceived) then FIndexFileReceived(Self);
- CallNEvents(14);
- end;
- end;
- ftplaGET, ftplaGETS:
- begin
- if FMFinished then
- begin
- FtpLastAction := ftplaNone;
- if Assigned(FFileReceived) then FFileReceived(Self);
- CallNEvents(5);
- end;
- end;
- ftplaPUT, ftplaPUTS:
- begin
- if FMFinished then
- begin
- FtpLastAction := ftplaNone;
- if Assigned(FFileStored) then FFileStored(Self);
- CallNEvents(7);
- end;
- end;
- ftplaLIST:
- begin
- FtpLastAction := ftplaNone;
-
- if not FFromCache then
- begin
- FFiles.Assign(TFiles);
- FDirectories.Assign(TDirectories);
- UpdateCache;
- end;
-
- if Assigned(FListingDone) then FListingDone(Self);
- CallNEvents(10);
- end;
- ftplaREN, ftplaRENS:
- begin
- if FMFinished then
- begin
- if Assigned(TempList) then FreeAndNil(TempList); // Clear tempoary file list that used by method MoveFile
-
- FtpLastAction := ftplaNone;
- if Assigned(FFileRenamed) then FFileRenamed(Self);
- CallNEvents(6);
- end;
- end;
- ftplaResolveLinks:
- begin
- FtpLastAction := ftplaNone;
- UpdateCache;
- Proceed('CWD '+ FCDirectory, fpCWD);
-
- if Assigned(FResolved) then FResolved(Self);
- CallNEvents(15);
- end;
- ftplaSearch:
- begin
- ReadyCWD := False;
- Proceed('CWD ' + FSDirectory, fpCWD);
- while not ReadyCWD do ProcessMessages;
-
- FtpLastAction := ftplaNone;
- FreeAndNil(Visited);
-
- if BAborted then
- begin
- BAborted := False;
- if Assigned(FAborted) then FAborted(Self);
- CallNEvents(13);
- end;
-
- if not FSuccess then DoFtpInfo(ftpSearchStopped);
- end;
- ftplaTransfer, ftplaTransfers:
- begin
- if FMFinished then
- begin
- FtpLastAction := ftplaNone;
- if Assigned(FFileTransferred) then FFileTransferred(Self);
- CallNEvents(16);
- end;
- end;
- end;
- end;
- end;
- end;
-
- procedure TMFtp.DoFtpInfo;
- var hs: Integer;
- S: String;
- begin
- if add = '' then
- begin
- case info of
- ftpAlreadyBusy:
- S := msgBusy;
- ftpLoggedIn:
- S := msgLogin;
- ftpNotSupportResume:
- S := msgNResume;
- ftpSearchStopped:
- S := msgSearchStopped;
- ftpServerDisconnected:
- S := msgEDisconnected;
- end;
- end
- else
- begin
- if (info = ftpTraceOut) and (Copy(add, 1, 5) = 'PASS ') then
- begin
- S := msgIDontTellYou;
- end
- else
- begin
- S := add;
- end;
- end;
-
- if Assigned(FtpInfoEvt) then FtpInfoEvt(Self, info, S);
- for hs := 1 to MAX_HANDLERS do
- if Assigned(NOnFtpInfo[hs]) then NOnFtpInfo[hs](Self, info, S);
- end;
-
- procedure TMFtp.DoFtpError;
- var hs: Integer;
- begin
- FSuccess := False;
- FError := e;
- // PostMessage(Handle,FTP_ERROR,Ord(e), 0);
- if Assigned(FOnError) then FOnError(Self, e, errs);
- for hs := 1 to MAX_HANDLERS do
- if Assigned(NOnFtpError[hs]) then NOnFtpError[hs](Self, e, errs);
- errs := '';
- end;
-
- procedure TMFtp.Ready;
- begin
- NextP := nil;
- PostMessage(Handle, FTP_READY, 0, 0);
- end;
-
- procedure TMFtp.Login;
- begin
- FRemain := FRetries;
- FBusy := False;
- ControlLoggedIn := False;
-
- LoginMain;
- end;
-
- procedure TMFtp.LoginMain;
- var S: String;
- begin
- FDBusy := False;
- if FBusy then
- begin
- DoFtpInfo(ftpAlreadyBusy);
- Exit;
- end;
-
- LastError := 0;
- FDirectory := '';
- Response := '';
- FError := FtpNone;
- FSuccess := True;
- Intermediate := False;
- FSupportSIZE := True;
- FSupportNOOP := True;
-
- Dec(FRemain);
- ReCreateTCPSocket;
-
- if Trim(FProxyServer) = '' then FProxyType := proxyNone else
- if FProxyType <> proxyNone then
- begin
- FtpServer := Server;
- FtpPort := Port;
- Server := FProxyServer;
- Port := FProxyPort;
- end;
-
- if Trim(Server) = '' then
- begin
- if Assigned(NeedInfo) then NeedInfo(Self, niHost, s);
- s := Trim(s);
- if s = '' then
- begin
- DoFtpError(ftpNoServer);
- Ready;
- Exit;
- end;
- SetServer(s);
- end;
-
- if Port = 0 then Port := 21;
-
- if Address <> '' then FillAddress(Address)
- else
- begin
- DoFtpInfo(ftpResolvingAddress, Host);
- LookupName(Host);
- CheckError;
- Exit;
- end;
- FillPort(Port);
- Connect;
- CheckError;
- end;
-
- procedure TMFtp.LookupNameDone;
- begin
- if CheckError then Exit;
- FillName;
- FillPort(Port);
- Address := GetAddressString;
- DoFtpInfo(ftpAddressResolved, Address);
- Connect;
- CheckError;
- end;
-
- procedure TMFtp.UpdateCache;
- begin
- if {(FFileMask = '') and }(FSuccess) then
- begin
- SaveToCache(GetCacheFilename(Server, FUser, FDirectory, Port, True), FDirectories);
- SaveToCache(GetCacheFilename(Server, FUser, FDirectory, Port, False), FFiles);
- end;
- end;
-
- procedure TMFtp.MyCloseFile;
- begin
- if FileOpened then
- begin
- FileOpened := False;
- FreeAndNil(DataFile);
- end;
- end;
-
- function TMFtp.MyEOF;
- begin
- if (FileOpened) and (Assigned(DataFile)) then
- Result := (DataFile.Position = DataFile.Size)
- else
- Result := True;
- end;
-
- {===== Directory/File managemenet routines =====}
- procedure TMFtp.BuildFileList;
- begin
- if CheckStatus then
- begin
- FtpLastAction := ftplaSearch;
- Visited := TStringList.Create;
-
- FBFParm := Parameter;
- if FBFParm.Depth <= 0 then FBFParm.Depth := MaxInt;
-
- if (FDirectory <> FBFParm.StartDir) and (FBFParm.StartDir <> '') then
- begin
- ReadyCWD := False;
- Proceed('CWD ' + FBFParm.StartDir, fpCWD);
- while not ReadyCWD do ProcessMessages;
- if not FSuccess then
- begin
- Ready;
- Exit;
- end;
- end;
-
- Visited.Add(FDirectory);
- if (FDirectory[1] <> '/') and (FDirectory[1] <> '\') then
- FSDirectory := '/' + FDirectory
- else
- FSDirectory := FDirectory;
-
- Dec(FBFParm.Depth);
- fpBuildFileList(True);
- Inc(FBFParm.Depth);
- end;
- end;
-
- procedure TMFtp.ChangeDirectory;
- begin
- if CheckStatus then
- begin
- FtpLastAction := ftplaCWD;
- Proceed('CWD ' + name, fpCWD);
- while (FBusy) and (not FAsync) do ProcessMessages;
- end;
- end;
-
- procedure TMFtp.ChangeToParentDirectory;
- begin
- if CheckStatus then
- begin
- FtpLastAction := ftplaCDUP;
- Proceed('CDUP', fpCWD);
- while (not FBusy) and (FAsync) do ProcessMessages;
- end;
- end;
-
- procedure TMFtp.CreateDirectory(dir: String);
- begin
- if CheckStatus then
- begin
- FTPLastAction := ftplaMKD;
- Proceed('MKD ' + dir, fpProcessGeneral);
- while (FBusy) and (not FAsync) do ProcessMessages;
- end;
- end;
-
- procedure TMFtp.CreateDirectory(dirs: TStrings);
- var i: Integer;
- begin
- if Assigned(dirs) and (CheckStatus) then
- begin
- FTPLastAction := ftplaMKDS;
- FMFinished := False;
-
- for i := 0 to dirs.Count - 1 do
- begin
- FMBusy := True;
- Proceed('MKD ' + dirs[i], fpProcessGeneral);
- while FMBusy do ProcessMessages;
- end;
-
- FMFinished := True;
- Ready;
- end;
- end;
-
- procedure TMFtp.DeleteDirectory(dir: String);
- begin
- if (dir <> '') and (CheckStatus) then
- begin
- FTPLastAction := ftplaRMD;
- OprDir := Trim(dir);
- Proceed('RMD ' + dir, fpDeleteDirectory);
- while (FBusy) and (not FAsync) do ProcessMessages;
- end;
- end;
-
- procedure TMFtp.DeleteDirectory(dirs: TStrings);
- var i: Integer;
- begin
- if Assigned(dirs) and (CheckStatus) then
- begin
- FTPLastAction := ftplaRMDS;
- FMFinished := False;
-
- for i := 0 to dirs.Count - 1 do
- begin
- FMBusy := True;
- OprDir := Trim(dirs[i]);
- Proceed('RMD ' + dirs[i], fpDeleteDirectory);
- while FMBusy do ProcessMessages;
- end;
-
- FMFinished := True;
- Ready;
- end;
- end;
-
- procedure TMFtp.DeleteFile(filename: String);
- begin
- if (filename <> '') and (CheckStatus) then
- begin
- FTPLastAction := ftplaRM;
- Proceed('DELE ' + filename, fpProcessGeneral);
- while (FBusy) and (not FAsync) do ProcessMessages;
- end;
- end;
-
- procedure TMFtp.DeleteFile(files: TStrings);
- var i: Integer;
- begin
- if Assigned(files) and (CheckStatus) then
- begin
- FTPLastAction := ftplaRMS;
- FMFinished := False;
-
- for i := 0 to files.Count - 1 do
- begin
- FMBusy := True;
- Proceed('DELE ' + files[i], fpProcessGeneral);
- while FMBusy do ProcessMessages;
- end;
-
- FMFinished := True;
- Ready;
- end;
- end;
-
- procedure TMFtp.MoveFile(filename, newdir: String);
- begin
- NewDir := Trim(NewDir);
- if NewDir[Length(NewDir)] <> '/' then NewDir := NewDir + '/';
- RenameFile(FileName, NewDir + ExtractFileName(FileName));
- end;
-
- procedure TMFtp.MoveFile(files: TStrings; newdir: String);
- var i: Integer;
- begin
- if not Assigned(files) then Exit;
- if files.Count < 1 then Exit;
- if not CheckStatus then Exit;
-
- FBusy := False;
- if Assigned(TempList) then TempList.Clear else TempList := TStringList.Create;
-
- NewDir := Trim(NewDir);
- if NewDir[Length(NewDir)] <> '/' then NewDir := NewDir + '/';
-
- for i := 0 to files.Count - 1 do
- TempList.Add(NewDir + ExtractFileName(Files[i]));
-
- RenameFile(files, TempList);
- end;
-
- procedure TMFtp.RenameFile(oldname, newname: String);
- begin
- if (CheckStatus) and (oldname <> '') and (oldname <> newname) then
- begin
- FTPLastAction := ftplaREN;
- Rnto := newname;
- Proceed('RNFR ' + oldname, fpRename);
- while (FBusy) and (not FAsync) do ProcessMessages;
- end;
- end;
-
- procedure TMFtp.RenameFile(oldnames, newnames: TStrings);
- var i: Integer;
- begin
- if Assigned(oldnames) and Assigned(newnames) then
- begin
- if oldnames.Count = newnames.Count then
- begin
- if not CheckStatus then Exit;
- FTPLastAction := ftplaRENS;
- FMFinished := False;
-
- for i := 0 to oldnames.Count - 1 do
- begin
- FMBusy := True;
- Rnto := newnames[i];
- Proceed('RNFR ' + oldnames[i], fpRename);
- while FMBusy do ProcessMessages;
- end;
-
- FMFinished := True;
- Ready;
- end;
- end;
- end;
-
- procedure TMFtp.ResolveLinks;
- begin
- if FDirectories.Count = 0 then Exit;
- if not CheckStatus then Exit;
-
- FSP := 0;
- FCDirectory := FDirectory;
- if FCDirectory[1] <> '/' then FCDirectory := '/' + FCDirectory;
- if FCDirectory[Length(FCDirectory)] <> '/' then FCDirectory := FCDirectory + '/';
-
- while FSP < FDirectories.Count do
- begin
- if (FDirectories[FSP].Filename <> '.') and (FDirectories[FSP].Filename <> '..') and
- (FDirectories[FSP].SymbolLink <> '.') and
- (FDirectories[FSP].SymbolLink <> '..') and
- (FDirectories[FSP].SymbolLink <> '') then Break;
- Inc(FSP);
- end;
-
- if FSP < FDirectories.Count then
- begin
- FtpLastAction := ftplaResolveLinks;
- Proceed('CWD '+ FCDirectory + Directories[0].Filename, fpResolveLinks);
- end
- else
- begin
- Ready;
- end;
- end;
-
- procedure TMFtp.LoadIndexFile;
- begin
- if (not CheckStatus) or (Trim(Filename) = '') then Exit;
-
- FIFile := GetTempFilename;
- FTPLastAction := ftplaGETIndexFile;
-
- GetFile(Filename, FIFile);
- end;
-
- procedure TMFtp.GetFile(RemoteFile, LocalFile: String);
- var p: TFtpProc;
- begin
- if (FTPLastAction <> ftplaGETIndexFile) and (FTPLastAction <> ftplaGETS) then
- begin
- if not CheckStatus then Exit;
- FTPLastAction := ftplaGET;
- end;
-
- FSelection := RemoteFile;
- FFile := LocalFile;
- FStartPoint := 0;
-
- if FSelection = '' then
- begin
- FMBusy := False;
- DoFtpError(ftpFileNotFound);
- Ready;
- Exit;
- end;
-
- if FFile <> '' then
- begin
- try
- if SysUtils.FileExists(FFile) then
- begin
- DataFile := TFileStream.Create(FFile, fmOpenReadWrite + fmShareDenyWrite);
- p := fpDownload;
- end
- else
- begin
- DataFile := TFileStream.Create(FFile, fmCreate);
- PassiveP := fpDownload4b;
- p := fpDownload3;
- end;
-
- FileOpened := True;
- ReadyPort := False;
- ReadyMain := False;
-
- if FMode = BinaryTransfer then
- SetTransferMode('I', p)
- else
- SetTransferMode('A', p);
-
- while (FBusy) and (not FAsync) do ProcessMessages;
- except
- DoFtpError(ftpFileOpen);
- Ready;
- end;
- end
- else
- begin
- FMBusy := False;
- DoFtpError(ftpFileOpen);
- Ready;
- Exit;
- end;
- end;
-
- procedure TMFtp.GetFile(RemoteFiles, LocalFiles: TStrings);
- var i: Integer;
- begin
- if not (Assigned(RemoteFiles) and Assigned(LocalFiles)) then Exit;
- if RemoteFiles.Count <> LocalFiles.Count then Exit;
- if not CheckStatus then Exit;
-
- FTPLastAction := ftplaGETS;
- FMFinished := False;
-
- for i := 0 to RemoteFiles.Count - 1 do
- begin
- FMBusy := True;
- GetFile(RemoteFiles[i], LocalFiles[i]);
- while FMBusy do ProcessMessages;
- end;
-
- FMFinished := True;
- Ready;
- end;
-
- procedure TMFtp.PutFile(LocalFile, RemoteFile: String);
- begin
- if FTPLastAction <> ftplaPUTS then
- begin
- if not CheckStatus then Exit;
- FTPLastAction := ftplaPUT;
- end;
-
- FSelection := RemoteFile;
- FFile := LocalFile;
- FStartPoint := 0;
-
- if FSelection = '' then
- begin
- FMBusy := False;
- DoFtpError(ftpFileNotFound);
- Ready;
- Exit;
- end;
-
- if FFile <> '' then
- begin
- try
- DataFile := TFileStream.Create(FFile, fmOpenRead);
- FileOpened := True;
- except
- FMBusy := False;
- DoFtpError(ftpFileOpen);
- Ready;
- end;
- end
- else
- begin
- FMBusy := False;
- DoFtpError(ftpFileOpen);
- Ready;
- Exit;
- end;
-
- if FMode = BinaryTransfer then
- SetTransferMode('I', fpUpload)
- else
- SetTransferMode('A', fpUpload);
-
- while (FBusy) and (not FAsync) do ProcessMessages;
- end;
-
- procedure TMFtp.PutFile(LocalFiles, RemoteFiles: TStrings);
- var i: Integer;
- begin
- if not (Assigned(RemoteFiles) and Assigned(LocalFiles)) then Exit;
- if RemoteFiles.Count <> LocalFiles.Count then Exit;
- if not CheckStatus then Exit;
-
- FTPLastAction := ftplaPUTS;
- FMFinished := False;
-
- for i := 0 to RemoteFiles.Count - 1 do
- begin
- FMBusy := True;
- PutFile(LocalFiles[i], RemoteFiles[i]);
- while FMBusy do ProcessMessages;
- end;
-
- FMFinished := True;
- Ready;
- end;
-
- procedure TMFtp.TransferFile(SourceFile, TargetFile: String; TargetFTP: TMFtp);
- begin
- FTransferSuccess := False;
-
- FTransferFromFtp := Self;
- FTransferToFtp := TargetFtp;
-
- FSourceName := SourceFile;
- FTargetName := TargetFile;
- FTransferCounter := 0;
-
- if Assigned(FTransferToFtp) then
- begin
- if ((FTransferFromFtp.CheckStatus) and (FTransferToFtp.CheckStatus)) or (FTPLastAction = ftplaTransfers) then
- begin
- if FTPLastAction <> ftplaTransfers then FTPLastAction := ftplaTransfer;
-
- {if CheckSymLink(FSourceName) then
- TransMode := 'A'
- else
- TransMode := 'I';}
-
- TransMode := 'I';
- FTransferFromFtp.SetTransferMode(TransMode, fpTransfer);
- end
- else
- DoFtpError(ftpTransferFatalError);
- end;
- end;
-
- procedure TMFtp.TransferFile(SourceFiles, TargetFiles: TStrings; TargetFTP: TMFtp);
- var i: Integer;
- begin
- if not (Assigned(SourceFiles) and Assigned(TargetFiles)) then Exit;
- if SourceFiles.Count <> TargetFiles.Count then Exit;
- if not ((TargetFTP.CheckStatus) and (CheckStatus)) then Exit;
-
- FTPLastAction := ftplaTransfers;
- FMFinished := False;
-
- for i := 0 to SourceFiles.Count - 1 do
- begin
- FMBusy := True;
- TransferFile(SourceFiles[i], TargetFiles[i], TargetFTP);
- while FMBusy do ProcessMessages;
- end;
-
- FMFinished := True;
- Ready;
- end;
-
- procedure TMFtp.IssueCommand;
- begin
- if Command = '' then
- begin
- NextP := nil;
- Ready;
- Exit;
- end;
-
- if CheckStatus then
- begin
- CurrentMode := '';
-
- if Assigned(OnDone) then
- Proceed(Command, OnDone)
- else
- Proceed(Command, fpProcessGeneral);
- end;
- end;
-
- procedure TMFtp.Refresh;
- var R1, R2: Boolean;
- begin
- FTPLastAction := ftplaLIST;
-
- if FCache then
- begin
- R1 := LoadFromCache(GetCacheFilename(Server, FUser, FDirectory, Port, True), FDirectories, FCacheE);
- R2 := LoadFromCache(GetCacheFilename(Server, FUser, FDirectory, Port, False), FFiles, FCacheE);
-
- if (R1 = True) and (R2 = True) then
- begin
- FFromCache := True;
- Ready;
- Exit;
- end;
- end;
-
- if CheckStatus then
- begin
- FFromCache := False;
- SetTransferMode('A', fpList);
-
- while (FBusy) and (not FAsync) do ProcessMessages;
- end;
- end;
-
- procedure TMFtp.RefreshB;
- begin
- ReadyList := False;
- SetTransferMode('A', fpList);
-
- while (not ReadyList) and (not BAborted) do ProcessMessages;
-
- FFiles.Assign(TFiles);
- FDirectories.Assign(TDirectories);
- UpdateCache;
- end;
-
- procedure TMFtp.Quit;
- begin
- if CheckStatus then Proceed('QUIT', fpQuit);
- end;
-
- procedure TMFtp.fpRename;
- begin
- if Line[1] = '3' then
- begin
- Proceed('Rnto ' + Rnto, fpRename2)
- end
- else
- begin
- errs := msgDenied;
- DoFtpError(ftpPermissionDenied);
- Ready;
- end;
- end;
-
- procedure TMFtp.fpRename2;
- begin
- if Line[1] <> '2' then
- begin
- errs := msgDenied;
- DoFtpError(ftpPermissionDenied);
- end;
-
- Ready;
- end;
-
- procedure TMFtp.fpResolveLinks;
- begin
- if line[1] <> '2' then
- begin
- FFiles.Add(FDirectories[FSP].Filename,
- FDirectories[FSP].Attrib,
- FDirectories[FSP].DateTime,
- FDirectories[FSP].Size,
- FDirectories[FSP].SymbolLink,
- FDirectories[FSP].Owner,
- FDirectories[FSP].Group,
- FDirectories[FSP].Description);
- FDirectories.Delete(FSP);
- end
- else
- begin
- Inc(FSP);
- end;
-
- while FSP < FDirectories.Count do
- begin
- if (FDirectories[FSP].Filename <> '.') and (FDirectories[FSP].Filename <> '..') and
- (FDirectories[FSP].SymbolLink <> '.') and
- (FDirectories[FSP].SymbolLink <> '..') and
- (FDirectories[FSP].SymbolLink <> '') then Break;
- Inc(FSP);
- end;
-
- if FSP < FDirectories.Count then
- Proceed('CWD ' + FCDirectory + FDirectories[FSP].Filename, fpResolveLinks)
- else
- Ready;
- end;
-
- procedure TMFtp.SetUrl;
- var S1, S2, RT, TUser, TPass, TServer: String;
- p, TPort: Integer;
- begin
- try
- if FBusy then
- begin
- DoFtpInfo(ftpAlreadyBusy);
- Exit;
- end;
-
- S := PrepareURL(Trim(S)); {preprocessing the url Line}
-
- RT := LowerCase(Copy(S, 1, 6));
- if RT <> 'ftp://' then
- begin
- errs := msgNSProtocol;
- DoFtpError(ftpBadURL);
- Exit;
- end
- else
- begin
- S1 := '';
- Delete(S, 1, 6);
- p := Pos('@', S);
- if p > 0 then
- begin
- S1 := Copy(S, 1, p - 1);
- Delete(S, 1, p);
- end;
- p := Pos('/', S);
- if p = 0 then
- S2 := ''
- else
- begin
- S2 := Copy(S, p, 999);
- Delete(S, p, 999);
- end;
- if S1 = '' then
- begin
- if FUser = '' then FUser := 'anonymous';
- if FPass = '' then FPass := 'guest@somewhere.on.earth';
- TUser := FUser;
- TPass := FPass;
- end
- else
- begin
- p := Pos(':', S1);
- if p = 0 then
- begin
- errs := msgISytax;
- DoFtpError(ftpBadURL);
- FBusy := False;
- Exit;
- end;
- TUser := Copy(S1, 1, p - 1);
- TPass := Copy(S1, p + 1, 999);
- end;
- p := Pos(':', S);
- if p = 0 then
- begin
- TServer := S;
- TPort := FPort; { useless, just make compiler happy }
- end
- else
- begin
- TServer := Copy(S, 1, p - 1);
- TPort := StrToInt(Copy(S, p + 1, 999));
- end;
- end;
-
- FUrl := S2;
-
- FBusy := True;
- if Assigned(FFtpBusy) then FFtpBusy(Self);
- CallNEvents(12);
-
- if (FUser = TUser) and (FPass = TPass) and (FServer = TServer)
- and (FPort = TPort) and (ControlLoggedIn) then
- begin
- fpProcessURL('299');
- Exit;
- end;
-
- FUser := TUser;
- FPass := TPass;
- Server := TServer;
- FPort := TPort;
-
- if not ControlConnected then
- begin
- URLMode := 2;
- Login;
- end
- else
- begin
- URLMode := 1;
- Proceed('QUIT', fpQuit);
- end;
- except
- errs := msgUEParse;
- DoFtpError(ftpBadURL);
- end;
- end;
-
- function TMFtp.GetUrl;
- var i: Integer;
- begin
- {reformats the url, extra information(username, password etc.) is excluded}
- if FPort = 21 then
- Result := 'ftp://' + Server + '/'
- else
- Result := 'ftp://' + Server + ':' + IntToStr(Port) + '/';
-
- if FDirectory = '' then Exit;
- if FDirectory = '/' then Exit;
- if FDirectory[1] = '/' then Delete(FDirectory, 1, 1);
-
- Result := Result + FDirectory;
-
- i := Length(Result);
- if Result[i] <> '/' then Result := Result + '/';
- end;
-
- procedure TMFtp.Proceed;
- var data: String;
- begin
- data := Line + #13#10;
-
- DoFtpInfo(ftpTraceOut, data);
- while data <> '' do
- begin
- ProcessMessages;
- Delete(data, 1, SendBuf(PChar(@data[1]), Length(data)));
- if (CheckError) or (Aborted) or (not Connected) then
- begin
- ReadyCWD := True;
- Exit;
- end;
- end;
-
- NextP := P;
- end;
-
- procedure TMFtp.DidConnect;
- begin
- if CheckError then Exit;
-
- DoFtpInfo(ftpServerConnected, Address);
-
- ControlConnected := True;
- OnHold := False;
-
- PartialLine := '';
- NextP := fpLogin;
- end;
-
- procedure TMFtp.TimedOut;
- begin
- errs := 'Connection timed out';
- FatalError(ftpConnectTimeOut);
- end;
-
- procedure TMFtp.DoRetry;
- {$ifndef USE_RETRYING_TIMER}
- var ST: Longword;
- {$endif}
- begin
- if FRemain < 0 then
- begin
- DoFTPInfo(ftpRetryFinished, 'Retry Finished');
- SRetry := True;
- Exit;
- end;
-
- {$ifdef USE_RETRYING_TIMER}
- if (not ControlLoggedIn) and (FRemain >= 0) and (FError <> ftpNone) then
- begin
- // DoFTPInfo(ftpRetrying, msgRetry + IntToStr(FRetryI) + ' Seconds..'); {mEga}
- DoFTPInfo(ftpRetrying, msgRetry);
-
- FDBusy := True;
-
- if FRetryI > 0 then
- begin
- RTimer.Interval := FRetryI * 1000;
- RTimer.Enabled := True;
- end;
- end;
- {$else}
- if (not ControlLoggedIn) and (FRemain >= 0) and (FError <> ftpNone) then
- begin
- // DoFTPInfo(ftpRetrying, msgRetry + IntToStr(FRetryI) + ' Seconds..'); {mEga}
- DoFTPInfo(ftpRetrying, msgRetry);
-
- FDBusy := True;
- SRetry := False;
-
- if FRetryI > 0 then
- begin
- ST := GetTickCount;
- while GetTickCount - ST < FRetryI * 1000 do
- begin
- if SRetry then
- Break
- else
- ProcessMessages;
- end;
- end;
- if not SRetry then
- begin
- LoginMain;
- Exit;
- end;
- end;
- {$endif}
- end;
-
- procedure TMFtp.DoDisconnect;
- procedure RealDoDisconnect;
- begin
- ControlConnected := False;
- DoFTPInfo(ftpServerDisconnected, msgDisconnected);
- PostMessage(Handle, FTP_AVAILABLE, 0, 0);
- FtpLastAction := ftplaNone;
- ReadyList := True;
- Ready;
- end;
- begin
- if FDBusy then Exit;
- DoRetry;
- if SRetry then RealDoDisconnect;
- end;
-
- procedure TMFtp.DoRead;
- var
- Linein, newLine: String;
- el: Integer;
- begin
- if OnHold then Exit;
- if Aborted then Exit;
- while True do
- begin
- if Aborted then Exit;
- Linein := RecvText;
- if CheckError then Exit;
- DoFtpInfo(ftpTraceIn, Linein);
- if Length(Linein) = 0 then Exit;
- Linein := PartialLine + Linein;
- repeat
- // fix for ftp.es.tripod.de, reported by Alfonso Martinez de Lizarrondo
- {$ifndef NOPATCH}
- el := Pos(#10, Linein);
- if el <> 0 then
- begin
- if ((el>1) and (Linein[el-1] = #13)) then
- newLine := Copy(Linein, 1, el - 2)
- else
- newLine := Copy(Linein, 1, el - 1);
-
- Delete(Linein, 1, el);
- {$else}
- el := Pos(#13 + #10, Linein);
- if el <> 0 then
- begin
- newLine := Copy(Linein, 1, el - 1);
- Delete(Linein, 1, el + 1);
- {$endif}
- OnHold := True;
- FtpProcess(newLine);
- OnHold := False;
- if Aborted then Exit;
- end;
- until el = 0;
- PartialLine := Linein;
- end;
- end;
-
- procedure TMFtp.FatalError;
- begin
- if Aborted then Exit;
-
- FError := e;
- DoFtpError(e);
- if DataSocket.IsConnected then DataSocket.Disconnect;
- if ListeningSocket.IsConnected then ListeningSocket.Disconnect;
- if IsConnected then Disconnect;
- end;
-
- procedure TMFtp.fpBuildFileList;
- var D: TStringList;
- L, CurrDir: String;
- i: Integer;
- begin
- D := TStringList.Create;
-
- try
- RefreshB;
- if not FSuccess then Ready;
-
- if Flag or (Visited.IndexOf(FDirectory) < 0) then
- begin
- if not Flag then Visited.Add(FDirectory);
- L := GetURL;
-
- if FDirectory <> '' then
- begin
- if (FDirectory[1] <> '/') and (FDirectory[1] <> '\') then
- CurrDir := '/' + FDirectory
- else
- CurrDir := FDirectory;
- end;
-
- for i := 0 to Directories.Count - 1 do
- begin
- if (FBFParm.ScanSymLink) or ((not FBFParm.ScanSymLink) and (Directories[i].SymbolLink = '')) then
- D.Add(Directories[i].Filename);
- if Assigned(FOnFileFound) then FOnFileFound(Self, Directories[i], L, True);
- end;
-
- for i := 0 to Files.Count - 1 do
- if Assigned(FOnFileFound) then FOnFileFound(Self, Files[i], L, False);
-
- if FBFParm.Depth > 0 then
- begin
- for i := 0 to D.Count - 1 do
- begin
- ReadyCWD := False;
- Proceed('CWD ' + CurrDir + '/' + D[i], fpCWD);
- while not ReadyCWD do ProcessMessages;
- if FDirectory <> '' then
- begin
- Dec(FBFParm.Depth);
- fpBuildFileList(False);
- Inc(FBFParm.Depth);
- end;
- end;
- end;
- end;
-
- if Flag then Ready;
- finally
- FreeAndNil(D);
- end;
- end;
-
- procedure TMFtp.fpChmod;
- begin
- if Line[1] = '5' then
- begin
- if Line[1] = '0' then
- DoFtpError(ftpProtocolError)
- else
- DoFtpError(ftpAccessDenied);
- Ready;
- end;
- end;
-
- procedure TMFtp.fpCWD;
- var i: Integer;
- begin
- if Line[1] <> '2' then
- begin
- FDirectory := '';
- errs := msgDenied;
- DoFtpError(ftpPermissionDenied);
- ReadyCWD := True;
- Ready;
- end
- else
- begin
- {setting new CurrentDirectory property}
- i := Pos('"', Line);
- if i > 0 then
- begin
- FDirectory := Copy(Line, i + 1, 999);
- FDirectory := Copy(FDirectory, 1, Pos('"', FDirectory) - 1);
- ReadyCWD := True;
- Ready;
- end
- else
- Proceed('PWD', fpCWD2);
- end;
- end;
-
- procedure TMFtp.fpCWD2;
- begin
- if Line[1] <> '2' then
- begin
- DoFtpError(ftpProtocolError)
- end
- else
- begin
- {setting new CurrentDirectory property}
- FDirectory := Copy(Line, Pos('"', Line) + 1, 999);
- FDirectory := Copy(FDirectory, 1, Pos('"', FDirectory) - 1);
-
- if (FType = ftpstNetTerm) or (FType = ftpstServU) then
- FDirectory := DOSName2UnixName(FDirectory);
- end;
-
- ReadyCWD := True;
- Ready;
- end;
-
- procedure TMFtp.fpDeleteDirectory;
- var S: String;
- begin
- if Line[1] <> '2' then
- begin
- errs := msgDenied;
- DoFtpError(ftpPermissionDenied);
- end
- else
- begin
- // find out the name of deleted directory
- if Oprdir[1] = '/' then
- S := Oprdir
- else
- if FDirectory[Length(FDirectory)] = '/' then
- S := FDirectory + Oprdir
- else
- S := FDirectory + '/' + Oprdir;
-
- // delete cache files
- Sysutils.DeleteFile(GetCacheFilename(Server, FUser, S, Port, True));
- Sysutils.DeleteFile(GetCacheFilename(Server, FUser, S, Port, False));
- end;
-
- Ready;
- end;
-
- procedure TMFtp.fpDownload;
- var s: String;
- begin
- DownloadSize := 0;
-
- if Assigned(NeedInfo) then NeedInfo(self, niOverwrite, s);
- if s = 'Resume' then
- begin
- if FSupportResume then
- begin
- if FSupportSIZE then
- begin
- Proceed('SIZE ' + FSelection, fpDownload2);
- end
- else
- begin
- fpDownload2('500');
- end;
- end
- else
- begin
- DoFtpInfo(ftpNotSupportResume);
- MyCloseFile;
- FTPLastAction := ftplaNone;
- Ready;
- end;
- end
- else
- begin
- if (s = 'Overwrite') or (s = '') then
- begin
- PassiveP := fpDownload4b;
- fpDownload3('299')
- end
- else
- begin
- MyCloseFile;
- FTPLastAction := ftplaNone;
- Ready;
- end;
- end;
- end;
-
- procedure TMFtp.fpDownload2;
- begin
- if Line[1] <> '2' then
- begin
- if (Line[1] = '5') and (Line[2] = '0') then
- begin
- FSupportSIZE := False;
- Line := '213 '+ IntToStr(DataFile.Size);
- fpDownload2(Line);
- end
- else
- begin
- PassiveP := fpDownload4b;
- fpDownload3('299');
- end;
- end
- else
- begin
- DownloadSize := StrToIntDef(Copy(Line, 5, 999), 0);
- if (DownloadSize < DataFile.Size) or (DataFile.Size = 0) then
- begin
- DoFtpInfo(ftpNotSupportResume, msgAOverwrite);
- PassiveP := fpDownload4b;
- fpDownload3('299');
- end
- else
- begin
- if DownloadSize = DataFile.Size then
- begin
- DoFtpInfo(ftpNothing, msgNothing);
- MyCloseFile;
- FTPLastAction := ftplaNone;
- Ready;
- end
- else
- begin
- DataFile.Seek(0, soFromEnd);
- PassiveP := fpDownload4a;
- fpDownload3('299');
- end;
- end;
- end;
- end;
-
- procedure TMFtp.fpDownload3;
- begin
- if Line[1] = '2' then
- begin
- if FPassive then
- Proceed('PASV', fpPreparePassive)
- else
- Proceed('PORT ' + SetupDataPort, PassiveP);
- end
- else
- begin
- DoFtpError(ftpProtocolError);
- Ready;
- end;
- end;
-
- procedure TMFtp.fpDownload4a;
- begin
- if Line[1] <> '2' then
- begin
- DoFtpError(ftpProtocolError);
- Ready;
- end
- else
- begin
- with DataSocket do
- begin
- OnReadReady := DataRetrFile;
- OnDisconnected := DataFileDisconnected;
- OnWriteReady := nil;
- if FPassive then
- OnConnected := DataListConnected
- else
- ListeningSocket.OnAccept := DataListConnected;
- end;
-
- FStartPoint := DataFile.Size;
- Proceed('REST ' + IntToStr(FStartPoint), fpDownload5a);
- end;
- end;
-
- procedure TMFtp.fpDownload4b;
- begin
- if Line[1] <> '2' then
- begin
- DoFtpError(ftpProtocolError);
- Ready;
- end
- else
- begin
- with DataSocket do
- begin
- OnReadReady := DataRetrFile;
- OnDisconnected := DataFileDisconnected;
- OnWriteReady := nil;
- if FPassive then
- OnConnected := DataListConnected
- else
- ListeningSocket.OnAccept := DataListConnected;
- end;
- Proceed('RETR ' + FSelection, fpDownload5b);
- end;
- end;
-
- procedure TMFtp.fpDownload5a;
- begin
- if Line[1] = '3' then
- Proceed('RETR ' + FSelection, fpDownload5b)
- else
- begin
- DataSocket.Disconnect;
- ListeningSocket.Disconnect;
- errs := msgFResumeD;
- DoFtpError(ftpResumeFailed);
- Ready;
- end;
- end;
-
- procedure TMFtp.fpDownload5b;
- var i, j: Integer;
- begin
- case Line[1] of
- '1':
- begin
- i := Pos('(', Line);
- if i > 0 then
- begin
- while i > 0 do
- begin
- Delete(Line, 1, i);
- i := Pos('(', Line);
- end;
-
- for j := 1 to Length(Line) do
- begin
- if Line[j] = ' ' then
- begin
- DoFtpInfo(ftpFileSize, Copy(Line, i + 1, j - i - 1));
- Exit;
- end;
- end;
- end;
- Exit;
- end;
- '2':
- begin
- ReadyMain := True;
- if ReadyPort then Ready;
- // NextP := nil;
- end
- else
- begin
- DataSocket.Disconnect; {close data connection}
- ListeningSocket.Disconnect;
- if (Aborted) and (Copy(Line, 1, 3) = '426') then
- begin
- if Assigned(FAborted) then FAborted(Self);
- CallNEvents(13);
- end
- else
- begin
- errs := msgDenied;
- DoFtpError(ftpPermissionDenied);
- end;
- Ready;
- end;
- end;
- end;
-
- procedure TMFtp.fpList;
- begin
- ReadyMain := False;
- ReadyPort := False;
-
- if Line[1] = '2' then
- begin
- if FPassive then
- begin
- PassiveP := fpList2;
- Proceed('PASV', fpPreparePassive)
- end
- else
- Proceed('PORT ' + SetupDataPort, fpList2)
- end
- else
- begin
- DoFtpError(ftpProtocolError);
- if ftpLastAction = ftplaSearch then ReadyList := True else Ready;
- end;
- end;
-
- procedure TMFtp.fpList2;
- begin
- if Line[1] <> '2' then
- begin
- DoFtpError(ftpProtocolError);
- if ftpLastAction = ftplaSearch then ReadyList := True else Ready;
- end
- else
- begin
- with DataSocket do
- begin
- OnReadReady := DataDoListing;
- OnDisconnected := DataListDisconnected;
- OnWriteReady := nil;
- if FPassive then
- OnConnected := DataListConnected
- else
- ListeningSocket.OnAccept := DataListConnected;
- end;
-
- FList.Clear;
- TFiles.Clear;
- TDirectories.Clear;
-
- pcount := 0;
- if FFileMask <> '' then
- Proceed('LIST ' + FFileMask, fpList3)
- else
- Proceed('LIST', fpList3);
-
- DoFtpInfo(ftpStartListing);
- end;
- end;
-
- procedure TMFtp.fpList3;
- begin
- case Line[1] of
- '1': Exit;
- '2':
- begin
- ReadyMain := True;
- if ReadyPort then
- if ftpLastAction = ftplaSearch then ReadyList := True else Ready;
- end
- else
- begin
- DataSocket.Disconnect; {close data connection}
- ListeningSocket.Disconnect;
- if (Aborted) and (Copy(Line, 1, 3) = '426') then
- begin
- if Assigned(FAborted) then FAborted(Self);
- CallNEvents(13);
- end
- else
- begin
- errs := msgDenied;
- DoFtpError(ftpPermissionDenied);
- end;
- if ftpLastAction = ftplaSearch then ReadyList := True else Ready;
- end;
- end;
- end;
-
- procedure TMFtp.fpLogin;
- begin
- if URLMode = 0 then FtpLastAction := ftplaLOGIN else UrlMode := 2;
-
- if Line[1] <> '2' then
- FatalError(ftpServerDown)
- else
- begin
- if (FUser = '') and Assigned(NeedInfo) then NeedInfo(Self, niUser, FUser);
-
- if FProxyType <> proxyNone then
- begin
- Server := FtpServer;
- Port := FtpPort;
- end
- else
- begin
- if FType = ftpstAutoDetect then
- begin
- if Pos('NetTerm FTP server', Line) <> 0 then FType := ftpstNetTerm;
- end;
- end;
-
- case FProxyType of
- proxyHost: Proceed('HOST ' + Server, fpLoginProxyHost);
- proxyNone: Proceed('USER ' + FUser, fpLogin2);
- proxyOpen: Proceed('OPEN ' + Server, fpLoginProxyOpen);
- proxySite: Proceed('USER ' + FPUser, fpLoginProxySite);
- proxyHostUser:
- begin
- if Port = 21 then
- Proceed('USER ' + Server + '!' + FUser, fpLogin2)
- else
- Proceed('USER ' + Server + ':' + IntToStr(Port) + '!' + FUser, fpLogin2);
- end;
- proxyUserSite:
- begin
- if Port = 21 then
- Proceed('USER ' + FUser + '@' + Server, fpLogin2)
- else
- Proceed('USER ' + FUser + '@' + Server + ':' + IntToStr(Port), fpLogin2);
- end;
- end;
- end;
- end;
-
- procedure TMFtp.fpLogin2;
- begin
- if Line[1] = '2' then
- begin
- if FType = ftpstAutoDetect then
- Proceed('SYST', fpTestSystemType)
- else
- Proceed('REST 100', fpTestREST);
- end
- else
- begin
- if Line[1] <> '3' then
- begin
- FatalError(ftpAccessDenied);
- end
- else
- begin
- if (FPass = '') and Assigned(NeedInfo) then NeedInfo(Self, niPassword, FPass);
- Proceed('PASS ' + FPass, fpLogin3);
- end;
- end;
- end;
-
- procedure TMFtp.fpLogin3;
- begin
- if Line[1] = '2' then
- begin
- if FType = ftpstAutoDetect then
- Proceed('SYST', fpTestSystemType)
- else
- Proceed('REST 100', fpTestREST);
- end
- else
- begin
- if Line[1] <> '3' then
- begin
- FatalError(ftpAccessDenied);
- end
- else
- begin
- if (FAcct = '') and Assigned(NeedInfo) then NeedInfo(Self, niAccount, FAcct);
- Proceed('ACCT ' + FAcct, fpLogin4);
- end;
- end;
- end;
-
- procedure TMFtp.fpLogin4;
- begin
- if Line[1] = '2' then
- begin
- if FType = ftpstAutoDetect then
- Proceed('SYST', fpTestSystemType)
- else
- Proceed('REST 100', fpTestREST);
- end
- else
- begin
- FatalError(ftpAccessDenied);
- end;
- end;
-
- procedure TMFtp.fpLogin5;
- begin
- if FDirectory = '' then
- begin
- if Line[1] = '2' then
- begin
- FDirectory := Copy(Line, Pos('"', Line) + 1, 999);
- FDirectory := Copy(FDirectory, 1, Pos('"', FDirectory) - 1);
-
- if (FType = ftpstNetTerm) or (FType = ftpstServU) then
- FDirectory := DOSName2UnixName(FDirectory);
- end
- else
- FatalError(ftpProtocolError);
- end
- else
- begin
- if Line[1] <> '2' then
- begin
- errs := msgDenied;
- DoFtpError(ftpPermissionDenied);
- end;
- end;
-
- DoFtpInfo(ftpLoggedIn);
- Ready;
- end;
-
- procedure TMFtp.fpLoginProxyHost(Line: String);
- begin
- if Line[1] <> '3' then FatalError(ftpServerDown) else Proceed('USER ' + FUser, fpLogin2);
- end;
-
- procedure TMFtp.fpLoginProxyOpen(Line: String);
- begin
- if Line[1] <> '2' then FatalError(ftpServerDown) else Proceed('USER ' + FUser, fpLogin2);
- end;
-
- procedure TMFtp.fpLoginProxySite(Line: String);
- begin
- if (FPUser = '') and Assigned(NeedInfo) then NeedInfo(Self, niUser, FPUser);
- case Line[1] of
- '2': Proceed('SITE ' + FServer, fpLoginProxySite3);
- '3':
- begin
- if (FPPass = '') and Assigned(NeedInfo) then NeedInfo(Self, niPassword, FPPass);
- Proceed('PASS ' + FPPass, fpLoginProxySite2);
- end;
- else FatalError(ftpAccessDenied);
- end;
- end;
-
- procedure TMFtp.fpLoginProxySite2(Line: String);
- begin
- if Line[1] = '2' then Proceed('SITE ' + FServer, fpLoginProxySite3) else FatalError(ftpAccessDenied);
- end;
-
- procedure TMFtp.fpLoginProxySite3(Line: String);
- begin
- if Line[1] <> '2' then FatalError(ftpProtocolError) else Proceed('USER ' + FUser, fpLogin2);
- end;
-
- procedure TMFtp.fpNOOP;
- begin
- if (Line[1] = '5') and (Line[2] = '0') then FSupportNOOP := False;
- FBusy := False;
- end;
-
- procedure TMFtp.fpPreparePassive;
- begin
- if (Line[1] = '2') and Assigned(PassiveP) then
- begin
- SetupDataPortPassive(Line);
- PassiveP('299');
- end
- else
- begin
- DoFtpError(ftpProtocolError);
- Ready;
- end;
- end;
-
- procedure TMFtp.fpProcessGeneral;
- begin
- if Line[1] <> '2' then
- begin
- errs := msgDenied;
- DoFtpError(ftpPermissionDenied);
- end;
-
- Ready;
- end;
-
- procedure TMFtp.fpProcessURL;
- begin
- UrlMode := 0;
-
- if FUrl = '' then
- Proceed('PWD', fpProcessURL2)
- else
- Proceed('CWD ' + FUrl, fpProcessURL2);
- end;
-
- procedure TMFtp.fpProcessURL2;
- var i, j: Integer;
- begin
- if Line[1] = '2' then
- begin
- FtpLastAction := ftplaCWD;
- FDirectory := Copy(Line, Pos('"', Line) + 1, 999);
- FDirectory := Copy(FDirectory, 1, Pos('"', FDirectory) - 1);
-
- if not ControlLoggedIn then
- begin
- ControlLoggedIn := True;
- SRetry := True;
- DoFtpInfo(ftpLoggedIn);
- end;
-
- fpCWD(Line);
- end
- else
- begin
- i := Length(FUrl);
-
- if FUrl[i] = '/' then
- begin
- FtpLastAction := ftplaCWD;
- errs := msgDenied;
- DoFtpError(ftpPermissionDenied);
- Ready;
- end
- else
- begin
- for j := i downto 1 do
- begin
- if FUrl[j] = '/' then
- begin
- FSelection := Copy(FUrl, j + 1, 999);
- Delete(FUrl, j + 1, 999);
- Break;
- end;
- end;
-
- Proceed('CWD ' + FUrl, fpProcessURL3);
- end;
- end;
- end;
-
- procedure TMFtp.fpProcessURL3;
- begin
- if Line[1] = '2' then
- begin
- if not ControlLoggedIn then
- begin
- ControlLoggedIn := True;
- SRetry := True;
- DoFtpInfo(ftpLoggedIn);
- end;
-
- if FSelection <> '' then
- begin
- if Assigned(NeedInfo) then
- begin
- FFile := FSelection;
- NeedInfo(Self, niLocalFile, FFile);
- if FFile = '' then
- begin
- Disconnect;
- Exit;
- end;
- end
- else
- begin
- Disconnect;
- Exit;
- end;
-
- FBusy := False;
- GetFile(FSelection, FFile);
- end;
- end
- else
- begin
- // FRemain := -1;
- FatalError(ftpFileNotFound);
- end;
- end;
-
- procedure TMFtp.fpQuit;
- begin
- ControlLoggedIn := False;
- if Line[1] <> '2' then FatalError(ftpNone);
- // NextP := nil;
- end;
-
- procedure TMFtp.fpSetinitialDirectory;
- begin
- if URLMode > 0 then
- begin
- fpProcessURL('299');
- Exit;
- end;
-
- if FIDirectory = '' then
- Proceed('PWD', fpLogin5)
- else
- Proceed('CWD ' + FIDirectory, fpSetinitialDirectory2);
- end;
-
- procedure TMFtp.fpSetinitialDirectory2;
- begin
- if Line[1] = '2' then
- begin
- FDirectory := Copy(Line, Pos('"', Line) + 1, 999);
- FDirectory := Copy(FDirectory, 1, Pos('"', FDirectory) - 1);
- end;
-
- if FDirectory <> '' then
- begin
- DoFtpInfo(ftpLoggedIn);
- Ready;
- end
- else
- Proceed('PWD', fpLogin5);
- end;
-
- procedure TMFtp.fpTestREST;
- begin
- if Line[1] = '3' then
- begin
- FSupportResume := True;
- DoFtpInfo(ftpSupportResume, msgSResume);
- Proceed('REST 0', fpSetinitialDirectory);
- end
- else
- begin
- FSupportResume := False;
- DoFtpInfo(ftpNotSupportResume);
- fpSetinitialDirectory('299');
- end;
- end;
-
- procedure TMFtp.fpTestSystemType;
- var FSyst: String;
- begin
- if Line[1] <> '5' then
- begin
- if FType = ftpstAutoDetect then
- begin
- FSyst := UpperCase(Copy(Line, 5, 99));
- FType := ftpstDefault;
-
- if Pos('UNIX', FSyst) <> 0 then FType := ftpstUnix else
- if Pos('BSD', FSyst) <> 0 then FType := ftpstBSD else
- if Pos('SUNOS', FSyst) <> 0 then FType := ftpstSunOS else
- if Pos('CLIX', FSyst) <> 0 then FType := ftpstClix else
- if Pos('ULTRIX', FSyst) <> 0 then FType := ftpstUltrix else
- if Pos('MVS', FSyst) <> 0 then FType := ftpstMVS else
- if Pos('QVT', FSyst) <> 0 then FType := ftpstQVT else
- if Pos('NCSA', FSyst) <> 0 then FType := ftpstNCSA else
- if Pos('WFTPD', FSyst) <> 0 then FType := ftpstWFTPD else
- if Pos('WINDWOS_NT', FSyst) <> 0 then FType := ftpstMSFTP else
- if Pos('CHAMELEON', FSyst) <> 0 then FType := ftpstChameleon else
- if Pos('VMS', FSyst) <> 0 then
- if Pos('MULTINET', FSyst) <> 0 then FType := ftpstVmsMultinet else FType := ftpstVmsUcx
- else
- begin
- if Pos('VM', Fsyst) <> 0 then
- begin
- if Pos('VPS', FSyst) = 0 then
- FType := ftpstVM
- else
- FType := ftpstVMVPS;
- end;
- end;
- end;
- end
- else
- begin
- FType := ftpstDefault;
- end;
-
- Proceed('REST 100', fpTestREST);
- end;
-
- function InitPort(Line: String): String;
- begin
- Result := Copy(Line, Pos('(', Line) + 1, Length(Line));
- Result := Copy(Result, 1, Pos(')', Result) - 1);
- end;
-
- procedure TMFtp.fpTransfer;
- begin
- if Line[1] <> '2' then
- begin
- FTransferSuccess := False;
- FTransferFromFtp.DoFtpError(ftpTransferType);
- end;
- FTransferToFtp.SetTransferMode(TransMode, fpTransfer2);
- end;
-
- procedure TMFtp.fpTransfer2;
- begin
- if Line[1] <> '2' then
- begin
- FTransferSuccess := False;
- FTransferToFtp.DoFtpError(ftpTransferType);
- end;
- FTransferFromFtp.Proceed('PASV', fpTransfer3);
- end;
-
- procedure TMFtp.fpTransfer3;
- begin
- if Line[1] <> '2' then
- begin
- FTransferFromFtp.DoFtpError(ftpTransferPort);
- FTransferToFtp.Proceed('PASV', fpTransfer3b);
- end
- else
- FTransferToFtp.Proceed('PORT ' + InitPort(Line), fpTransfer5);
- end;
-
- procedure TMFtp.fpTransfer3b;
- begin
- if Line[1] <> '2' then
- begin
- FTransferSuccess := False;
- FTransferToFtp.DoFtpError(ftpTransferFatalPort);
- end
- else
- FTransferFromFtp.Proceed('PORT ' + InitPort(Line), fpTransfer4b);
- end;
-
- procedure TMFtp.fpTransfer4b;
- begin
- if Line[1] <> '2' then
- begin
- FTransferSuccess := False;
- FTransferToFtp.DoFtpError(ftpTransferFatalPort);
- Inc(FTransferCounter);
- fpTransferFinished;
- end
- else
- fpTransfer5(Line);
- end;
-
- procedure TMFtp.fpTransfer5;
- var GetToFileSize, GetFromFileSize: Integer;
- begin
- if Line[1] <> '2' then
- begin
- fpTransfer3(Line);
- end
- else
- begin
- GetToFileSize := FTransferToFtp.FileExists(FTargetName);
- if GetToFileSize<> - 1 then
- begin
- GetToFileSize := UnformatInteger(FTransferToFtp.Files.Items[GetToFileSize].Size);
- GetFromFileSize := FTransferFromFtp.FileExists(FSourceName);
-
- if GetFromFileSize = - 1 then
- begin
- FTransferSuccess := False;
- FTransferFromFtp.DoFtpError(ftpTransferGet);
- Inc(FTransferCounter);
- fpTransferFinished;
- Exit;
- end;
-
- GetFromFileSize := UnformatInteger(FTransferFromFtp.Files.Items[GetFromFileSize].Size);
-
- if GetToFileSize <> 0 then
- begin
- if (GetFromFileSize>GetToFileSize) and (FTransferResume) and (FTransferToFtp.FSupportResume) then
- begin
- TempInt := GetToFileSize;
- DoFTPInfo(ftpTransferResume, FTargetName);
- FTransferToFtp.Proceed('APPE ' + FTargetName, fpTransfer6b);
- Exit;
- end;
- end;
- end;
- FTransferToFtp.Proceed('STOR ' + FTargetName, fpTransfer6);
- end;
- end;
-
- procedure TMFtp.fpTransfer6; // from 'Stor TargetName'
- begin
- case Line[1] of
- '1':
- begin
- DoFTPInfo(ftpTransferPutStart, FSourceName);
- fpTransfer7b('3');
- end;
- else
- fpTransfer6b(Line);
- end;
- end;
-
- procedure TMFtp.fpTransfer6b; // from 'Appe TargetName'
- begin
- case Line[1] of
- '1':
- begin
- DoFTPInfo(ftpTransferPutStart, FTargetName);
- FTransferFromFtp.Proceed('REST ' + IntToStr(TempInt), fpTransfer7b);
- end;
- '2':
- begin
- DoFTPInfo(ftpTransferPutFinish, FTargetName);
- FTransferSuccess := True;
- fpTransferFinished;
- end;
- else
- begin
- Inc(FTransferCounter);
- FTransferSuccess := False;
- FTransferToFtp.DoFtpError(ftpTransferPut);
- fpTransferFinished;
- end;
- end;
- end;
-
- procedure TMFtp.fpTransfer7b;
- begin
- if Line[1] <> '3' then FTransferToFtp.DoFtpError(ftpTransferResumeFailed);
- FTransferFromFtp.Proceed('RETR ' + FSourceName, fpTransfer8);
- end;
-
- procedure TMFtp.fpTransfer8; // After Normal/Resume Transfer
- begin
- case Line[1] of
- '1': DoFTPInfo(ftpTransferGetStart, FSourceName);
- '2':
- begin
- FTransferSuccess := True;
- DoFTPInfo(ftpTransferGetFinish, FSourceName);
- fpTransferFinished;
- end;
- else
- begin
- FTransferToFtp.StopTransfer;
- while Copy(FTransferToFtp.LastReply, 1, 3) <> '226' do ProcessMessages;
- FTransferSuccess := False;
- FTransferFromFtp.DoFtpError(ftpTransferGet);
- // Inc(FTransferCounter);
- fpTransferFinished;
- end;
- end;
- end;
-
- procedure TMFtp.fpTransferFinished;
- begin
- Inc(FTransferCounter);
- if FTransferCounter >= 2 then
- begin
- FTransferFromFtp.FBusy := False;
- FTransferToFtp.FBusy := False;
-
- if Assigned(FTransferToFtp.FOnReady) then
- begin
- FTransferToFtp.FOnReady(Self);
- FTransferToFtp.CallNEvents(9);
- end;
-
- Ready; // if Assigned(FTransferFromFtp.FOnReady) then
- // FTransferFromFtp.FOnReady(Self);
- end;
- end;
-
- procedure TMFtp.fpUpload;
- begin
- UploadSize := 0;
-
- if (FSupportResume) and (FSupportSIZE) then
- Proceed('SIZE ' + FSelection, fpUpload2)
- else
- begin
- PassiveP := fpUpload4b;
- fpUpload3('299');
- end;
- end;
-
- procedure TMFtp.fpUpload2;
- var s: String;
- begin
- if Line[1] <> '2' then
- begin
- if (Line[1] = '5') and (Line[2] = '0') then FSupportSIZE := False;
- PassiveP := fpUpload4b;
- end
- else
- begin
- UploadSize := StrToIntDef(Copy(Line, 5, 999), 0);
- if UploadSize = 0 then
- begin
- PassiveP := fpUpload4b;
- end
- else
- begin
- if (Assigned(NeedInfo)) then NeedInfo(self, niOverwrite, s);
- if s = 'Resume' then
- begin
- DataFile.Seek(UploadSize, soFromBeginning);
- PassiveP := fpUpload4a;
- end
- else
- begin
- if (s = 'Overwrite') or (s = '') then
- begin
- PassiveP := fpUpload4b;
- end
- else
- begin
- MyCloseFile;
- FTPLastAction := ftplaNone;
- Ready;
- Exit;
- end;
- end;
- end;
- end;
-
- fpUpload3('299');
- end;
-
- procedure TMFtp.fpUpload3;
- begin
- ReadyPort := False;
- ReadyMain := False;
-
- if Line[1] = '2' then
- begin
- if FPassive then
- begin
- Proceed('PASV', fpPreparePassive);
- end
- else
- Proceed('PORT ' + SetupDataPort, PassiveP);
- end
- else
- begin
- DoFtpError(ftpProtocolError);
- Ready;
- end;
- end;
-
- procedure TMFtp.fpUpload4a;
- begin
- if Line[1] <> '2' then
- begin
- DoFtpError(ftpProtocolError);
- Ready;
- end
- else
- begin
- with DataSocket do
- begin
- OnReadReady := nil;
- OnDisconnected := DataFileDisconnected;
- if FPassive then
- begin
- OnWriteReady := DataStorConnected;
- OnConnected := DataListConnected;
- end
- else
- begin
- OnWriteReady := nil;
- ListeningSocket.OnAccept := DataStorConnected;
- end;
- end;
-
- FStartPoint := UploadSize;
- Proceed('REST ' + IntToStr(FStartPoint), fpUpload5a);
- end;
- end;
-
- procedure TMFtp.fpUpload5a;
- begin
- if Line[1] = '3' then
- Proceed('STOR ' + FSelection, fpUpload5b)
- else
- begin
- DataSocket.Disconnect;
- ListeningSocket.Disconnect;
- errs := msgFResumeU;
- DoFtpError(ftpResumeFailed);
- Ready;
- end;
- end;
-
- procedure TMFtp.fpUpload4b;
- begin
- if line[1] <> '2' then
- begin
- DoFtpError(ftpProtocolError);
- Ready;
- end
- else
- begin
- with DataSocket do
- begin
- OnReadReady := nil;
- OnDisconnected := DataFileDisconnected;
- OnWriteReady := DataStorFile;
- if FPassive then
- OnConnected := DataStorConnected
- else
- ListeningSocket.OnAccept := DataStorConnected;
- end;
- Proceed('STOR ' + FSelection, fpUpload5b);
- end;
-
- end;
-
- procedure TMFtp.fpUpload5b;
- begin
- case Line[1] of
- '1':
- begin
- NextP := fpProcessGeneral;
- end;
- '2':
- begin
- ReadyMain := True;
- if ReadyPort then Ready;
- end;
- else
- begin
- DataSocket.Disconnect; {close data connection}
- ListeningSocket.Disconnect;
- if (Aborted) and (Copy(Line, 1, 3) = '426') then
- begin
- if Assigned(FAborted) then FAborted(Self);
- CallNEvents(13);
- end
- else
- begin
- errs := msgDenied;
- DoFtpError(ftpPermissionDenied);
- end;
- Ready;
- end;
- end;
- end;
-
- procedure TMFtp.FtpProcess;
- begin
- if Line = '' then Exit;
-
- if Intermediate and (Copy(Line, 1, 4) <> Response + ' ') then
- begin
- if Copy(Line, Length(Line) - 1, 2) <> #13#10 then
- FBannerStore := FBannerStore + Line + #13#10
- else
- FBannerStore := FBannerStore + Line;
- Exit;
- end;
-
- if Line[4] = '-' then
- begin
- if not Intermediate then
- begin
- Intermediate := True;
- FBannerStore := Line;
- end;
-
- Response := Copy(Line, 1, 3);
- Exit;
- end;
-
- if Intermediate then
- begin
- Intermediate := False;
- FBanner.Clear;
- FBanner.Text := FBannerStore;
- FBanner.Add(Line);
- DoFtpInfo(ftpBannerAvailable);
- end;
-
- FLastLine := Line;
- if Assigned(NextP) then NextP(Line);
- end;
-
- {=========== data connection routines ===========}
- procedure TMFtp.DataListConnected;
- begin
- if not FPassive then
- DataSocket.Accept(ListeningSocket);
- if DataSocket.LastError <> 0 then
- begin
- if (not TransferAborted) and (DataSocket.LastError <> 10038) then FatalError(ftpDataError);
- Exit;
- end;
- Bytes := 0;
- FSuccess := True;
- StartTime := GetTickCount;
- TrTime := 0;
- DataPartialLine := '';
- DataConnected := True;
- TransferAborted := False;
- end;
-
- procedure TMFtp.DataListDisconnected;
- var
- e: TNotifyEvent;
- begin
- with DataSocket do
- begin
- e := OnReadReady;
- OnConnected := nil;
- if Assigned(e) then OnReadReady(Sender);
- TrTime := GetTickCount - StartTime;
- Disconnect;
- ListeningSocket.Disconnect;
- DoFtpInfo(ftpDirectoryRefresh);
- DoFtpInfo(ftpTransferDone);
- DataConnected := False;
- FDoingListing := False;
- ReadyPort := True;
- if ReadyMain then
- if ftpLastAction = ftplaSearch then ReadyList := True else Ready;
- end;
- end;
-
- procedure TMFtp.DataFileDisconnected;
- var
- e: TNotifyEvent;
- begin
- e := DataSocket.OnReadReady;
- if Assigned(e) then DataSocket.OnReadReady(Sender);
- TrTime := GetTickCount - StartTime;
- DataSocket.Disconnect;
- ListeningSocket.Disconnect;
- MyCloseFile;
- DoFtpInfo(ftpTransferDone);
- DataConnected := False;
- FDoingListing := False;
- ReadyPort := True;
- if ReadyMain then Ready;
- end;
-
- procedure TMFtp.DataRetrFile;
- var
- n, Transferred: Integer;
- begin
- FDoingListing := False;
-
- repeat
- n := DataSocket.RecvBuf(@InBuffer, IN_BUFFER_SIZE);
- if DataSocket.LastError <> 0 then
- begin
- if (not TransferAborted) and (DataSocket.LastError <> 10038) then FatalError(ftpDataError);
- Exit;
- end;
- if (n = 0) or (FileOpened = False) then Exit;
- Inc(Bytes, n);
- TrTime := GetTickCount - StartTime;
- DoFtpInfo(ftpDataTrace);
-
- // if FileOpened ...
- Transferred := DataFile.Write(InBuffer, n);
- if n <> Transferred then
- begin
- DoFtpError(ftpFileWrite);
- MyCloseFile;
- end;
- until n <= 0;
- end;
-
- procedure TMFtp.DataDoListing;
- var i, el: Integer;
- d: Boolean;
- Linein, newLine: String;
- fname, size, date, symlink: String;
- attrib: String;
- owner, group: String;
- begin
- FDoingListing := True;
- i := DataSocket.RecvBuf(@InBuffer, IN_BUFFER_SIZE);
- if DataSocket.LastError <> 0 then
- begin
- if (not TransferAborted) and (DataSocket.LastError <> 10038) then FatalError(ftpDataError);
- Exit;
- end;
- InBuffer[i] := #0;
- Linein := StrPas(@InBuffer);
- if Linein = '' then Exit;
- Inc(Bytes, Length(Linein));
- Linein := DataPartialLine + Linein;
- repeat
- el := Pos(#13 + #10, Linein);
- if el <> 0 then
- begin
- newLine := Copy(Linein, 1, el - 1);
- Delete(Linein, 1, el + 1);
- TrTime := GetTickCount - StartTime;
- DoFtpInfo(ftpDataTrace, newLine);
- try
- FList.Add(newLine);
-
- Inc(pcount);
- if ParseListingLine(FtpParse.TMFtpServerType(FType), newLine, fname,
- size, date, symlink, attrib, owner, group, d) then
- begin
- if d then
- begin
- if (fname <> '.') and (fname <> '..') then
- begin
- TDirectories.Add(fname, Attrib, Date, Size, Symlink, owner, group, '');
- DoFtpInfo(ftpListingParsed, 'Folder');
- end;
- end
- else
- begin
- TFiles.Add(fname, Attrib, Date, Size, Symlink, owner, group, '');
- DoFtpInfo(ftpListingParsed, 'File');
- end;
- end;
- except
- end;
- end;
- until el = 0;
-
- DataPartialLine := Linein;
- end;
-
- procedure TMFtp.DataStorFile(sender: TObject); {BDS}
- var
- Totsent, nb, fp: Longint;
- BlockingError: Boolean;
- begin
- nb := OUT_BUFFER_SIZE;
- if TransferAborted then
- begin
- FSuccess := False;
- end else begin
- BlockingError := False;
- repeat
- if MyEOF then Break;
-
- try
- fp := TotalBytesToSend - DataFile.Position;
- if fp < nb then
- nb := fp;
- DataFile.Read(OutBuffer, nb);
- // Inc(Bytes, nb);
- except
- DoFtpError(ftpFileRead);
- MyCloseFile;
- DataSocket.Disconnect;
- ListeningSocket.Disconnect;
- FSuccess := False;
- end;
-
- Totsent := 0;
- while Totsent < nb do
- begin
- ProcessMessages;
- if Aborted then
- begin
- FSuccess := False;
- break;
- end else begin
- DataSocket.WantBlockingErrors := True;
- Inc(Totsent, DataSocket.SendBuf(@OutBuffer[Totsent], nb - Totsent));
- DataSocket.WantBlockingErrors := False;
- BlockingError := DataSocket.LastError = WSAEWOULDBLOCK;
-
- if BlockingError then
- begin
- DataFile.Seek(DataFile.Position - (nb - Totsent), soFromBeginning);
- break;
- end;
-
- if (DataSocket.LastError <> 0) then
- begin
- if not TransferAborted then FatalError(ftpDataError);
- Inc(Bytes, Totsent);
- Exit;
- end;
- end;
- end;
- Inc(Bytes, Totsent);
- until BlockingError or (not FSuccess);
- DoFtpInfo(ftpDataTrace);
- TrTime := GetTickCount - StartTime;
- end;
-
- // check FSuccess and done state
- if (not FSuccess) or (MyEOF) then
- begin
- DataSocket.Disconnect;
- ListeningSocket.Disconnect;
- MyCloseFile;
- TrTime := GetTickCount - TrTime;
- DoFtpInfo(ftpTransferDone);
- ReadyPort := True;
- if ReadyMain then Ready;
- end;
- end;
-
- procedure TMFtp.DataStorConnected; {BDS}
- begin
- if not FPassive then
- DataSocket.Accept(ListeningSocket);
- if DataSocket.LastError <> 0 then
- begin
- if not TransferAborted then FatalError(ftpDataError);
- Exit;
- end;
- Bytes := 0;
- FSuccess := True;
- StartTime := GetTickCount;
- TrTime := 0;
- DataPartialLine := '';
- DataConnected := True;
- TransferAborted := False;
- FDoingListing := False;
- TotalBytesToSend := DataFile.Size;
- StartTime := GetTickCount;
- DoFtpInfo(ftpFileSize, IntToStr(DataFile.Size));
- end;
-
- procedure TMFtp.StopTransfer;
- var data: String;
- begin
- if TransferAborted then Exit;
- TransferAborted := True;
- data := #255 + #244;
- while data <> '' do
- begin
- if Aborted then Exit;
- Delete(data, 1, SendBuf(PChar(@data[1]), Length(data)));
- if CheckError then Exit;
- end;
- data := #255 + #242;
- while data <> '' do
- begin
- if Aborted then Exit;
- Delete(data, 1, SendBufOOB(PChar(@data[1]), Length(data)));
- if CheckError then Exit;
- end;
- Proceed('ABOR', NextP);
- data := #255 + #242;
- while data <> '' do
- begin
- if Aborted then Exit;
- Delete(data, 1, SendBuf(PChar(@data[1]), Length(data)));
- if CheckError then Exit;
- end;
- end;
-
- procedure TMFtp.Abort;
- begin
- case FtpLastAction of
- ftplaGet, ftplaGETIndexFile, ftplaPut, ftplaList:
- begin
- StopTransfer;
- end;
- ftplaGETS, ftplaPUTS:
- begin
- FMFinished := True;
- StopTransfer;
- end;
- ftplaMKDS, ftplaRMDS, ftplaRMS, ftplaRENS:
- begin
- FMFinished := True;
- FMAborted := True;
- end;
- ftplaSearch:
- begin
- BAborted := True;
- FSuccess := False;
-
- ReadyCWD := True;
- ReadyList := True;
- end;
- ftplaLogin, ftplaNone:
- begin
- if not ControlLoggedIn then
- begin
- FRemain := -1;
- {$ifdef USE_RETRYING_TIMER}
- RTimer.Enabled := False;
- {$else}
- SRetry := True;
- {$endif}
- Disconnect;
-
- if Assigned(FAborted) then FAborted(Self);
- CallNEvents(13);
- end;
- end;
- end;
- end;
-
- function TMFtp.SetupDataPort;
- var
- Line: String;
- dataaddr: String;
- dataport: Word;
- i: Word;
- begin
- { this line should not in the with block }
- ListeningSocket.Address := GetLocalAddress;
- with ListeningSocket do
- begin
- Port := 0;
- FillAddress(Address);
- FillPort(Port);
- CreateTCPSocket;
- Listen;
- dataaddr := GetLocalAddress;
- dataport := GetLocalPort;
- end;
- DataPartialLine := '';
- i := 1;
- while i <> 0 do
- begin
- i := Pos('.', dataaddr);
- if i <> 0 then dataaddr[i] := ',';
- end;
- Line := dataaddr + ',' + IntToStr(dataport div 256) + ',' + IntToStr(dataport mod 256);
- Result := Line;
- end;
-
- procedure TMFtp.SetupDataPortPassive;
- var p: String;
- ps: array[0..5] of String;
- c, l, i: Word;
- begin
- c := 0;
-
- p := copy(s, pos('(', s) + 1, length(s));
- p := copy(p, 1, pos(')', p) - 1);
- {A bug of Troll Tech ftp server(ftp.troll.no):
-
- 227 Passive mode OK (195,0,254,75,42,154 )
-
- and the correct respondence is:
-
- 227 Passive mode OK (195,0,254,75,42,154)
- }
- {$ifndef NOPATCH} p := Trim(p); {$endif}
-
- l := length(p);
- for i:=1 to l do
- if p[i] = ',' then
- Inc(c)
- else
- ps[c]:=ps[c] + p[i];
-
- DataPartialLine := '';
-
- with DataSocket do
- begin
- Address := ps[0] + '.' + ps[1] + '.' + ps[2]+'.' + ps[3];
- Port := StrToInt(ps[4]) shl 8 + StrToInt(ps[5]);
- FillAddress(Address);
- FillPort(Port);
- CreateTCPSocket;
- Connect;
- end;
- end;
-
- function TMFtp.CheckError;
- begin
- if (LastError = 0) or (Aborted) then
- begin
- FError := ftpNone;
- Result := False;
- end
- else
- begin
- case LastError of
- WSAENETDOWN:
- begin
- FError := ftpNetworkDown;
- errs := msgNetworkDown;
- end;
- WSAEACCES:
- begin
- FError := ftpInvalidAddress;
- errs := msgInvalidAddress;
- end;
- WSAENOTSOCK:
- begin
- FError := ftpNone;
- {Invalid socket specified (it is usually not a real error)}
- Result := False;
- Exit;
- end;
- WSAEINVAL:
- begin
- FError := ftpInternalError;
- errs := '';
- end;
- WSAETIMEDOUT:
- begin
- FError := ftpConnectTimeout;
- errs := msgTimeOut;
- end;
- WSAEMFILE:
- begin
- FError := ftpOutofSockets;
- errs := msgOutOfSocket;
- end;
- WSAENETUNREACH:
- begin
- FError := ftpNetworkUnreachable;
- errs := msgNetworkUR;
- end;
- WSAEADDRNOTAVAIL:
- begin
- FError := ftpAddressNotAvailable;
- errs := msgNotAvail;
- end;
- WSAECONNREFUSED:
- begin
- FError := ftpConnectionRefused;
- errs := msgRefuse;
- end;
- WSAENETRESET, WSAENOBUFS:
- begin
- FError := ftpGeneralWinsockError;
- errs := msgGeneralE;
- end;
- WSAECONNABORTED:
- begin
- FError := ftpConnAborted;
- errs := msgAborted;
- end;
- WSAECONNRESET:
- begin
- FError := ftpConnReset;
- errs := msgReset;
- end;
- WSAHOST_NOT_FOUND, WSATRY_AGAIN, WSANO_RECOVERY, WSANO_DATA:
- begin
- FError := ftpAddressResolutionError;
- errs := msgARE;
- end;
- WSAEHOSTUNREACH:
- begin
- FError := ftpHostUnreachable;
- errs := msgHostUR;
- end;
- WSAENOTCONN: { disconnected from server }
- begin
- FError := ftpNone;
- Result := False;
- Exit;
- end;
- else
- { WSAEFAULT, WSAEOPNOTSUPP, WSAESHUTDOWN, WSAEMSGSIZE,
- WSAEADDRINUSE, WSAEINPROGRESS, WSAEINTR, WSAEAFNOSUPPORT, WSAEISCONN }
- begin
- FError := ftpInternalError;
- errs := msgUnexpected + IntToStr(LastError) + ')';
- end;
- end;
- // FRemain := -1;
- FatalError(FError);
- Result := True;
- end;
- end;
-
- {call this before an operation is being started}
- function TMFtp.CheckStatus;
- begin
- Result := False;
-
- if not ControlConnected then
- begin
- FSuccess := False;
- DoFtpInfo(ftpServerDisconnected);
- Exit;
- end;
- if FBusy then
- begin
- FSuccess := False;
- DoFtpInfo(ftpAlreadyBusy);
- Exit;
- end;
-
- FBusy := True;
- if Assigned(FFtpBusy) then FFtpBusy(Self);
- CallNEvents(12);
-
- FSuccess := True;
- NTimer.Enabled := False;
- Result := True;
-
- FError := FtpNone;
- end;
-
- function TMFtp.RecvText;
- var
- n: Integer;
- buf: array[0..IN_BUFFER_SIZE] of Char;
- begin
- n := RecvBuf(buf, IN_BUFFER_SIZE);
- buf[n] := #0;
- Result := buf;
- end;
-
- procedure TMFtp.NTimerTimer;
- begin
- if FBusy then Exit;
- if not ControlLoggedIn then exit;
- if not FSupportNOOP then exit;
-
- FBusy := True;
- FtpLastAction := ftplaNOOP;
- Proceed('NOOP', fpNOOP);
- end;
-
- function TMFtp.GetInterval;
- begin
- Result := NTimer.Interval div 1000;
- end;
-
- procedure TMFtp.SetInterval;
- begin
- NTimer.Interval := I * 1000;
- end;
-
- {$ifdef USE_RETRYING_TIMER}
- procedure TMFtp.RTimerTimer;
- begin
- RTimer.Enabled := False;
- LoginMain;
- end;
- {$endif}
-
- function TMFtp.GetStartPoint;
- begin
- if (FtpLastAction = ftplaGET) or (FtpLastAction = ftplaPUT) then
- Result := FStartPoint
- else
- Result := 0;
- end;
-
- procedure TMFtp.SetAsync;
- begin
- if not FBusy then FAsync := B;
- end;
-
- procedure TMFtp.SetRetries;
- begin
- FRetries := I;
- end;
-
- function TMFtp.FileExists;
- begin
- Result := FFiles.IndexOf(filename);
- end;
-
- function TMFtp.DirectoryExists;
- begin
- Result := FDirectories.IndexOf(dir);
- end;
-
- procedure TMFtp.FileSetAttr;
- var Value: Integer;
- begin
- Value := 0;
- if OwnerRead then Inc(Value, 400);
- if OwnerWrite then Inc(Value, 200);
- if OwnerExecute then Inc(Value, 100);
- if GroupRead then Inc(Value, 40);
- if GroupWrite then Inc(Value, 20);
- if GroupExecute then Inc(Value, 10);
- if PublicRead then Inc(Value, 4);
- if PublicWrite then Inc(Value, 2);
- if PublicExecute then Inc(Value);
- Proceed('SITE CHMOD ' + IntToStr(Value)+' '+ filename, fpChmod);
- end;
-
- procedure TMFtp.SetTransferMode;
- begin
- if M = CurrentMode then
- begin
- P('299');
- end
- else
- begin
- CurrentMode := M;
- Proceed('TYPE ' + M, P);
- end;
- end;
-
- procedure TMFtp.CallNEvents;
- var i: Integer;
- begin
- for i := 1 to MAX_HANDLERS do
- if Assigned(NEvents[EventType, i]) then NEvents[EventType, i](Self);
- end;
-
- function TMFtp.RegisterNotifyEvent;
- var i: Integer;
- begin
- if Assigned(P) then
- begin
- for i := 1 to MAX_HANDLERS do
- begin
- if not Assigned(NEvents[EventType, i]) then
- begin
- NEvents[EventType, i] := P;
- Result := i;
- Exit;
- end;
- end;
- end;
- Result := -1;
- end;
-
- function TMFtp.RegisterErrorEvent;
- var i: Integer;
- begin
- if Assigned(P) then
- begin
- for i := 1 to MAX_HANDLERS do
- begin
- if not Assigned(NOnFtpError[i]) then
- begin
- NOnFtpError[i] := P;
- Result := i;
- Exit;
- end;
- end;
- end;
- Result := -1;
- end;
-
- function TMFtp.RegisterInfoEvent;
- var i: Integer;
- begin
- if Assigned(P) then
- begin
- for i := 1 to MAX_HANDLERS do
- begin
- if not Assigned(NOnFtpInfo[i]) then
- begin
- NOnFtpInfo[i] := P;
- Result := i;
- Exit;
- end;
- end;
- end;
- Result := -1;
- end;
-
- procedure TMFtp.UnRegisterNotifyEvent;
- begin
- NEvents[EventType, i] := nil;
- end;
-
- procedure TMFtp.UnRegisterErrorEvent;
- begin
- NOnFtpError[i] := nil;
- end;
-
- procedure TMFtp.UnRegisterInfoEvent;
- begin
- NOnFtpInfo[i] := nil;
- end;
-
- { message processing }
-
- function TMFtp.ProcessMessage;
- var
- Msg: TMsg;
- begin
- if PeekMessage(Msg, 0, 0, 0, PM_REMOVE) then
- begin
- Result := True;
- TranslateMessage(Msg);
- DispatchMessage(Msg);
- end
- else
- Result := False;
- end;
-
- procedure TMFtp.ProcessMessages;
- begin
- if not FMultiThreaded then
- Application.ProcessMessages
- else
- while ProcessMessage do Sleep(500);
- end;
-
- end.
-