NMFtp.pas
上传用户:szzdds
上传日期:2013-09-18
资源大小:293k
文件大小:74k
源码类别:

Delphi控件源码

开发平台:

Delphi

  1. unit NMFtp;
  2. {$X+}
  3. {$R-}
  4. {$IFDEF VER100}
  5. {$DEFINE NMF3}
  6. {$ENDIF}
  7. {$IFDEF VER110}
  8. {$DEFINE NMF3}
  9. {$ENDIF}
  10. {$IFDEF VER120}
  11. {$DEFINE NMF3}
  12. {$ENDIF}
  13. {$IFDEF VER125}
  14. {$DEFINE NMF3}
  15. {$ENDIF}
  16. interface
  17. uses
  18.   SysUtils, WinProcs, Classes, PSock, Forms, WinSock, NMConst;
  19. {$IFDEF VER110}
  20. {$OBJEXPORTALL On}
  21. {$ENDIF}
  22. {$IFDEF VER120}
  23. {$OBJEXPORTALL On}
  24. {$ENDIF}
  25. {$IFDEF VER125}
  26. {$OBJEXPORTALL On}
  27. {$ENDIF}
  28. const
  29.    {Transmission Type}
  30.   MODE_ASCII = 1;
  31.   MODE_IMAGE = 2;
  32.   MODE_BYTE = 3;
  33.    //  CompName     ='NMFTP';
  34.    //  Major_Version='4';
  35.    //  Minor_Version='02';
  36.    //  Date_Version ='012798';
  37. const {protocol}
  38.   Cont_Quit = 'QUIT';
  39.   Cont_User = 'USER ';
  40.   Cont_Pass = 'PASS ';
  41.   Cont_Cwd = 'CWD ';
  42.   Cont_Rnfr = 'RNFR ';
  43.   Cont_Rnto = 'RNTO ';
  44.   Cont_Dele = 'DELE ';
  45.   Cont_Mkd = 'MKD ';
  46.   Cont_Rmd = 'RMD ';
  47.   Cont_Port = 'PORT ';
  48.   Cont_List = 'LIST';
  49.   Cont_Nlst = 'NLST';
  50.   Cont_Retr = 'RETR ';
  51.   Cont_Stou = 'STOU';
  52.   Cont_Stor = 'STOR ';
  53.   Cont_Pwd = 'PWD';
  54.   Cont_Typ = 'TYPE ';
  55.   No_Byte = 'BYTE';
  56.   Cont_Rein = 'REIN';
  57.   Cont_Allo = 'ALLO ';
  58.   Cont_Appe = 'APPE ';
  59.   Cont_Rest = 'REST ';
  60. const
  61.   NMOS_UNKNOWN = -1;
  62.   NMOS_FIRST = 2400;
  63.   NMOS_UNIX = 2400;
  64.   NMOS_WINDOWS = 2401;
  65.   NMOS_VM = 2402;
  66.   NMOS_BULL = 2403;
  67.   NMOS_MAC = 2404;
  68.   NMOS_TOPS20 = 2405;
  69.   NMOS_VMS = 2406;
  70.   NMOS_OS2 = 2407;
  71.   NMOS_MVS_IBM = 2408;
  72.   NMOS_MVS_INTERLINK = 2409;
  73.   NMOS_OTHER = 2410;
  74.   NMOS_AUTO = 2411;
  75.   NMOS_NT = 2412;
  76.   NMOS_TANDEM = 2413;
  77.   NMOS_AS400 = 2414;
  78.   NMOS_OS9 = 2415;
  79.   NMOS_NETWARE = 2416;
  80. type
  81.   TFirewallType = (FTUser, FtOpen, FtSite);
  82.   TFTPDirectoryList = class(TObject)
  83.   private
  84.     FAttribute, FName, FModifDate, FSize: TStringList;
  85.     tokens: array[1..25] of shortstring;
  86.     NoTokens: integer;
  87.   protected
  88.   public
  89.     constructor Create;
  90.     destructor Destroy; override;
  91.     procedure ParseLine(Line: string); virtual;
  92.     procedure Clear;
  93.     property Attribute: TStringList read FAttribute;
  94.     property Name: TStringList read FName;
  95.     property Size: TStringList read FSize;
  96.     property ModifDate: TStringList read FModifDate;
  97.   published
  98.   end; {_ TFTPDirectoryList = class(TObject) _}
  99.   TFTPUnixList = class(TFTPDirectoryList)
  100.   public
  101.     procedure ParseLine(Line: string); override;
  102.   end; {_ TFTPUnixList = class(TFTPDirectoryList) _}
  103.   TFTPNETWAREList = class(TFTPDirectoryList)
  104.   public
  105.     procedure ParseLine(Line: string); override;
  106.   end; {_ TFTPNETWAREList = class(TFTPDirectoryList) _}
  107.   TFTPDOSList = class(TFTPDirectoryList)
  108.   public
  109.     procedure ParseLine(Line: string); override;
  110.   end; {_ TFTPDOSList = class(TFTPDirectoryList) _}
  111.   TFTPVMSList = class(TFTPDirectoryList)
  112.   public
  113.     procedure ParseLine(Line: string); override;
  114.   end; {_ TFTPVMSList = class(TFTPDirectoryList) _}
  115.   TFTPMVSList = class(TFTPDirectoryList)
  116.   public
  117.     procedure ParseLine(Line: string); override;
  118.   end; {_ TFTPMVSList = class(TFTPDirectoryList) _}
  119.   TFTPVMList = class(TFTPDirectoryList)
  120.   public
  121.     procedure ParseLine(Line: string); override;
  122.   end; {_ TFTPVMList = class(TFTPDirectoryList) _}
  123.   TFTPMACOSList = class(TFTPDirectoryList)
  124.   public
  125.     procedure ParseLine(Line: string); override;
  126.   end; {_ TFTPMACOSList = class(TFTPDirectoryList) _}
  127.   TFTPAS400List = class(TFTPDirectoryList)
  128.   public
  129.     procedure ParseLine(Line: string); override;
  130.   end; {_ TFTPAS400List = class(TFTPDirectoryList) _}
  131.   TFTPOTHERList = class(TFTPDirectoryList)
  132.   public
  133.     procedure ParseLine(Line: string); override;
  134.   end; {_ TFTPOTHERList = class(TFTPDirectoryList) _}
  135. type
  136.   TCmdType = (cmdChangeDir,
  137.     cmdMakeDir,
  138.     cmdDelete,
  139.     cmdRemoveDir,
  140.     cmdList,
  141.     cmdRename,
  142.     cmdUpRestore,
  143.     cmdDownRestore,
  144.     cmdDownload,
  145.     cmdUpload,
  146.     cmdAppend,
  147.     cmdReInit,
  148.     cmdAllocate,
  149.     cmdNList,
  150.     cmdDoCommand,
  151.     cmdCurrentDir);
  152.   FTPException = class(Exception); {FTP Exceptions}
  153.   TFailureEvent = procedure(var Handled: Boolean; Trans_Type: TCmdType) of object;
  154.   TSuccessEvent = procedure(Trans_Type: TCmdType) of object;
  155.   TUnsupportedEvent = procedure(Trans_Type: TCmdType) of object;
  156.   TNMListItem = procedure(Listing: string) of object;
  157.    {*******************************************************************************************
  158.    FTP Class Definition
  159.    ********************************************************************************************}
  160.   TNMFTP = class(TPowersock)
  161.   private
  162.     ProcessLock: TRTLCriticalSection;
  163.     FUserID, FPassword: string; {Password and User ID strings}
  164.     FPassive: Boolean;
  165.     DataSocket: TPowersock; {Socket for Data Transfers}
  166.     FTransactionStart, FTransactionStop: TNotifyEvent; {Handler after each packet received for progress reports etc}
  167.     FOnSuccess: TSuccessEvent;
  168.     FOnFailure: TFailureEvent;
  169.     FOnAuthenticationNeeded: THandlerEvent;
  170.     FOnAuthenticationFailed: THandlerEvent;
  171.     FOnListItem: TNMListItem;
  172.     FOnConnect: TNotifyEvent;
  173.     FOnUnSupportedFunction: TUnsupportedEvent;
  174.     FVendor: integer;
  175.     FFTPDirectoryList: TFTPDirectoryList;
  176.     FParseList: Boolean;
  177.     FFirewallType: TFirewallType;
  178.       // Added these 2 property containers to support user ID and password
  179.       // with firewalls
  180.     FFWUserID, FFWPassword: string;
  181.       // Added FFWAuth property container for optional firewall authentication
  182.     FFWAuth: Boolean;
  183.     FListMask: string;
  184.     function GetBytesRcvd: Longint;
  185.     function GetBytesSent: Longint;
  186.     function GetBytesTotal(Replymess: string): Longint;
  187.     function Transaction(const CommandString: string): string; override;
  188.     procedure CheckRead(Sender: TObject);
  189.     function GetCurrentDir: string;
  190.     procedure ReadExtraLines(Replymess: string);
  191.     procedure Flush;
  192.       { FTPStatus:TStringEvent ;  }
  193.   protected
  194.       { Protected declarations }
  195.   public
  196.     constructor Create(AOwner: TComponent); override;
  197.     procedure Connect; override;
  198.     destructor Destroy; override;
  199.     procedure Disconnect; override;
  200.     procedure DoCommand(CommandStr: string);
  201.     procedure ChangeDir(DirName: string);
  202.     procedure Mode(TheMode: integer);
  203.     procedure Delete(Filename: string);
  204.     procedure MakeDirectory(DirectoryName: string);
  205.     procedure RemoveDir(DirectoryName: string);
  206.     procedure List;
  207.     procedure Rename(Filename, FileName2: string);
  208.     procedure Download(RemoteFile, LocalFile: string);
  209.     procedure DownloadRestore(RemoteFile, LocalFile: string);
  210.     procedure Upload(LocalFile, RemoteFile: string);
  211.     procedure UploadUnique(LocalFile: string);
  212.     procedure UploadAppend(LocalFile, RemoteFile: string);
  213.     procedure UploadRestore(LocalFile, RemoteFile: string; Position: integer);
  214.     procedure Reinitialize;
  215.     procedure Allocate(FileSize: integer);
  216.     procedure Nlist;
  217.     procedure Abort; override;
  218.     property CurrentDir: string read GetCurrentDir;
  219.     property BytesSent: Longint read GetBytesSent;
  220.     property BytesRecvd: Longint read GetBytesRcvd;
  221.     property FTPDirectoryList: TFTPDirectoryList read FFTPDirectoryList;
  222.   published
  223.     property OnPacketRecvd;
  224.     property OnPacketSent;
  225.     property OnError;
  226.     property OnConnectionRequired;
  227.     property OnConnect: TNotifyEvent read FOnConnect write FOnConnect;
  228.     property UserID: string read FUserID write FUserID;
  229.     property Password: string read FPassword write FPassword;
  230.     property OnTransactionStart: TNotifyEvent read FTransactionStart write FTransactionStart;
  231.     property OnTransactionStop: TNotifyEvent read FTransactionStop write FTransactionStop;
  232.     property OnAuthenticationNeeded: THandlerEvent read FOnAuthenticationNeeded write FOnAuthenticationNeeded;
  233.     property OnAuthenticationFailed: THandlerEvent read FOnAuthenticationFailed write FOnAuthenticationFailed;
  234.     property OnFailure: TFailureEvent read FOnFailure write FOnFailure;
  235.     property OnSuccess: TSuccessEvent read FOnSuccess write FOnSuccess;
  236.     property OnListItem: TNMListItem read FOnListItem write FOnListItem;
  237.     property OnUnSupportedFunction: TUnsupportedEvent read FOnUnSupportedFunction write FOnUnSupportedFunction;
  238.     property Vendor: integer read FVendor write FVendor;
  239.     property ParseList: Boolean read FParseList write FParseList;
  240.     property Proxy;
  241.     property ProxyPort;
  242.     property Passive: Boolean read FPassive write FPassive;
  243.     property FirewallType: TFirewallType read FFirewallType write FFirewallType;
  244.       // Added these 2 properties to support user ID and password with firewalls
  245.     property FWUserID: string read FFWUserID write FFWUserID;
  246.     property FWPassword: string read FFWPassword write FFWPassword;
  247. // Added FWAuthenticate for optional firewall authentication
  248.     property FWAuthenticate: Boolean read FFWAuth write FFWAuth;
  249.     property ListMask: string read FListMask write FListMask;
  250.   end; {_ TNMFTP            = class(TPowersock) _}
  251. implementation
  252. constructor TFTPDirectoryList.Create;
  253. begin
  254.   inherited Create;
  255.   FAttribute := TStringList.Create;
  256.   FName := TStringList.Create;
  257.   FModifDate := TStringList.Create;
  258.   FSize := TStringList.Create;
  259. end; {_ constructor TFTPDirectoryList.Create; _}
  260. destructor TFTPDirectoryList.Destroy;
  261. begin
  262.   FAttribute.free;
  263.   FModifDate.free;
  264.   FName.free;
  265.   FSize.free;
  266.   inherited Destroy;
  267. end; {_ destructor TFTPDirectoryList.Destroy; _}
  268. procedure TFTPDirectoryList.ParseLine(Line: string);
  269. var
  270.   i, j: integer;
  271.   procedure skipblanks;
  272.   begin
  273.     repeat
  274.       inc(j)
  275.     until (Line[j] <> ' ') or (j > Length(Line));
  276.   end; {_ repeat _}
  277. begin
  278.   for i := 1 to 25 do tokens[i] := ''; //clear tokens;
  279.   i := 1;
  280.   j := 1;
  281.   tokens[1] := '';
  282.   repeat
  283.     if Line[j] <> ' ' then
  284.     begin
  285.       tokens[i] := tokens[i] + Line[j];
  286.       inc(j)
  287.     end {_ if line[i] <> ' ' then _}
  288.     else {_ NOT if line[i] <> ' ' then _}
  289.     begin
  290.       inc(i);
  291.       tokens[i] := '';
  292.       skipblanks;
  293.     end; {_ NOT if line[i] <> ' ' then _}
  294.   until j > Length(Line);
  295.   NoTokens := i;
  296. end; {_ procedure skipblanks; _}
  297. procedure TFTPDirectoryList.Clear;
  298. begin
  299.   FAttribute.Clear;
  300.   FName.Clear;
  301.   FSize.Clear;
  302.   FModifDate.Clear;
  303. end; {_ procedure TFTPDirectoryList.Clear; _}
  304. procedure TFTPUnixList.ParseLine(Line: string);
  305. begin
  306.   inherited ParseLine(Line);
  307.   if NoTokens > 7 then
  308.   begin
  309.     FName.add(tokens[NoTokens]);
  310.     FSize.add(tokens[NoTokens - 4]);
  311.     FModifDate.add(tokens[NoTokens - 3] + ' ' + tokens[NoTokens - 2] + ' ' + tokens[NoTokens - 1]);
  312.     FAttribute.add(tokens[1]);
  313.   end; {_ if NoTokens > 7 then _}
  314. end; {_ procedure TFTPUnixList.ParseLine(Line: string); _}
  315. procedure TFTPNETWAREList.ParseLine(Line: string);
  316. begin
  317.   inherited ParseLine(Line);
  318.   if NoTokens > 7 then
  319.   begin
  320.     FName.add(tokens[NoTokens - 1]);
  321.     FSize.add(tokens[NoTokens - 5]);
  322.     FModifDate.add(tokens[NoTokens - 4] + ' ' + tokens[NoTokens - 3] + ' ' + tokens[NoTokens - 2]);
  323.     FAttribute.add(tokens[1]);
  324.   end; {_ if NoTokens > 7 then _}
  325. end; {_ procedure TFTPNETWAREList.ParseLine(Line: string); _}
  326. procedure TFTPDOSList.ParseLine(Line: string);
  327. begin
  328.   inherited ParseLine(Line);
  329.   if NoTokens > 7 then
  330.   begin
  331.     FName.add(tokens[NoTokens - 1]);
  332.     FSize.add(tokens[NoTokens - 5]);
  333.     FModifDate.add(tokens[NoTokens - 4] + ' ' + tokens[NoTokens - 3] + ' ' + tokens[NoTokens - 2]);
  334.     FAttribute.add(tokens[1]);
  335.   end; {_ if NoTokens > 7 then _}
  336. end; {_ procedure TFTPDOSList.ParseLine(Line: string); _}
  337. procedure TFTPVMSList.ParseLine(Line: string);
  338. begin
  339.   inherited ParseLine(Line);
  340.   if NoTokens > 7 then
  341.   begin
  342.     FName.add(tokens[NoTokens - 1]);
  343.     FSize.add(tokens[NoTokens - 5]);
  344.     FModifDate.add(tokens[NoTokens - 4] + ' ' + tokens[NoTokens - 3] + ' ' + tokens[NoTokens - 2]);
  345.     FAttribute.add(tokens[1]);
  346.   end; {_ if NoTokens > 7 then _}
  347. end; {_ procedure TFTPVMSList.ParseLine(Line: string); _}
  348. procedure TFTPMVSList.ParseLine(Line: string);
  349. begin
  350.   inherited ParseLine(Line);
  351.   if NoTokens > 7 then
  352.   begin
  353.     FName.add(tokens[NoTokens - 1]);
  354.     FSize.add(tokens[NoTokens - 5]);
  355.     FModifDate.add(tokens[NoTokens - 4] + ' ' + tokens[NoTokens - 3] + ' ' + tokens[NoTokens - 2]);
  356.     FAttribute.add(tokens[1]);
  357.   end; {_ if NoTokens > 7 then _}
  358. end; {_ procedure TFTPMVSList.ParseLine(Line: string); _}
  359. procedure TFTPVMList.ParseLine(Line: string);
  360. begin
  361.   inherited ParseLine(Line);
  362.   if NoTokens > 7 then
  363.   begin
  364.     FName.add(tokens[NoTokens - 1]);
  365.     FSize.add(tokens[NoTokens - 5]);
  366.     FModifDate.add(tokens[NoTokens - 4] + ' ' + tokens[NoTokens - 3] + ' ' + tokens[NoTokens - 2]);
  367.     FAttribute.add(tokens[1]);
  368.   end; {_ if NoTokens > 7 then _}
  369. end; {_ procedure TFTPVMList.ParseLine(Line: string); _}
  370. procedure TFTPMACOSList.ParseLine(Line: string);
  371. begin
  372.   inherited ParseLine(Line);
  373.   if NoTokens > 7 then
  374.   begin
  375.     FName.add(tokens[NoTokens - 1]);
  376.     FSize.add(tokens[NoTokens - 5]);
  377.     FModifDate.add(tokens[NoTokens - 4] + ' ' + tokens[NoTokens - 3] + ' ' + tokens[NoTokens - 2]);
  378.     FAttribute.add(tokens[1]);
  379.   end; {_ if NoTokens > 7 then _}
  380. end; {_ procedure TFTPMACOSList.ParseLine(Line: string); _}
  381. procedure TFTPAS400List.ParseLine(Line: string);
  382. begin
  383.   inherited ParseLine(Line);
  384.   if NoTokens > 3 then
  385.   begin
  386.     if tokens[NoTokens][1] = '*' then
  387.       FName.add(tokens[NoTokens])
  388.     else FName.add(tokens[NoTokens - 1]);
  389.     FAttribute.add(tokens[1]);
  390.   end; {_ if NoTokens > 7 then _}
  391. end; {_ procedure TFTPAS400List.ParseLine(Line: string); _}
  392. procedure TFTPOTHERList.ParseLine(Line: string);
  393. begin
  394.   inherited ParseLine(Line);
  395.   if NoTokens > 7 then
  396.   begin
  397.     FName.add(tokens[NoTokens]);
  398.     FSize.add(tokens[NoTokens - 4]);
  399.     FModifDate.add(tokens[NoTokens - 3] + ' ' + tokens[NoTokens - 2] + ' ' + tokens[NoTokens - 1]);
  400.     FAttribute.add(tokens[1]);
  401.   end; {_ if NoTokens > 7 then _}
  402. end; {_ procedure TFTPOTHERList.ParseLine(Line: string); _}
  403. {*******************************************************************************************
  404. Initialize the  TNMFTP Component
  405. ********************************************************************************************}
  406. constructor TNMFTP.Create;
  407. begin
  408.   inherited Create(AOwner); {Do Inherited create}
  409.   Port := 21; {Set Default Port}
  410.    {OnRead:=ProcessIdleRead;}{Set read functions for Asyncronous Reads}
  411.   DataSocket := nil;
  412.   FFTPDirectoryList := nil;
  413.   FVendor := NMOS_AUTO;
  414.   OnRead := CheckRead;
  415.   InitializeCriticalSection(ProcessLock);
  416. end; {_ constructor TNMFTP.Create; _}
  417. destructor TNMFTP.Destroy;
  418. begin
  419.   Cancel;
  420.   DeleteCriticalSection(ProcessLock);
  421.  //  if Connected then Disconnect;
  422.   if FFTPDirectoryList <> nil then
  423.     FFTPDirectoryList.free;
  424.   inherited Destroy;
  425. end; {_ destructor TNMFTP.Destroy; _}
  426. {*******************************************************************************************
  427. Disconnect from server
  428. ********************************************************************************************}
  429. procedure TNMFTP.Disconnect;
  430. var
  431.   Replymess: string;
  432. begin
  433.   BeenCanceled := False; {Reset Cancelled flag}
  434.   if Connected then
  435.       {If Connected}
  436.   begin
  437.     StatusMessage(Status_Informational, Cont_Quit); {Inform Status}
  438.     try
  439.       FFTPDirectoryList.free;
  440.       FFTPDirectoryList := nil;
  441.       FVendor := NMOS_AUTO;
  442.       if DataAvailable then Read(0);
  443.       Replymess := Transaction(Cont_Quit); {Do a Quit transaction}
  444.       if ((ReplyNumber > 300) and (ReplyNumber < 600))
  445.         then raise FTPException.Create(Replymess); {If Error raise exception}
  446.       CloseImmediate;
  447.     finally
  448.       inherited Disconnect; {Finally Disconnect}
  449.     end {_ try _}
  450.   end; {_ if Connected then _}
  451. end; {_ procedure TNMFTP.Disconnect; _}
  452. {*******************************************************************************************
  453. Initialize a FTP connection
  454. ********************************************************************************************}
  455. procedure TNMFTP.Connect;
  456. var
  457.   Replymess: string;
  458.   Handled: Boolean;
  459. begin
  460.   BeenCanceled := False; {Reset Cancelled flag}
  461.   if not Connected then
  462.       {If not already connected}
  463.   begin
  464.     ClearInput;
  465.     inherited Connect; {Do the inherited connect}
  466.     try
  467.       Replymess := ' ';
  468.       ReadExtraLines(Replymess);
  469.       if ReplyNumber > 400 then
  470.       begin
  471.         if Assigned(OnConnectionFailed) then OnConnectionFailed(self);
  472.         raise FTPException.Create(Replymess); {If Error show exception}
  473.       end;
  474.          // Below this line added by Edward T. Smith 11/18/1998
  475. // FFWUserID is the firewall user ID
  476.       if FFWAuth then
  477.       begin
  478.         Replymess := Transaction(Cont_User + FFWUserID); {Send User Name and check result}
  479.         if (ReplyNumber > 400) and (ReplyNumber < 600) then
  480.         begin
  481.           if Assigned(OnConnectionFailed) then OnConnectionFailed(self);
  482.           raise FTPException.Create(Replymess); {If Error show exception}
  483.         end;
  484.         if ReplyNumber = 331 then
  485.               {If Password Needed}
  486.         begin
  487.           StatusMessage(Status_Informational, Cont_Pass); {Show outgoing Message} {Show Outgoing Message}
  488.           Replymess := Transaction(Cont_Pass + FFWPassword); {Send Password and check result}
  489. // FFWPassword is the firewall password
  490.           if (ReplyNumber > 400) and (ReplyNumber < 600) then
  491.           begin
  492.             if Assigned(OnConnectionFailed) then OnConnectionFailed(self);
  493.             raise FTPException.Create(Replymess); {If Error show exception}
  494.           end;
  495.         end; {_ if ReplyNumber = 331 then _}
  496.       end; // FIrewall Authentication
  497. // Above this line added by Edward T. Smith 11/18/1998
  498.       if (FUserID = '') or (Password = '') then
  499.         if Assigned(FOnAuthenticationNeeded) then FOnAuthenticationNeeded(Handled);
  500.       if Proxy <> '' then
  501.       begin
  502.         case FFirewallType of
  503.           FTUser: Replymess := Transaction('USER ' + UserID + '@' + Host);
  504.           FtOpen: Replymess := Transaction('OPEN ' + Host);
  505.           FtSite: Replymess := Transaction('SITE ' + Host);
  506.         end;
  507.       end;
  508.       if (Proxy = '') or (FFirewallType <> FTUser) then
  509.       begin
  510.         StatusMessage(Status_Informational, Cont_User + UserID); {Show Outgoing message}
  511.         Replymess := Transaction(Cont_User + UserID); {Send User Name and check result}
  512.         if (ReplyNumber > 400) and (ReplyNumber < 600) then
  513.         begin
  514.           if Assigned(OnConnectionFailed) then OnConnectionFailed(self);
  515.           raise FTPException.Create(Replymess); {If Error show exception}
  516.         end;
  517.       end;
  518.       if ReplyNumber = 331 then
  519.             {If Password Needed}
  520.       begin
  521.         StatusMessage(Status_Informational, Cont_Pass); {Show outgoing Message} {Show Outgoing Message}
  522.         Replymess := Transaction(Cont_Pass + Password); {Send Password and check result}
  523.         if (ReplyNumber > 400) and (ReplyNumber < 600) then
  524.         begin
  525.           if Assigned(OnConnectionFailed) then OnConnectionFailed(self);
  526.           raise FTPException.Create(Replymess); {If Error show exception}
  527.         end;
  528.       end; {_ if ReplyNumber = 331 then _}
  529.       if Assigned(FOnConnect) then FOnConnect(self);
  530.     except {If fault}
  531.       if Connected then Disconnect; {Disconnect}
  532.       StatusMessage(Status_Informational, sFTP_Msg_Disconnect); {Show Status}
  533.       raise; {Show disconnected status}
  534.     end; {_ try _}
  535.   end; {_ if not Connected then _}
  536. end; {_ procedure TNMFTP.Connect; _}
  537. {*******************************************************************************************
  538. Do a generic FTP Command
  539. ********************************************************************************************}
  540. procedure TNMFTP.DoCommand(CommandStr: string);
  541. var Replymess: string;
  542.   Handled: Boolean;
  543.   ThisCmd: TCmdType;
  544. begin
  545.   if NthWord(CommandStr, ' ', 1) + ' ' = Cont_Cwd then ThisCmd := cmdChangeDir
  546.   else if NthWord(CommandStr, ' ', 1) + ' ' = Cont_Dele then ThisCmd := cmdDelete
  547.   else if NthWord(CommandStr, ' ', 1) + ' ' = Cont_Mkd then ThisCmd := cmdMakeDir
  548.   else if NthWord(CommandStr, ' ', 1) + ' ' = Cont_Rmd then ThisCmd := cmdRemoveDir
  549.   else if CommandStr = Cont_Pwd then ThisCmd := cmdCurrentDir
  550.   else {_ NOT if CommandStr = Cont_Pwd then ThisCmd := cmdCurrentDir _}  ThisCmd := cmdDoCommand;
  551.   BeenCanceled := False; {Reset Cancelled flag}
  552.   CertifyConnect;
  553.   if Connected then
  554.       {If connected}
  555.   begin
  556.     StatusMessage(Status_Informational, CommandStr); {Show Outgoing Message}
  557.     if DataAvailable then Read(0);
  558.     Replymess := Transaction(CommandStr); {Send command and chectk result}
  559.     if (ReplyNumber > 399) and (ReplyNumber < 600) then
  560.     begin
  561.       if Assigned(FOnUnSupportedFunction) and (ReplyNumber >= 500) and (ReplyNumber <= 502) then FOnUnSupportedFunction(ThisCmd);
  562.       if not Assigned(FOnFailure) then raise FTPException.Create(Replymess)
  563.             {Raise exception on errors}
  564.       else {_ NOT if not assigned(FOnFailure) then raise FTPException.Create(Replymess) _}
  565.       begin
  566.         Handled := False;
  567.         FOnFailure(Handled, ThisCmd);
  568.         if not Handled then raise FTPException.Create(Replymess);
  569.             {Raise exception on errors}
  570.       end {_ NOT if not assigned(FOnFailure) then raise FTPException.Create(Replymess) _}
  571.     end {_ if (ReplyNumber > 399) and (ReplyNumber < 600) then _}
  572.     else if Assigned(FOnSuccess) then FOnSuccess(ThisCmd);
  573.   end; {_ if Connected then _}
  574. end; {_ procedure TNMFTP.DoCommand(CommandStr: string); _}
  575. {*******************************************************************************************
  576. Change the Dirctory at remote host
  577. ********************************************************************************************}
  578. procedure TNMFTP.ChangeDir(DirName: string);
  579. begin
  580.   DoCommand(Cont_Cwd + DirName); {Do Change Directory}
  581. end; {_ procedure TNMFTP.ChangeDir(DirName: string); _}
  582. {*******************************************************************************************
  583. Rename  File in Remote Server
  584. ********************************************************************************************}
  585. procedure TNMFTP.Rename(Filename, FileName2: string);
  586. var
  587.   Replymess: string;
  588.   Handled: Boolean;
  589. begin
  590.   BeenCanceled := False; {Reset Cancelled flag}
  591.   CertifyConnect;
  592.   if Connected then
  593.       {If connected}
  594.   begin
  595.     if DataAvailable then Read(0);
  596.     StatusMessage(Status_Informational, Cont_Rnfr + Filename); {Show Outgoing Message}
  597.     Replymess := Transaction(Cont_Rnfr + Filename); {Send Rename from and check result}
  598.     if (ReplyNumber > 351) and (ReplyNumber < 600) then
  599.       if not Assigned(FOnFailure) then raise FTPException.Create(Replymess)
  600.             {Raise exception on errors}
  601.       else {_ NOT if not assigned(FOnFailure) then raise FTPException.Create(Replymess) _}
  602.       begin
  603.         Handled := False;
  604.         FOnFailure(Handled, cmdRename);
  605.         if not Handled then raise FTPException.Create(Replymess);
  606.             {Raise exception on errors}
  607.       end; {_ NOT if not assigned(FOnFailure) then raise FTPException.Create(Replymess) _}
  608.     StatusMessage(Status_Informational, Cont_Rnto + FileName2); {Show Outgoing Message}
  609.     Replymess := Transaction(Cont_Rnto + FileName2); {Send Rename to and check result}
  610.     if (ReplyNumber > 300) and (ReplyNumber < 600) then
  611.     begin
  612.       if Assigned(FOnUnSupportedFunction) and (ReplyNumber >= 500) and (ReplyNumber <= 502) then FOnUnSupportedFunction(cmdRename);
  613.       if not Assigned(FOnFailure) then
  614.         raise FTPException.Create(Replymess)
  615.             {Raise exception on errors}
  616.       else {_ NOT if not assigned(FOnFailure) then _}
  617.       begin
  618.         Handled := False;
  619.         FOnFailure(Handled, cmdRename);
  620.         if not Handled then
  621.           raise FTPException.Create(Replymess);
  622.             {Raise exception on errors}
  623.       end {_ NOT if not assigned(FOnFailure) then _}
  624.     end {_ if (ReplyNumber > 300) and (ReplyNumber < 600) then _}
  625.     else if Assigned(FOnSuccess) then FOnSuccess(cmdRename);
  626.   end; {_ if Connected then _} {Resume Asynchronous Processing}
  627. end; {_ procedure TNMFTP.Rename(Filename, FileName2: string); _}
  628. {*******************************************************************************************
  629. Delete file in remote server
  630. ********************************************************************************************}
  631. procedure TNMFTP.Delete(Filename: string);
  632. begin
  633.   DoCommand(Cont_Dele + Filename); {Send Delete command and check result}
  634. end; {_ procedure TNMFTP.Delete(Filename: string); _}
  635. {*******************************************************************************************
  636. Delete file in remote server
  637. ********************************************************************************************}
  638. procedure TNMFTP.MakeDirectory(DirectoryName: string);
  639. begin
  640.   DoCommand(Cont_Mkd + DirectoryName); {Send Delete command and check result}
  641. end; {_ procedure TNMFTP.MakeDirectory(DirectoryName: string); _}
  642. {*******************************************************************************************
  643. Delete file in remote server
  644. ********************************************************************************************}
  645. procedure TNMFTP.RemoveDir(DirectoryName: string);
  646. begin
  647.   DoCommand(Cont_Rmd + DirectoryName); {Send Delete command and check result}
  648. end; {_ procedure TNMFTP.RemoveDir(DirectoryName: string); _}
  649. {*******************************************************************************************
  650. Upload file to Remote Server with unique name
  651. ********************************************************************************************}
  652. procedure TNMFTP.UploadUnique(LocalFile: string);
  653. var
  654.   Replymess: string;
  655.   strm: TFileStream;
  656.   Done, Handled: Boolean;
  657.   Tsck: TSocket;
  658. label CleanUp;
  659. begin
  660.   Done := False;
  661.   BeenCanceled := False; {Reset Cancelled flag}
  662.   CertifyConnect;
  663.   if Connected then
  664.       {If connected}
  665.   begin
  666.     DataSocket := TPowersock.Create(self); {Create a Data socket}
  667.     DataSocket.TimeOut := TimeOut;
  668.     try
  669.       if DataAvailable then Read(0);
  670.       DataSocket.TimeOut := TimeOut;
  671.       DataSocket.Port := 0; {Set Port to Zero}
  672.       DataSocket.Listen(True); {Listen in the datasocket}
  673.       strm := TFileStream.Create(LocalFile, fmOpenRead);
  674.       try
  675.         FBytesTotal := strm.Size;
  676.       finally
  677.         strm.Destroy;
  678.       end; {_ try _}
  679.       StatusMessage(Status_Informational, Cont_Port + GetLocalAddress + DataSocket.GetPortString); {Show Outgoing Message}
  680.       Replymess := Transaction(Cont_Port + GetLocalAddress + DataSocket.GetPortString); {Send Port for data socket}
  681.       if (ReplyNumber > 300) and (ReplyNumber < 600) then
  682.         if not Assigned(FOnFailure) then raise FTPException.Create(Replymess)
  683.                {Raise exception on errors}
  684.         else {_ NOT if not assigned(FOnFailure) then raise FTPException.Create(Replymess) _}
  685.         begin
  686.           Handled := False;
  687.           FOnFailure(Handled, cmdUpload);
  688.           if not Handled then raise FTPException.Create(Replymess)
  689.           else goto CleanUp;
  690.                {Raise exception on errors}
  691.         end; {_ NOT if not assigned(FOnFailure) then raise FTPException.Create(Replymess) _}
  692.       if Assigned(FPacketSent) then
  693.         DataSocket.OnPacketSent := FPacketSent; {Set function to handle data socket status}
  694.       StatusMessage(Status_Informational, Cont_Stou); {Show Outgoing Message}
  695.       Replymess := Transaction(Cont_Stou); {Give store unique cmmand}
  696.       if (ReplyNumber > 300) and (ReplyNumber < 600) then
  697.       begin
  698.         if Assigned(FOnUnSupportedFunction) and (ReplyNumber >= 500) and (ReplyNumber <= 502) then FOnUnSupportedFunction(cmdUpload);
  699.         if not Assigned(FOnFailure) then
  700.           raise FTPException.Create(Replymess)
  701.                {Raise exception on errors}
  702.         else {_ NOT if not assigned(FOnFailure) then _}
  703.         begin
  704.           Handled := False;
  705.           FOnFailure(Handled, cmdUpload);
  706.           if not Handled then
  707.             raise FTPException.Create(Replymess)
  708.           else goto CleanUp;
  709.                {Raise exception on errors}
  710.         end; {_ NOT if not assigned(FOnFailure) then _}
  711.       end; {_ if (ReplyNumber > 300) and (ReplyNumber < 600) then _}
  712.       Tsck := DataSocket.handle;
  713.       DataSocket.ThisSocket := DataSocket.Accept; {Accept the datasocket}
  714.       WinSock.CloseSocket(Tsck);
  715.       if Assigned(FTransactionStart) then FTransactionStart(self);
  716.       if not (BeenCanceled or BeenTimedOut) then DataSocket.SendFile(LocalFile);
  717.          {If no Local filename specified save file same as remote}
  718.       if Assigned(FTransactionStop) then FTransactionStop(self);
  719.       DataSocket.RequestCloseSocket;
  720.       if not (BeenCanceled or BeenTimedOut) then
  721.         if DataAvailable then Readln
  722.         else {_ NOT if DataAvailable > 0 then read (0); _}  Replymess := sFTP_Cont_Msg_UpldS;
  723.       StatusMessage(Status_Informational, Replymess);
  724.       if not (BeenCanceled or BeenTimedOut) then ReadExtraLines(Replymess); {Read Extra Lines}
  725.       Done := True;
  726.       CleanUp:
  727.     finally
  728.       DataSocket.Destroy; {Destroy datasocket}
  729.       DataSocket := nil;
  730.       if Done then if Assigned(FOnSuccess) then FOnSuccess(cmdUpload);
  731.     end; {_ try _}
  732.   end; {_ if Connected then _}
  733. end; {_ procedure TNMFTP.UploadUnique(LocalFile: string); _}
  734. {*******************************************************************************************
  735. List Current Directory in Remote Server
  736. ********************************************************************************************}
  737. procedure TNMFTP.List;
  738. var
  739.   Replymess: string;
  740.   Success, Handled: Boolean;
  741.   Tsck: TSocket;
  742. label CleanUp;
  743. begin
  744.   EnterCriticalSection(ProcessLock);
  745.   Success := False;
  746.   BeenCanceled := False; {If there is a cancelled process reset it}
  747.    //if Fabort then
  748.    //  begin
  749.    //    ReplyMess:= transaction('ABOR');
  750.    //    Fabort := False;
  751.    //  end;
  752.   CertifyConnect; {Make sure Connection exists}
  753.   if Connected then
  754.   begin
  755.     if DataAvailable then Read(0);
  756.     DataSocket := TPowersock.Create(self); {Create a Data socket}
  757.     DataSocket.TimeOut := TimeOut;
  758.     if Assigned(FPacketRecvd) then
  759.       DataSocket.OnPacketRecvd := FPacketRecvd; {Set function to handle data socket status}
  760.     if FParseList then
  761.     begin
  762.       if FFTPDirectoryList = nil then
  763.       begin
  764.         if Vendor = NMOS_AUTO then
  765.         begin
  766.           try DoCommand('SYST')except end;
  767.           if (Pos('UNIX', TransactionReply) > 0) then
  768.             FVendor := NMOS_UNIX
  769.           else if (Pos('NETWARE', TransactionReply) > 0) then
  770.             FVendor := NMOS_NETWARE
  771.           else if (Pos('DOS', TransactionReply) > 0) then
  772.             FVendor := NMOS_WINDOWS
  773.           else if (Pos('VMS', TransactionReply) > 0) then
  774.             FVendor := NMOS_VMS
  775.           else if (Pos('MVS', TransactionReply) > 0) then
  776.             FVendor := NMOS_MVS_IBM
  777.           else if (Pos('VM', TransactionReply) > 0) then
  778.             FVendor := NMOS_VM
  779.           else if (Pos('MACOS', TransactionReply) > 0) then
  780.             FVendor := NMOS_MAC
  781.           else if (Pos('OS/400', TransactionReply) > 0) then
  782.             FVendor := NMOS_AS400
  783.           else {_ NOT if (Pos('OS/400', TransactionReply) > 0) then _}
  784.             FVendor := NMOS_OTHER;
  785.         end; {_ if Vendor = NMOS_AUTO then _}
  786.         case FVendor of
  787.           NMOS_UNIX: FFTPDirectoryList := TFTPUnixList.Create;
  788.           NMOS_NETWARE: FFTPDirectoryList := TFTPUnixList.Create;
  789.           NMOS_WINDOWS: FFTPDirectoryList := TFTPUnixList.Create;
  790.           NMOS_VMS: FFTPDirectoryList := TFTPUnixList.Create;
  791.           NMOS_MVS_IBM: FFTPDirectoryList := TFTPUnixList.Create;
  792.           NMOS_VM: FFTPDirectoryList := TFTPUnixList.Create;
  793.           NMOS_MAC: FFTPDirectoryList := TFTPUnixList.Create;
  794.           NMOS_AS400: FFTPDirectoryList := TFTPUnixList.Create;
  795.           NMOS_OTHER: FFTPDirectoryList := TFTPUnixList.Create;
  796.         end; {_ case FVendor of _}
  797.       end; {_ if FFTPDirectoryList <> nil then _}
  798.       FFTPDirectoryList.Clear;
  799.     end; {_ if FParseList then _}
  800.     DataSocket.TimeOut := TimeOut;
  801.     try
  802.       if FPassive then
  803.       begin
  804.         Replymess := Transaction('PASV');
  805.         if (ReplyNumber > 499) then
  806.           if not Assigned(FOnFailure) then
  807.             raise FTPException.Create(Replymess)
  808.           else
  809.           begin
  810.             Handled := False;
  811.             FOnFailure(Handled, cmdList);
  812.             if not Handled then
  813.               raise FTPException.Create(Replymess)
  814.             else goto CleanUp;
  815.                               {Raise exception on errors}
  816.           end; {_ NOT if not assigned(FOnFailure) then _}
  817.         DataSocket.Port := StrToInt(Copy(NthWord(Replymess, ',', 6), 1, Pos(')', NthWord(Replymess, ',', 6)) - 1)) + (256 * StrToInt(NthWord(Replymess, ',', 5)));
  818.         DataSocket.Host := Host;
  819.         DataSocket.Connect;
  820.       end
  821.       else { _FPassive_ }
  822.       begin
  823.         DataSocket.Port := 0; {Set Port to Zero}
  824.         DataSocket.Listen(True); {Listen in the datasocket}
  825.         Replymess := Transaction(Cont_Port + GetLocalAddress + DataSocket.GetPortString); {Send Port for data socket}
  826.         if (ReplyNumber > 300) and (ReplyNumber < 600) then
  827.           if not Assigned(FOnFailure) then
  828.             raise FTPException.Create(Replymess)
  829.                         {Raise exception on errors}
  830.           else {_ NOT if not assigned(FOnFailure) then _}
  831.           begin
  832.             Handled := False;
  833.             FOnFailure(Handled, cmdList);
  834.             if not Handled then
  835.               raise FTPException.Create(Replymess)
  836.             else goto CleanUp;
  837.                            {Raise exception on errors}
  838.           end; {_ NOT if not assigned(FOnFailure) then _}
  839.       end { not _FPassive_ };
  840.       StatusMessage(Status_Informational, Cont_List); {Show Outgoing Message}
  841.       if FListMask = '' then Replymess := Transaction(Cont_List)
  842.       else Replymess := Transaction(Cont_List + ' ' + FListMask); {Send List command}
  843.       if (ReplyNumber > 300) and (ReplyNumber < 600) then
  844.       begin
  845.         if Assigned(FOnUnSupportedFunction) and (ReplyNumber >= 500) and (ReplyNumber <= 502) then FOnUnSupportedFunction(cmdList);
  846.         if not Assigned(FOnFailure) then
  847.           raise FTPException.Create(Replymess)
  848.                     {Raise exception on errors}
  849.         else {_ NOT if not assigned(FOnFailure) then _}
  850.         begin
  851.           Handled := False;
  852.           FOnFailure(Handled, cmdList);
  853.           if not Handled then
  854.             raise FTPException.Create(Replymess)
  855.           else goto CleanUp;
  856.                   {Raise exception on errors}
  857.         end; {_ NOT if not assigned(FOnFailure) then _}
  858.       end; {_ if (ReplyNumber > 300) and (ReplyNumber < 600) then _}
  859.       if not FPassive then
  860.       begin
  861.         Tsck := DataSocket.handle;
  862.         DataSocket.ThisSocket := DataSocket.Accept; {Accept the datasocket}
  863.         WinSock.CloseSocket(Tsck);
  864.       end;
  865.       if Assigned(FTransactionStart) then FTransactionStart(self);
  866.       while not (BeenCanceled or BeenTimedOut or DataSocket.DataAvailable) and DataSocket.Connected do
  867.         DataSocket.wait;
  868.       if not (BeenCanceled or BeenTimedOut) then
  869.         repeat
  870.           if DataSocket.DataAvailable then
  871.           begin
  872.             Replymess := DataSocket.Readln;
  873.             if (Replymess = '') then Break;
  874.             if Length(Replymess) > 2 then
  875.               if Replymess[Length(Replymess) - 1] = #13 then
  876.                 SetLength(Replymess, Length(Replymess) - 2)
  877.               else
  878.                 SetLength(Replymess, Length(Replymess) - 1);
  879.             if FParseList then
  880.               FFTPDirectoryList.ParseLine(Replymess);
  881.             if Assigned(FOnListItem) then FOnListItem(Replymess);
  882.           end
  883.           else
  884.             DataSocket.wait; //Application.ProcessMessages;
  885.         until (((not DataSocket.Connected) or DataAvailable) and (not DataSocket.DataAvailable)) or BeenTimedOut or BeenCanceled;
  886.       if Assigned(FTransactionStop) then FTransactionStop(self);
  887.       if DataSocket.Connected then DataSocket.RequestCloseSocket;
  888.       if not (BeenCanceled or BeenTimedOut) then
  889.         Replymess := Readln;
  890.       if Replymess = '' then Replymess := '226 Data Transfer successful';
  891.       StatusMessage(Status_Informational, Replymess);
  892.       if not (BeenCanceled or BeenTimedOut) then ReadExtraLines(Replymess); {Read Extra Lines}
  893.       Success := True;
  894.       CleanUp:
  895.     finally
  896.       DataSocket.Destroy; { _Destroy datasocket_ }
  897.       DataSocket := nil;
  898.       if BeenCanceled then
  899.       begin
  900.         BeenCanceled := False;
  901.         Replymess := Transaction('ABOR');
  902.       end;
  903.       LeaveCriticalSection(ProcessLock);
  904.       if Success then if Assigned(FOnSuccess) then FOnSuccess(cmdList);
  905.     end {_ try _}
  906.   end; { _Connected_ }
  907. end;
  908. {*******************************************************************************************
  909. Upload a file to a Remote Server
  910. ********************************************************************************************}
  911. procedure TNMFTP.Upload(LocalFile, RemoteFile: string);
  912. var
  913.   Replymess: string;
  914.   strm: TFileStream;
  915.   Success, Handled: Boolean;
  916.   Tsck: TSocket;
  917. label CleanUp;
  918. begin
  919.   try
  920.     Success := False;
  921.     BeenCanceled := False; {If there is a cancelled process reset it}
  922.     CertifyConnect; {Make sure Connection exists}
  923.     if Connected then
  924.     begin
  925.       EnterCriticalSection(ProcessLock);
  926.       if DataAvailable then Read(0);
  927.       DataSocket := TPowersock.Create(self); {Create a Data socket}
  928.       DataSocket.TimeOut := TimeOut;
  929.       strm := TFileStream.Create(LocalFile, fmOpenRead);
  930.       DataSocket.TimeOut := TimeOut;
  931.       if Assigned(FPacketSent) then
  932.         DataSocket.OnPacketSent := FPacketSent; {Set function to handle data socket status}
  933.       try
  934.         FBytesTotal := strm.Size;
  935.       finally
  936.         strm.Destroy;
  937.       end; {_ try _}
  938.       try
  939.         if FPassive then
  940.         begin
  941.           Replymess := Transaction('PASV');
  942.           if (ReplyNumber > 499) then
  943.             if not Assigned(FOnFailure) then
  944.               raise FTPException.Create(Replymess)
  945.             else
  946.             begin
  947.               Handled := False;
  948.               FOnFailure(Handled, cmdUpload);
  949.               if not Handled then
  950.                 raise FTPException.Create(Replymess)
  951.               else goto CleanUp;
  952.                               {Raise exception on errors}
  953.             end; {_ NOT if not assigned(FOnFailure) then _}
  954.           DataSocket.Port := StrToInt(Copy(NthWord(Replymess, ',', 6), 1, Pos(')', NthWord(Replymess, ',', 6)) - 1)) + (256 * StrToInt(NthWord(Replymess, ',', 5)));
  955.           DataSocket.Host := Host;
  956.           DataSocket.Connect;
  957.         end
  958.         else { _FPassive_ }
  959.         begin
  960.           DataSocket.Port := 0; {Set Port to Zero}
  961.           DataSocket.Listen(True); {Listen in the datasocket}
  962.           Replymess := Transaction(Cont_Port + GetLocalAddress + DataSocket.GetPortString); {Send Port for data socket}
  963.           if (ReplyNumber > 300) and (ReplyNumber < 600) then
  964.             if not Assigned(FOnFailure) then
  965.               raise FTPException.Create(Replymess)
  966.                         {Raise exception on errors}
  967.             else {_ NOT if not assigned(FOnFailure) then _}
  968.             begin
  969.               Handled := False;
  970.               FOnFailure(Handled, cmdUpload);
  971.               if not Handled then
  972.                 raise FTPException.Create(Replymess)
  973.               else goto CleanUp;
  974.                            {Raise exception on errors}
  975.             end; {_ NOT if not assigned(FOnFailure) then _}
  976.         end { not _FPassive_ };
  977.         if RemoteFile = '' then
  978.         begin
  979.           StatusMessage(Status_Informational, Cont_Stor + LocalFile); {Show Outgoing Message}
  980.           Replymess := Transaction(Cont_Stor + ExtractFileName(LocalFile)) {Give store unique cmmand}
  981.         end {_ if RemoteFile = '' then _}
  982.         else {_ NOT if RemoteFile = '' then _}
  983.         begin
  984.           StatusMessage(Status_Informational, Cont_Stor + RemoteFile); {Show Outgoing Message}
  985.           Replymess := Transaction(Cont_Stor + RemoteFile); {Give store unique cmmand}
  986.         end; {_ NOT if RemoteFile = '' then _}
  987.         if (ReplyNumber > 300) and (ReplyNumber < 600) then
  988.         begin
  989.           if Assigned(FOnUnSupportedFunction) and (ReplyNumber >= 500) and (ReplyNumber <= 502) then FOnUnSupportedFunction(cmdUpload);
  990.           if not Assigned(FOnFailure) then
  991.             raise FTPException.Create(Replymess)
  992.                     {Raise exception on errors}
  993.           else {_ NOT if not assigned(FOnFailure) then _}
  994.           begin
  995.             Handled := False;
  996.             FOnFailure(Handled, cmdUpload);
  997.             if not Handled then
  998.               raise FTPException.Create(Replymess)
  999.             else goto CleanUp;
  1000.                      {Raise exception on errors}
  1001.           end; {_ NOT if not assigned(FOnFailure) then _}
  1002.         end; {_ if (ReplyNumber > 300) and (ReplyNumber < 600) then _}
  1003.         if not FPassive then
  1004.         begin
  1005.           Tsck := DataSocket.handle;
  1006.           DataSocket.ThisSocket := DataSocket.Accept; {Accept the datasocket}
  1007.           WinSock.CloseSocket(Tsck);
  1008.         end;
  1009.         if Assigned(FTransactionStart) then FTransactionStart(self);
  1010.         DataSocket.CloseAfterData;
  1011.         if not (BeenCanceled or BeenTimedOut) then DataSocket.SendFile(LocalFile);
  1012.             {If no Local filename specified save file same as remote}
  1013.         if Assigned(FTransactionStop) then FTransactionStop(self);
  1014.         WinSock.CloseSocket(DataSocket.ThisSocket);
  1015.         Replymess := Readln;
  1016.         if Replymess = '' then Replymess := '226 Data Transfer successful';
  1017.         StatusMessage(Status_Informational, Replymess);
  1018.         if not (BeenCanceled or BeenTimedOut) then ReadExtraLines(Replymess); {Read Extra Lines}
  1019.         Success := True;
  1020.         CleanUp:
  1021.       finally
  1022.         DataSocket.Destroy; { _Destroy datasocket_ }
  1023.         DataSocket := nil;
  1024.         LeaveCriticalSection(ProcessLock);
  1025.         if Success then if Assigned(FOnSuccess) then FOnSuccess(cmdUpload);
  1026.       end {_ try _}
  1027.     end; { _Connected_ }
  1028.   except
  1029.     Handled := False;
  1030.     FOnFailure(Handled, cmdUpload);
  1031.     if not Handled then
  1032.       raise;
  1033.   end;
  1034. end;
  1035. {*******************************************************************************************
  1036. Upload a file to a Remote Server
  1037. ********************************************************************************************}
  1038. procedure TNMFTP.UploadRestore(LocalFile, RemoteFile: string; Position: integer);
  1039. var
  1040.   Replymess: string;
  1041.   strm: TFileStream;
  1042.   Success, Handled: Boolean;
  1043.   Tsck: TSocket;
  1044.   gudtLinger: Tlinger;
  1045. label CleanUp;
  1046. begin
  1047.   Success := False;
  1048.   BeenCanceled := False; {If there is a cancelled process reset it}
  1049.   CertifyConnect; {Make sure Connection exists}
  1050.   if Connected then
  1051.   begin
  1052.     if DataAvailable then Read(0);
  1053.     DataSocket := TPowersock.Create(self); {Create a Data socket}
  1054.     DataSocket.TimeOut := TimeOut;
  1055.     strm := TFileStream.Create(LocalFile, fmOpenRead);
  1056.     DataSocket.TimeOut := TimeOut;
  1057.     if Assigned(FPacketSent) then
  1058.       DataSocket.OnPacketSent := FPacketSent; {Set function to handle data socket status}
  1059.     try
  1060.       FBytesTotal := strm.Size;
  1061.     finally
  1062.       strm.Destroy;
  1063.     end; {_ try _}
  1064.     try
  1065.       if FPassive then
  1066.       begin
  1067.         Replymess := Transaction('PASV');
  1068.         if (ReplyNumber > 499) then
  1069.           if not Assigned(FOnFailure) then
  1070.             raise FTPException.Create(Replymess)
  1071.           else
  1072.           begin
  1073.             Handled := False;
  1074.             FOnFailure(Handled, cmdUpload);
  1075.             if not Handled then
  1076.               raise FTPException.Create(Replymess)
  1077.             else goto CleanUp;
  1078.                               {Raise exception on errors}
  1079.           end; {_ NOT if not assigned(FOnFailure) then _}
  1080.         DataSocket.Port := StrToInt(Copy(NthWord(Replymess, ',', 6), 1, Pos(')', NthWord(Replymess, ',', 6)) - 1)) + (256 * StrToInt(NthWord(Replymess, ',', 5)));
  1081.         DataSocket.Host := Host;
  1082.         DataSocket.Connect;
  1083.       end
  1084.       else { _FPassive_ }
  1085.       begin
  1086.         DataSocket.Port := 0; {Set Port to Zero}
  1087.         DataSocket.Listen(True); {Listen in the datasocket}
  1088.         Replymess := Transaction(Cont_Port + GetLocalAddress + DataSocket.GetPortString); {Send Port for data socket}
  1089.         if (ReplyNumber > 300) and (ReplyNumber < 600) then
  1090.           if not Assigned(FOnFailure) then
  1091.             raise FTPException.Create(Replymess)
  1092.                         {Raise exception on errors}
  1093.           else {_ NOT if not assigned(FOnFailure) then _}
  1094.           begin
  1095.             Handled := False;
  1096.             FOnFailure(Handled, cmdUpload);
  1097.             if not Handled then
  1098.               raise FTPException.Create(Replymess)
  1099.             else goto CleanUp;
  1100.                            {Raise exception on errors}
  1101.           end; {_ NOT if not assigned(FOnFailure) then _}
  1102.       end { not _FPassive_ };
  1103.       if RemoteFile = '' then
  1104.       begin
  1105.         StatusMessage(Status_Informational, Cont_Rest + IntToStr(Position) + '' + Cont_Stor); {Show Outgoing Message}
  1106.         Replymess := Transaction(Cont_Rest + IntToStr(Position));
  1107.         Replymess := Transaction(Cont_Stor + ExtractFileName(LocalFile)); {Give store unique cmmand}
  1108.       end {_ if RemoteFile = '' then _}
  1109.       else {_ NOT if RemoteFile = '' then _}
  1110.       begin
  1111.         StatusMessage(Status_Informational, Cont_Rest + IntToStr(Position) + '' + Cont_Stor); {Show Outgoing Message}
  1112.         Replymess := Transaction(Cont_Rest + IntToStr(Position));
  1113.         Replymess := Transaction(Cont_Stor + RemoteFile); {Give store unique cmmand}
  1114.       end; {_ NOT if RemoteFile = '' then _}
  1115.       if (ReplyNumber > 399) and (ReplyNumber < 600) then
  1116.       begin
  1117.         if Assigned(FOnUnSupportedFunction) and (ReplyNumber >= 500) and (ReplyNumber <= 502) then FOnUnSupportedFunction(cmdUpload);
  1118.         if not Assigned(FOnFailure) then
  1119.           raise FTPException.Create(Replymess)
  1120.                     {Raise exception on errors}
  1121.         else {_ NOT if not assigned(FOnFailure) then _}
  1122.         begin
  1123.           Handled := False;
  1124.           FOnFailure(Handled, cmdUpload);
  1125.           if not Handled then
  1126.             raise FTPException.Create(Replymess)
  1127.           else goto CleanUp;
  1128.                      {Raise exception on errors}
  1129.         end; {_ NOT if not assigned(FOnFailure) then _}
  1130.       end; {_ if (ReplyNumber > 300) and (ReplyNumber < 600) then _}
  1131.       if not FPassive then
  1132.       begin
  1133.         Tsck := DataSocket.handle;
  1134.         DataSocket.ThisSocket := DataSocket.Accept; {Accept the datasocket}
  1135.         WinSock.CloseSocket(Tsck);
  1136.       end;
  1137.       if Assigned(FTransactionStart) then FTransactionStart(self);
  1138.       strm := TFileStream.Create(LocalFile, fmOpenRead);
  1139.       strm.Position := Position;
  1140.       try
  1141.         if not (BeenCanceled or BeenTimedOut)
  1142.           then DataSocket.SendRestStream(strm);
  1143.       finally
  1144.         strm.free;
  1145.       end;
  1146.             {If no Local filename specified save file same as remote}
  1147.       if Assigned(FTransactionStop) then FTransactionStop(self);
  1148.       gudtLinger.l_onoff := 0;
  1149.       gudtLinger.l_linger := 0;
  1150.       setsockopt(DataSocket.ThisSocket, SOL_SOCKET, SO_LINGER, @gudtLinger, 4);
  1151.       DataSocket.RequestCloseSocket;
  1152.       if not (BeenCanceled or BeenTimedOut) then
  1153.         Replymess := Read(0);
  1154.       if Replymess = '' then Replymess := '226 Data Transfer successful';
  1155.       StatusMessage(Status_Informational, Replymess);
  1156.       if not (BeenCanceled or BeenTimedOut) then ReadExtraLines(Replymess); {Read Extra Lines}
  1157.       Success := True;
  1158.       CleanUp:
  1159.     finally
  1160.       DataSocket.Destroy; { _Destroy datasocket_ }
  1161.       DataSocket := nil;
  1162.       if Success then if Assigned(FOnSuccess) then FOnSuccess(cmdUpload);
  1163.     end {_ try _}
  1164.   end; { _Connected_ }
  1165. end;
  1166. {*******************************************************************************************
  1167. Download a file from a Remote Server
  1168. ********************************************************************************************}
  1169. procedure TNMFTP.Download(RemoteFile, LocalFile: string);
  1170. var
  1171.   Replymess: string;
  1172.   Success, Handled: Boolean;
  1173.   Tsck: TSocket;
  1174. label CleanUp;
  1175. begin
  1176.   try
  1177.     Success := False;
  1178.     BeenCanceled := False; {If there is a cancelled process reset it}
  1179.     CertifyConnect; {Make sure Connection exists}
  1180.     if Connected then
  1181.     begin
  1182.       EnterCriticalSection(ProcessLock);
  1183.       if DataAvailable then Read(0);
  1184.       DataSocket := TPowersock.Create(self); {Create a Data socket}
  1185.       DataSocket.TimeOut := TimeOut;
  1186.       if Assigned(FPacketRecvd) then
  1187.         DataSocket.OnPacketRecvd := FPacketRecvd; {Set function to handle data socket status}
  1188.       try
  1189.         if FPassive then
  1190.         begin
  1191.           Replymess := Transaction('PASV');
  1192.           if (ReplyNumber > 499) then
  1193.             if not Assigned(FOnFailure) then
  1194.               raise FTPException.Create(Replymess)
  1195.             else
  1196.             begin
  1197.               Handled := False;
  1198.               FOnFailure(Handled, cmdDownload);
  1199.               if not Handled then
  1200.                 raise FTPException.Create(Replymess)
  1201.               else goto CleanUp;
  1202.                               {Raise exception on errors}
  1203.             end; {_ NOT if not assigned(FOnFailure) then _}
  1204.           DataSocket.Port := StrToInt(Copy(NthWord(Replymess, ',', 6), 1, Pos(')', NthWord(Replymess, ',', 6)) - 1)) + (256 * StrToInt(NthWord(Replymess, ',', 5)));
  1205.           DataSocket.Host := Host;
  1206.           DataSocket.Connect;
  1207.         end
  1208.         else { _FPassive_ }
  1209.         begin
  1210.           DataSocket.Port := 0; {Set Port to Zero}
  1211.           DataSocket.Listen(True); {Listen in the datasocket}
  1212.           Replymess := Transaction(Cont_Port + GetLocalAddress + DataSocket.GetPortString); {Send Port for data socket}
  1213.           if (ReplyNumber > 300) and (ReplyNumber < 600) then
  1214.             if not Assigned(FOnFailure) then
  1215.               raise FTPException.Create(Replymess)
  1216.                         {Raise exception on errors}
  1217.             else {_ NOT if not assigned(FOnFailure) then _}
  1218.             begin
  1219.               Handled := False;
  1220.               FOnFailure(Handled, cmdDownload);
  1221.               if not Handled then
  1222.                 raise FTPException.Create(Replymess)
  1223.               else goto CleanUp;
  1224.                            {Raise exception on errors}
  1225.             end; {_ NOT if not assigned(FOnFailure) then _}
  1226.         end { not _FPassive_ };
  1227.         StatusMessage(Status_Informational, Cont_Retr + RemoteFile); {Show Outgoing Message}
  1228.         FBytesTotal := 0;
  1229.         Replymess := inherited Transaction(Cont_Retr + RemoteFile);
  1230.         if (ReplyNumber > 300) and (ReplyNumber < 600) then
  1231.           if not Assigned(FOnFailure) then raise FTPException.Create(Replymess)
  1232.                {Raise exception on errors}
  1233.           else {_ NOT if not assigned(FOnFailure) then raise FTPException.Create(Replymess) _}
  1234.           begin
  1235.             Handled := False;
  1236.             FOnFailure(Handled, cmdDownload);
  1237.             if not Handled then raise FTPException.Create(Replymess)
  1238.             else goto CleanUp;
  1239.                      {Raise exception on errors}
  1240.           end; {_ NOT if not assigned(FOnFailure) then raise FTPException.Create(Replymess) _}
  1241.         FBytesTotal := GetBytesTotal(Replymess);
  1242.         while (Replymess[1] = ' ') or (Replymess[4] = '-') do
  1243.         begin
  1244.           Replymess := Readln; {Handle Extra Lines}
  1245.           StatusMessage(Status_Informational, Replymess); {Show Received Lines}
  1246.           if FBytesTotal = 0 then FBytesTotal := GetBytesTotal(Replymess);
  1247.           if (ReplyNumber > 300) and (ReplyNumber < 600) then
  1248.           begin
  1249.             if Assigned(FOnUnSupportedFunction) and (ReplyNumber >= 500) and (ReplyNumber <= 502) then FOnUnSupportedFunction(cmdDownload);
  1250.             if not Assigned(FOnFailure) then
  1251.               raise FTPException.Create(Replymess)
  1252.                   {Raise exception on errors}
  1253.             else {_ NOT if not assigned(FOnFailure) then _}
  1254.             begin
  1255.               Handled := False;
  1256.               FOnFailure(Handled, cmdDownload);
  1257.               if not Handled then
  1258.                 raise FTPException.Create(Replymess);
  1259.                      {Raise exception on errors}
  1260.             end; {_ NOT if not assigned(FOnFailure) then _}
  1261.           end; {_ if (ReplyNumber > 300) and (ReplyNumber < 600) then _}
  1262.         end; {_ while (Replymess[1] = ' ') or (Replymess[4] = '-') do _}
  1263.         if not FPassive then
  1264.         begin
  1265.           Tsck := DataSocket.handle;
  1266.           DataSocket.ThisSocket := DataSocket.Accept; {Accept the datasocket}
  1267.           WinSock.CloseSocket(Tsck);
  1268.         end;
  1269.         FBytesTotal := GetBytesTotal(Replymess);
  1270.         if Assigned(FTransactionStart) then FTransactionStart(self);
  1271.         if not (BeenCanceled or BeenTimedOut) then
  1272.           if LocalFile = '' then DataSocket.CaptureFile(RemoteFile)
  1273.                {If no Local filename specified save file same as remote}
  1274.           else {_ NOT if LocalFile = '' then DataSocket.CaptureFile(RemoteFile) _}  DataSocket.CaptureFile(LocalFile); {If Local filename specified save file under it}
  1275.         if Assigned(FTransactionStop) then FTransactionStop(self);
  1276.         DataSocket.RequestCloseSocket;
  1277.         FBytesTotal := DataSocket.BytesRecvd;
  1278.         StatusMessage(Status_Informational, (sFTP_Msg_Recvd + IntToStr(BytesTotal) + sFTP_No_Bytes));
  1279.         if not (BeenCanceled or BeenTimedOut) then Replymess := Readln;
  1280.             //if ReplyMess='' then ReplyMess:='226 Data Transfer successful';
  1281.         StatusMessage(Status_Informational, Replymess);
  1282.         if not (BeenCanceled or BeenTimedOut) then ReadExtraLines(Replymess);
  1283.             {Read Extra Lines}
  1284.             {If no Local filename specified save file same as remote}
  1285.         if Assigned(FTransactionStop) then FTransactionStop(self);
  1286.         Success := True;
  1287.         CleanUp:
  1288.       finally
  1289.         DataSocket.Destroy; { _Destroy datasocket_ }
  1290.         DataSocket := nil;
  1291.         if BeenCanceled then
  1292.         begin
  1293.           BeenCanceled := False;
  1294.           Replymess := Transaction('ABOR');
  1295.         end;
  1296.         if Success then if Assigned(FOnSuccess) then FOnSuccess(cmdDownload);
  1297.       end {_ try _}
  1298.     end; { _Connected_ }
  1299.   except
  1300.     Handled := False;
  1301.     FOnFailure(Handled, cmdDownload);
  1302.     if not Handled then
  1303.       raise;
  1304.   end;
  1305. end;
  1306. {*******************************************************************************************
  1307. Download a file from a Remote Server
  1308. ********************************************************************************************}
  1309. procedure TNMFTP.DownloadRestore(RemoteFile, LocalFile: string);
  1310. var
  1311.   Replymess: string;
  1312.   Success, Handled: Boolean;
  1313.   AFileStream: TFileStream;
  1314.   Posn: integer;
  1315.   Tsck: TSocket;
  1316. label CleanUp;
  1317. begin
  1318.   Success := False;
  1319.   BeenCanceled := False; {If there is a cancelled process reset it}
  1320.   CertifyConnect; {Make sure Connection exists}
  1321.   if Connected then
  1322.   begin
  1323.     if DataAvailable then Read(0);
  1324.     DataSocket := TPowersock.Create(self); {Create a Data socket}
  1325.     DataSocket.TimeOut := TimeOut;
  1326.     if LocalFile = '' then LocalFile := RemoteFile;
  1327.     if Assigned(FPacketRecvd) then
  1328.       DataSocket.OnPacketRecvd := FPacketRecvd; {Set function to handle data socket status}
  1329.     try
  1330.       if FPassive then
  1331.       begin
  1332.         Replymess := Transaction('PASV');
  1333.         if (ReplyNumber > 499) then
  1334.           if not Assigned(FOnFailure) then
  1335.             raise FTPException.Create(Replymess)
  1336.           else
  1337.           begin
  1338.             Handled := False;
  1339.             FOnFailure(Handled, cmdDownload);
  1340.             if not Handled then
  1341.               raise FTPException.Create(Replymess)
  1342.             else goto CleanUp;
  1343.                               {Raise exception on errors}
  1344.           end; {_ NOT if not assigned(FOnFailure) then _}
  1345.         DataSocket.Port := StrToInt(Copy(NthWord(Replymess, ',', 6), 1, Pos(')', NthWord(Replymess, ',', 6)) - 1)) + (256 * StrToInt(NthWord(Replymess, ',', 5)));
  1346.         DataSocket.Host := Host;
  1347.         DataSocket.Connect;
  1348.       end
  1349.       else { _FPassive_ }
  1350.       begin
  1351.         DataSocket.Port := 0; {Set Port to Zero}
  1352.         DataSocket.Listen(True); {Listen in the datasocket}
  1353.         Replymess := Transaction(Cont_Port + GetLocalAddress + DataSocket.GetPortString); {Send Port for data socket}
  1354.         if (ReplyNumber > 300) and (ReplyNumber < 600) then
  1355.           if not Assigned(FOnFailure) then
  1356.             raise FTPException.Create(Replymess)
  1357.                         {Raise exception on errors}
  1358.           else {_ NOT if not assigned(FOnFailure) then _}
  1359.           begin
  1360.             Handled := False;
  1361.             FOnFailure(Handled, cmdDownload);
  1362.             if not Handled then
  1363.               raise FTPException.Create(Replymess)
  1364.             else goto CleanUp;
  1365.                            {Raise exception on errors}
  1366.           end; {_ NOT if not assigned(FOnFailure) then _}
  1367.       end { not _FPassive_ };
  1368.       try
  1369.         AFileStream := TFileStream.Create(LocalFile, fmOpenRead); {If Local filename specified save file under it}
  1370.         Posn := AFileStream.Size;
  1371.         AFileStream.free;
  1372.       except
  1373.         Posn := 0;
  1374.       end;
  1375.       StatusMessage(Status_Informational, Cont_Rest + Cont_Retr + RemoteFile); {Show Outgoing Message}
  1376.       FBytesTotal := 0;
  1377.       Replymess := inherited Transaction(Cont_Rest + IntToStr(Posn));
  1378.       Replymess := inherited Transaction(Cont_Retr + RemoteFile);
  1379.       if (ReplyNumber > 300) and (ReplyNumber < 600) then
  1380.         if not Assigned(FOnFailure) then raise FTPException.Create(Replymess)
  1381.                {Raise exception on errors}
  1382.         else {_ NOT if not assigned(FOnFailure) then raise FTPException.Create(Replymess) _}
  1383.         begin
  1384.           Handled := False;
  1385.           FOnFailure(Handled, cmdDownload);
  1386.           if not Handled then raise FTPException.Create(Replymess);
  1387.                      {Raise exception on errors}
  1388.         end; {_ NOT if not assigned(FOnFailure) then raise FTPException.Create(Replymess) _}
  1389.       FBytesTotal := GetBytesTotal(Replymess);
  1390.       while (Replymess[1] = ' ') or (Replymess[4] = '-') do
  1391.       begin
  1392.         Replymess := Readln; {Handle Extra Lines}
  1393.         StatusMessage(Status_Informational, Replymess); {Show Received Lines}
  1394.         if FBytesTotal = 0 then FBytesTotal := GetBytesTotal(Replymess);
  1395.         if (ReplyNumber > 300) and (ReplyNumber < 600) then
  1396.         begin
  1397.           if Assigned(FOnUnSupportedFunction) and (ReplyNumber >= 500) and (ReplyNumber <= 502) then FOnUnSupportedFunction(cmdDownload);
  1398.           if not Assigned(FOnFailure) then
  1399.             raise FTPException.Create(Replymess)
  1400.                   {Raise exception on errors}
  1401.           else {_ NOT if not assigned(FOnFailure) then _}
  1402.           begin
  1403.             Handled := False;
  1404.             FOnFailure(Handled, cmdDownload);
  1405.             if not Handled then
  1406.               raise FTPException.Create(Replymess);
  1407.                      {Raise exception on errors}
  1408.           end; {_ NOT if not assigned(FOnFailure) then _}
  1409.         end; {_ if (ReplyNumber > 300) and (ReplyNumber < 600) then _}
  1410.       end; {_ while (Replymess[1] = ' ') or (Replymess[4] = '-') do _}
  1411.       if not FPassive then
  1412.       begin
  1413.         Tsck := DataSocket.handle;
  1414.         DataSocket.ThisSocket := DataSocket.Accept; {Accept the datasocket}
  1415.         WinSock.CloseSocket(Tsck);
  1416.       end;
  1417.       FBytesTotal := GetBytesTotal(Replymess);
  1418.       if Assigned(FTransactionStart) then FTransactionStart(self);
  1419.       if not (BeenCanceled or BeenTimedOut) then
  1420.         if LocalFile = '' then DataSocket.AppendFile(RemoteFile)
  1421.                {If no Local filename specified save file same as remote}
  1422.         else {_ NOT if LocalFile = '' then DataSocket.CaptureFile(RemoteFile) _}  DataSocket.AppendFile(LocalFile); {If Local filename specified save file under it}
  1423.       if Assigned(FTransactionStop) then FTransactionStop(self);
  1424.       DataSocket.RequestCloseSocket;
  1425.       FBytesTotal := DataSocket.BytesRecvd;
  1426.       StatusMessage(Status_Informational, (sFTP_Msg_Recvd + IntToStr(BytesTotal) + sFTP_No_Bytes));
  1427.       if not (BeenCanceled or BeenTimedOut) then Replymess := Read(0);
  1428.       if Replymess = '' then Replymess := '226 Data Transfer successful';
  1429.       StatusMessage(Status_Informational, Replymess);
  1430.       if not (BeenCanceled or BeenTimedOut) then ReadExtraLines(Replymess);
  1431.             {Read Extra Lines}
  1432.             {If no Local filename specified save file same as remote}
  1433.       if Assigned(FTransactionStop) then FTransactionStop(self);
  1434.       Success := True;
  1435.       CleanUp:
  1436.     finally
  1437.       DataSocket.Destroy; { _Destroy datasocket_ }
  1438.       DataSocket := nil;
  1439.       if BeenCanceled then
  1440.       begin
  1441.         BeenCanceled := False;
  1442.         Replymess := Transaction('ABOR');
  1443.       end;
  1444.       if Success then if Assigned(FOnSuccess) then FOnSuccess(cmdDownload);
  1445.     end {_ try _}
  1446.   end; { _Connected_ }
  1447. end;
  1448. {*******************************************************************************************
  1449. Upload a file to a Remote Server  and append to existing file
  1450. ********************************************************************************************}
  1451. procedure TNMFTP.UploadAppend(LocalFile, RemoteFile: string);
  1452. var
  1453.   Replymess: string;
  1454.   strm: TFileStream;
  1455.   Success, Handled: Boolean;
  1456.   Tsck: TSocket;
  1457. label CleanUp;
  1458. begin
  1459.   Success := False;
  1460.   BeenCanceled := False; {If there is a cancelled process reset it}
  1461.   CertifyConnect; {Make sure Connection exists}
  1462.   if Connected then
  1463.   begin
  1464.     if DataAvailable then Read(0);
  1465.     DataSocket := TPowersock.Create(self); {Create a Data socket}
  1466.     DataSocket.TimeOut := TimeOut;
  1467.     strm := TFileStream.Create(LocalFile, fmOpenRead);
  1468.     DataSocket.TimeOut := TimeOut;
  1469.     if Assigned(FPacketSent) then
  1470.       DataSocket.OnPacketSent := FPacketSent; {Set function to handle data socket status}
  1471.     try
  1472.       FBytesTotal := strm.Size;
  1473.     finally
  1474.       strm.Destroy;
  1475.     end; {_ try _}
  1476.     try
  1477.       if FPassive then
  1478.       begin
  1479.         Replymess := Transaction('PASV');
  1480.         if (ReplyNumber > 499) then
  1481.           if not Assigned(FOnFailure) then
  1482.             raise FTPException.Create(Replymess)
  1483.           else
  1484.           begin
  1485.             Handled := False;
  1486.             FOnFailure(Handled, cmdAppend);
  1487.             if not Handled then
  1488.               raise FTPException.Create(Replymess)
  1489.             else goto CleanUp;
  1490.                               {Raise exception on errors}
  1491.           end; {_ NOT if not assigned(FOnFailure) then _}
  1492.         DataSocket.Port := StrToInt(Copy(NthWord(Replymess, ',', 6), 1, Pos(')', NthWord(Replymess, ',', 6)) - 1)) + (256 * StrToInt(NthWord(Replymess, ',', 5)));
  1493.         DataSocket.Host := Host;
  1494.         DataSocket.Connect;
  1495.       end
  1496.       else { _FPassive_ }
  1497.       begin
  1498.         DataSocket.Port := 0; {Set Port to Zero}
  1499.         DataSocket.Listen(True); {Listen in the datasocket}
  1500.         Replymess := Transaction(Cont_Port + GetLocalAddress + DataSocket.GetPortString); {Send Port for data socket}
  1501.         if (ReplyNumber > 300) and (ReplyNumber < 600) then
  1502.           if not Assigned(FOnFailure) then
  1503.             raise FTPException.Create(Replymess)
  1504.                         {Raise exception on errors}
  1505.           else {_ NOT if not assigned(FOnFailure) then _}
  1506.           begin
  1507.             Handled := False;
  1508.             FOnFailure(Handled, cmdAppend);
  1509.             if not Handled then
  1510.               raise FTPException.Create(Replymess)
  1511.             else goto CleanUp;
  1512.                            {Raise exception on errors}
  1513.           end; {_ NOT if not assigned(FOnFailure) then _}
  1514.       end { not _FPassive_ };
  1515.       if RemoteFile = '' then
  1516.       begin
  1517.         StatusMessage(Status_Informational, Cont_Appe + LocalFile); {Show Outgoing Message}
  1518.         Replymess := Transaction(Cont_Appe + ExtractFileName(LocalFile)) {Give store unique cmmand}
  1519.       end {_ if RemoteFile = '' then _}
  1520.       else {_ NOT if RemoteFile = '' then _}
  1521.       begin
  1522.         StatusMessage(Status_Informational, Cont_Appe + RemoteFile); {Show Outgoing Message}
  1523.         Replymess := Transaction(Cont_Appe + RemoteFile); {Give store unique cmmand}
  1524.       end; {_ NOT if RemoteFile = '' then _}
  1525.       if (ReplyNumber > 300) and (ReplyNumber < 600) then
  1526.       begin
  1527.         if Assigned(FOnUnSupportedFunction) and (ReplyNumber >= 500) and (ReplyNumber <= 502) then FOnUnSupportedFunction(cmdAppend);
  1528.         if not Assigned(FOnFailure) then
  1529.           raise FTPException.Create(Replymess)
  1530.                     {Raise exception on errors}
  1531.         else {_ NOT if not assigned(FOnFailure) then _}
  1532.         begin
  1533.           Handled := False;
  1534.           FOnFailure(Handled, cmdAppend);
  1535.           if not Handled then
  1536.             raise FTPException.Create(Replymess)
  1537.           else goto CleanUp;
  1538.                      {Raise exception on errors}
  1539.         end; {_ NOT if not assigned(FOnFailure) then _}
  1540.       end; {_ if (ReplyNumber > 300) and (ReplyNumber < 600) then _}
  1541.       if not FPassive then
  1542.       begin
  1543.         Tsck := DataSocket.handle;
  1544.         DataSocket.ThisSocket := DataSocket.Accept; {Accept the datasocket}
  1545.         WinSock.CloseSocket(Tsck);
  1546.       end;
  1547.       if Assigned(FTransactionStart) then FTransactionStart(self);
  1548.       if not (BeenCanceled or BeenTimedOut) then DataSocket.SendFile(LocalFile);
  1549.             {If no Local filename specified save file same as remote}
  1550.       if Assigned(FTransactionStop) then FTransactionStop(self);
  1551.       CloseAfterData;
  1552.       DataSocket.RequestCloseSocket;
  1553.       if not (BeenCanceled or BeenTimedOut) then
  1554.         Replymess := Readln;
  1555.       if Replymess = '' then Replymess := '226 Data Transfer successful';
  1556.       StatusMessage(Status_Informational, Replymess);
  1557.       if not (BeenCanceled or BeenTimedOut) then ReadExtraLines(Replymess); {Read Extra Lines}
  1558.       Success := True;
  1559.       CleanUp:
  1560.     finally
  1561.       DataSocket.Destroy; { _Destroy datasocket_ }
  1562.       DataSocket := nil;
  1563.       if Success then if Assigned(FOnSuccess) then FOnSuccess(cmdAppend);
  1564.     end {_ try _}
  1565.   end; { _Connected_ }
  1566. end;
  1567. {*******************************************************************************************
  1568. Get Current Directory in Remote Server
  1569. ********************************************************************************************}
  1570. function TNMFTP.GetCurrentDir;
  1571. begin
  1572.   DoCommand(Cont_Pwd); {Send get Current directory Command}
  1573.   Result := NthWord(TransactionReply, '"', 2);
  1574. end; {_ function TNMFTP.GetCurrentDir; _}
  1575. {*******************************************************************************************
  1576. Change the mode for file transactions
  1577. ********************************************************************************************}
  1578. procedure TNMFTP.Mode(TheMode: integer);
  1579. begin
  1580.   case TheMode of
  1581.     MODE_ASCII: DoCommand(Cont_Typ + 'A'); {Send AsCII Command}
  1582.     MODE_IMAGE: DoCommand(Cont_Typ + 'I'); {Send Image Command}
  1583.     MODE_BYTE: DoCommand(Cont_Typ + 'L 8'); {Send Byte Command}
  1584.   end; {_ case TheMode of _}
  1585. end; {_ procedure TNMFTP.Mode(TheMode: Integer); _}
  1586. {*******************************************************************************************
  1587. Get the value of BytesReceived property
  1588. ********************************************************************************************}
  1589. function TNMFTP.GetBytesRcvd;
  1590. begin Result := DataSocket.BytesRecvd end;
  1591. {*******************************************************************************************
  1592. Get the value of BytesReceived property
  1593. ********************************************************************************************}
  1594. function TNMFTP.GetBytesSent;
  1595. begin Result := DataSocket.BytesSent end;
  1596. {*******************************************************************************************
  1597. Get the value of BytesTotal property
  1598. ********************************************************************************************}
  1599. function TNMFTP.GetBytesTotal;
  1600. var
  1601.   ReplyP: string[255];
  1602.   i: integer;
  1603. begin
  1604.   i := Pos(No_Byte, UpperCase(Replymess));
  1605.   if i > 0 then
  1606.   begin
  1607.     ReplyP := '';
  1608.     while (Replymess[i] < '0') or (Replymess[i] > '9') do
  1609.       i := i - 1;
  1610.     while (Replymess[i] >= '0') and (Replymess[i] <= '9') do
  1611.       i := i - 1;
  1612.     i := i + 1;
  1613.     while (Replymess[i] >= '0') and (Replymess[i] <= '9') do
  1614.     begin
  1615.       ReplyP := ReplyP + Replymess[i];
  1616.       i := i + 1;
  1617.     end; {_ while (Replymess[I] >= '0') and (Replymess[I] <= '9') do _}
  1618.     Result := StrToIntDef(ReplyP, 0);
  1619.   end {_ if I > 0 then _}
  1620.   else {_ NOT if I > 0 then _}  Result := 0;
  1621. end; {_ function TNMFTP.GetBytesTotal; _}
  1622. {*******************************************************************************************
  1623. Abort a FTP file transaction
  1624. ********************************************************************************************}
  1625. procedure TNMFTP.Abort;
  1626. begin
  1627.   // ReplyMess:= transaction('ABOR');
  1628.   if DataSocket <> nil then
  1629.   begin
  1630.       //DataSocket.FOStream.size := 0;
  1631.     DataSocket.Cancel; {Cancel Read or write}
  1632.   end; {_ if DataSocket <> nil then _}
  1633.   Cancel;
  1634.    //FAbort := True;
  1635. end; {_ procedure TNMFTP.Abort; _}
  1636. {*******************************************************************************************
  1637. Process Extra Lines in Transaction
  1638. ********************************************************************************************}
  1639. function TNMFTP.Transaction(const CommandString: string): string;
  1640. var Replymess: string;
  1641. begin
  1642.   Replymess := inherited Transaction(CommandString);
  1643.   ReadExtraLines(Replymess);
  1644.   Result := Replymess;
  1645. end; {_ function TNMFTP.Transaction(const CommandString: string): string; _}
  1646. procedure TNMFTP.ReadExtraLines;
  1647. begin
  1648.   while (Replymess[1] = ' ') or (Replymess[4] = '-') do
  1649.       {If extra Lines}
  1650.   begin
  1651.     Replymess := Readln; {Handle Extra Lines}
  1652.     StatusMessage(Status_Informational, Replymess); {Show Received Lines}
  1653.   end; {_ while (Replymess[1] = ' ') or (Replymess[4] = '-') do _}
  1654. end; {_ procedure TNMFTP.ReadExtraLines; _}
  1655. {*******************************************************************************************
  1656. List Files in Current Directory in Remote Server
  1657. ********************************************************************************************}
  1658. procedure TNMFTP.Nlist;
  1659. var
  1660.   Replymess: string;
  1661.   Done: Boolean;
  1662.   Sck1: integer;
  1663. begin {Stop Asynchronous Processing}
  1664.   Done := False;
  1665.   BeenCanceled := False; {Reset Cancelled flag}
  1666.   CertifyConnect;
  1667.   if Connected then
  1668.       {If connected}
  1669.   begin
  1670.     DataSocket := TPowersock.Create(self); {Create a Data socket}
  1671.     DataSocket.TimeOut := TimeOut;
  1672.     try
  1673.       if DataAvailable then Read(0);
  1674.       DataSocket.TimeOut := TimeOut;
  1675.       DataSocket.Port := 0; {Set Port to Zero}
  1676.       DataSocket.Listen(True); {Listen in the datasocket}
  1677.       StatusMessage(Status_Informational, Cont_Port + GetLocalAddress + DataSocket.GetPortString); {Show Outgoing Message}
  1678.       Replymess := Transaction(Cont_Port + GetLocalAddress + DataSocket.GetPortString); {Send Port for data socket}
  1679.       if (ReplyNumber > 300) and (ReplyNumber < 600)
  1680.         then raise FTPException.Create(Replymess);
  1681.          {Raise exception on errors}
  1682.       StatusMessage(Status_Informational, Cont_Nlst); {Show Outgoing Message}
  1683.       if FListMask = '' then Replymess := Transaction(Cont_Nlst)
  1684.       else Replymess := Transaction(Cont_Nlst + ' ' + FListMask); {Send List command}
  1685.       if (ReplyNumber > 300) and (ReplyNumber < 600)
  1686.         then raise FTPException.Create(Replymess);
  1687.          {Raise exception on errors}
  1688.       FBytesTotal := GetBytesTotal(Replymess);
  1689.       Sck1 := DataSocket.ThisSocket;
  1690.       DataSocket.ThisSocket := DataSocket.Accept; {Accept the datasocket}
  1691.       WinSock.CloseSocket(Sck1); {Accept the datasocket}
  1692.       if Assigned(FTransactionStart) then FTransactionStart(self);
  1693.       while not (BeenCanceled or BeenTimedOut or DataSocket.DataAvailable) do
  1694.         DataSocket.wait;
  1695.       if not (BeenCanceled or BeenTimedOut) then
  1696.         repeat
  1697.           if DataSocket.DataAvailable then
  1698.           begin
  1699.             Replymess := DataSocket.Readln;
  1700.             if Length(Replymess) > 2 then
  1701.               if Replymess[Length(Replymess) - 1] = #13 then
  1702.                 SetLength(Replymess, Length(Replymess) - 2)
  1703.               else {_ NOT if Replymess[Length(Replymess) - 1] = #13 then _}  SetLength(Replymess, Length(Replymess) - 1);
  1704.             if Assigned(FOnListItem) then FOnListItem(Replymess);
  1705.           end {_ if  DataAvailable > 0 then read (0); _}
  1706.           else {_ NOT if DataAvailable > 0 then read (0); _}
  1707.             DataSocket.wait; //Application.ProcessMessages;
  1708.         until (((not DataSocket.Connected) or DataAvailable) and (not DataSocket.DataAvailable)) or BeenTimedOut or BeenCanceled; {Capture incoming data}
  1709.          {Capture incoming data}
  1710.       if Assigned(FTransactionStop) then FTransactionStop(self);
  1711.       DataSocket.RequestCloseSocket;
  1712.       FBytesTotal := DataSocket.BytesRecvd;
  1713.       StatusMessage(Status_Informational, (sFTP_Msg_Recvd + IntToStr(BytesTotal) + sFTP_No_Bytes));
  1714.       if not (BeenCanceled or BeenTimedOut) then Replymess := Read(0);
  1715.       if Replymess = '' then Replymess := '226 Data Transfer successful';
  1716.       StatusMessage(Status_Informational, Replymess);
  1717.       if not (BeenCanceled or BeenTimedOut) then ReadExtraLines(Replymess); {Read Extra Lines}
  1718.       Done := True;
  1719.     finally
  1720.       DataSocket.Destroy; {Destroy datasocket}
  1721.       DataSocket := nil;
  1722.       if Done then if Assigned(FOnSuccess) then FOnSuccess(cmdNList);
  1723.       if BeenCanceled then Flush;
  1724.     end; {_ try _}
  1725.   end; {_ if Connected then _}
  1726. end; {_ procedure TNMFTP.Nlist; _}
  1727. procedure TNMFTP.Reinitialize;
  1728. begin
  1729.   DoCommand(Cont_Rein);
  1730. end; {_ procedure TNMFTP.Reinitialize; _}
  1731. procedure TNMFTP.Allocate(FileSize: integer);
  1732. begin
  1733.   DoCommand(Cont_Allo + IntToStr(FileSize));
  1734. end; {_ procedure TNMFTP.Allocate(FileSize: Integer); _}
  1735. procedure TNMFTP.CheckRead(Sender: TObject);
  1736. begin
  1737.   (*if DataAvailable  then
  1738.   begin
  1739.     { AStr := TMemoryStream(FIstream).Memory;
  1740.      if Astr[0] ='4' then
  1741.         if AStr[1] = '2' then
  1742.            if (AStr[2] ='1') or (AStr[2] ='6') then
  1743.                Cancel;    }
  1744.   end;  *)
  1745. end;
  1746. procedure TNMFTP.Flush;
  1747. var STime: TDateTime;
  1748. var Replymess: string;
  1749. begin
  1750.   BeenCanceled := False;
  1751.   STime := Now;
  1752.   repeat
  1753.     Replymess := Read(0);
  1754.     Application.ProcessMessages;
  1755.   until (Replymess <> '') or (Now - STime > 1.1E-5);
  1756.   StatusMessage(Status_Informational, Replymess);
  1757. end; {_ procedure TNMFTP.Flush; _}
  1758. end.