home *** CD-ROM | disk | FTP | other *** search
/ Delphi 2 - Developers' Solutions / Delphi 2 Developers' Solutions.iso / dds / chap11 / howto05 / delphi10 / ccftp.pas next >
Encoding:
Pascal/Delphi Source File  |  1996-06-12  |  69.9 KB  |  2,038 lines

  1. unit Ccftp;
  2.  
  3. interface
  4.  
  5. uses
  6.   SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
  7.   Forms, Dialogs, ExtCtrls, StdCtrls, Buttons, Menus, FileCtrl, CCWSock;
  8.  
  9. type
  10.   { This record holds the information for a number of internet connections }
  11.   PConnectionsRecord = ^TConnectionsRecord;
  12.   TConnectionsRecord = record
  13.     CProfile   : String; { Connection profile; used in lists }
  14.     CIPAddress : String; { Dotted character IP Address       }
  15.     CUserName  : String; { Login name to site; can be anonym }
  16.     CPassword  : String; { Password; won't be shown          }
  17.     CStartDir  : String; { Starting directory; used for FTP  }
  18.   end;
  19.   { Array of TCR }
  20.   CRFile = file of TConnectionsRecord; { File type for TCRec }
  21.   { Component to hold FTP handling capabilities }
  22.   TFTPComponent = class( TWinControl )
  23.   public
  24.     FTPCommandInProgress ,
  25.     Connection_Established : Boolean;
  26.     Socket1 : TCCSocket;
  27.     Socket2 : TCCSocket;
  28.     constructor Create( AOwner : TComponent ); override;
  29.     destructor Destroy; override;
  30.     function GetTotalBytesToReceive( TheString : String ) : Longint;
  31.     function StripBrackets( TheString : String ) : String;
  32.     function GetShortPathname( TheString : String ) : String;
  33.     function GetWin16FileName( InputName : String ) : String;
  34.     function GetRemoteWorkingDirectory( var RemoteDir : String ) : Boolean;
  35.     function SetRemoteDirectory( TheDir : String ) : Boolean;
  36.     function DeleteRemoteDirectory( TheDir : String ) : Boolean;
  37.     function CreateRemoteDirectory( TheDir : String ) : Boolean;
  38.     function DeleteRemoteFile( TheFileName : String ) : Boolean;
  39.     function EstablishConnection( PCRPointer : PConnectionsRecord ) : Boolean;
  40.     function LoginUser( PCRPointer : PConnectionsRecord ) : Boolean;
  41.     function SendPassword( PCRPointer : PConnectionsRecord ) : Boolean;
  42.     function SetRemoteStartupDirectory( PCRPointer : PConnectionsRecord )
  43.               : Boolean;
  44.     function GetRemoteDirectoryListing( TheListBox : TListBox ) : Boolean;
  45.     function GetRemoteDirectoryListingToMemo : Boolean;
  46.     procedure SendASCIILocalFile( LocalName : String );
  47.     procedure SendBinaryLocalFile( LocalName : String );
  48.     procedure ReceiveASCIIRemoteFile( RemoteName , LocalName : String );
  49.     procedure ReceiveBinaryRemoteFile( RemoteName , LocalName : String );
  50.     function GetLocalDirectoryAndListing( var TheString : String;
  51.                                               TheListBox : TListBox )
  52.               : Boolean;
  53.     function GetUNIXTextString( var StringIn : String ) : String;
  54.     procedure ReceiveASCIIRemoteFileToMemo( RemoteName : String );
  55.     function GetListeningPort : Integer;
  56.     procedure GetFileNameFromUNIXFileName( var TheName : String );
  57.     function Disconnect : Boolean;
  58.     function DoCStyleFormat(       TheText      : string;
  59.                              const TheArguments : array of const ) : String;
  60.     procedure UpdateGauge( BytesFinished , TotalToHandle : longint );
  61.     function GetQuotedString( TheString : String ) : String;
  62.     procedure AddProgressText( WhatText : String );
  63.     procedure ShowProgressText( WhatText : String );
  64.     procedure ShowProgressErrorText( WhatText : String );
  65.     function GetFTPServerResponse( var ResponseString : String ) : integer;
  66.     procedure FTPSocketsErrorOccurred( Sender     : TObject;
  67.                                      ErrorCode  : Integer;
  68.                                      TheMessage : String   );
  69.     function PerformFTPCommand(
  70.                     TheCommand   : string;
  71.               const TheArguments : array of const ) : Integer;
  72.   end;
  73.  
  74. const
  75.   POV_MEMO                 = 1; { Progress to the Memo           }
  76.   POV_STAT                 = 2; { Progress to the status caption }
  77.   TCPIP_STATUS_PRELIMINARY   = 1; { Wait; command being processed  }
  78.   TCPIP_STATUS_COMPLETED     = 2; { Done; command fully succeded   }
  79.   TCPIP_STATUS_CONTINUING    = 3; { OK; send more data to finish   }
  80.   TCPIP_STATUS_RETRY_COMMAND = 4; { Temporary Error; try cmd again }
  81.   TCPIP_STATUS_FATAL_ERROR   = 5; { Fatal Error; don't retry cmd   }
  82.  
  83. var
  84.   GlobalErrorCode      : Integer;        { Used to pass around error info  }
  85.   GlobalAbortedFlag    : Boolean;        { Used to signal timeout error    }
  86.  
  87. implementation
  88.  
  89. uses CCICCFRM;
  90.  
  91. { This is the FTP component constructor; it creates 2 sockets }
  92. constructor TFTPComponent.Create( AOwner : TComponent );
  93. begin
  94.   { do inherited create }
  95.   inherited Create( AOwner );
  96.   { Create sockets, put in their parents, and error procs }
  97.   Socket1 := TCCSocket.Create( Self );
  98.   Socket1.Parent := Self;
  99.   Socket1.OnErrorOccurred := FTPSocketsErrorOccurred;
  100.   Socket2 := TCCSocket.Create( Self );
  101.   Socket2.Parent := Self;
  102.   Socket2.OnErrorOccurred := FTPSocketsErrorOccurred;
  103.   { Set up booleans }
  104.   Connection_Established := false;
  105.   FTPCommandInProgress := false;
  106. end;
  107.  
  108. { This is the FTP component destructor; it frees 2 sockets }
  109. destructor TFTPComponent.Destroy;
  110. begin
  111.   { Free the sockets }
  112.   Socket1.Free;
  113.   Socket2.Free;
  114.   { and call inherited }
  115.   inherited Destroy;
  116. end;
  117.  
  118. function TFTPComponent.GetShortPathname( TheString : String ) : String;
  119. var HoldingString : String;
  120. begin
  121.   HoldingString := Copy( TheString , 1 , 3 );
  122.   HoldingString := HoldingString + '..\' + ExtractFileName( TheString );
  123.   Result := HoldingString;
  124. end;
  125.  
  126. function TFTPComponent.StripBrackets( TheString : String ) : String;
  127. var HoldingString : String;
  128.     HoldingPosition : Integer;
  129. begin
  130.   HoldingPosition := Pos( '[' , TheString );
  131.   if HoldingPosition = 0 then
  132.   begin
  133.     Result := TheString;
  134.     exit;
  135.   end
  136.   else
  137.   begin
  138.     HoldingString := Copy( TheString , HoldingPosition + 1 , 255 );
  139.     HoldingPosition := Pos( ']' , HoldingString );
  140.     if HoldingPosition = 0 then
  141.     begin
  142.       Result := HoldingString;
  143.       exit;
  144.     end
  145.     else
  146.     begin
  147.       HoldingString := Copy( HoldingString , 1 , HoldingPosition - 1 );
  148.       Result := HoldingString;
  149.       exit;
  150.     end;
  151.   end;
  152. end;
  153.  
  154. { This function takes a UNIX filespec and turns it into a Win16 filename }
  155. function TFTPComponent.GetWin16FileName( InputName : String ) : String;
  156. var WorkingString ,
  157.     HoldingString   : String; { Holding string }
  158. begin
  159.   WorkingString := ExtractFileExt( InputName );
  160.   if WorkingString = '' then
  161.   begin
  162.     if Length( InputName ) > 8 then
  163.      WorkingString := Copy( InputName , 1 , 8 ) else
  164.       WorkingString := InputName;
  165.   end
  166.   else
  167.   begin
  168.     if Length( WorkingString ) > 4 then
  169.      WorkingString := Copy( WorkingString , 1 , 4 );
  170.     HoldingString :=
  171.      Copy( InputName , 1 , Pos( WorkingString , InputName ) - 1 );
  172.     if Length( HoldingString ) > 8 then
  173.      HoldingString := Copy( HoldingString , 1 , 8 );
  174.     if HoldingString = '' then
  175.     begin
  176.       { Dot file }
  177.       HoldingString := Copy( InputName , 2 , 255 ) + '.TXT';
  178.       WorkingString := HoldingString;
  179.     end
  180.     else WorkingString := HoldingString + WorkingString;
  181.   end;
  182.   Result := WorkingString;
  183. end;
  184.  
  185. { This sends a local file in binary mode to the remote server }
  186. procedure TFTPComponent.SendBinaryLocalFile( LocalName : String );
  187. var TheReturnString : String;  { Internal string holder }
  188.     TheResult       : Integer; { Internal int holder    }
  189.     Through         : Boolean;
  190.     FileNamePChar   : array[ 0 .. 255 ] of char;
  191.     OutputFileHandle : Integer;
  192.     TotalBytesSent ,
  193.     BytesRead ,
  194.     FileToSendSize    : Longint;
  195.     CopyBuffer       : array[ 0 .. 255 ] of char absolute TheReturnString;
  196. begin
  197.   LocalName := ExpandFileName( LocalName );
  198.   StrPCopy( FileNamePChar , LocalName );
  199.   OutputFileHandle := _lopen( FileNamePChar , 0 );
  200.   if OutputFileHandle = -1 then
  201.   begin
  202.     MessageDlg( 'Cannot Open local file ' + LocalName ,
  203.      mtError , [mbOK] , 0 );
  204.     exit;
  205.   end;
  206.   FileToSendSize := _llseek( OutputFileHandle , 0 , 2 );
  207.   _llseek( OutputFileHandle , 0 , 0 );
  208.   TheReturnString :=
  209.    DoCStyleFormat( 'TYPE I' ,
  210.     [ nil ] );
  211.   { Put result in progress and status line }
  212.   AddProgressText( TheReturnString );
  213.   ShowProgressText( TheReturnString );
  214.   { Send Password sequence }
  215.   TheResult := PerformFTPCommand( 'TYPE I',
  216.                                   [ nil ] );
  217.   if TheResult <> TCPIP_STATUS_PRELIMINARY then
  218.   begin
  219.     FTPCommandInProgress := false;
  220.     exit;
  221.   end;
  222.   repeat
  223.     TheResult := GetFTPServerResponse( TheReturnString );
  224.     { Put result in progress and status line }
  225.     AddProgressText( TheReturnString );
  226.     ShowProgressText( TheReturnString );
  227.   until (( GlobalAbortedFlag ) or ( TheResult <> TCPIP_STATUS_PRELIMINARY ));
  228.   FTPCommandInProgress := false;
  229.   if ( GlobalAbortedFlag or ( TheResult <> TCPIP_STATUS_COMPLETED )) then
  230.   begin
  231.     { Do clever C formatting trick }
  232.     TheReturnString :=
  233.      DoCStyleFormat( 'FTP File Send Failed!' ,
  234.       [ nil ] );
  235.     { Put result in progress and status line }
  236.     AddProgressText( TheReturnString );
  237.     ShowProgressErrorText( TheReturnString );
  238.     { leave }
  239.     exit;
  240.   end
  241.   else
  242.   begin
  243.     { Set up socket 2 for listening }
  244.     Socket2.AsynchMode := False;
  245.     Socket2.NonAsynchTimeoutValue := 60;
  246.     { do a listen and send command to server that this is receipt socket }
  247.     if GetListeningPort = TCPIP_STATUS_FATAL_ERROR then
  248.     begin
  249.       Socket2.CCSockCancelListen;
  250.       exit;
  251.     end;
  252.     Socket1.NonAsynchTimeoutValue := 0; {infinite timeout}
  253.     TheReturnString :=
  254.      DoCStyleFormat( 'STOR %s' ,
  255.       [ ExtractFileName( LocalName ) ] );
  256.     { Put result in progress and status line }
  257.     AddProgressText( TheReturnString );
  258.     ShowProgressText( TheReturnString );
  259.     TheResult := PerformFTPCommand( 'STOR %s' , [ ExtractFileName( LocalName ) ] );
  260.     GetFTPServerResponse( TheReturnString );
  261.     AddProgressText( TheReturnString );
  262.     ShowProgressText( TheReturnString );
  263.     Socket1.NonAsynchTimeoutValue := 30;
  264.     if (( TheResult = TCPIP_STATUS_RETRY_COMMAND ) or
  265.        ( TheResult = TCPIP_STATUS_FATAL_ERROR )) then
  266.     begin
  267.       TheReturnString :=
  268.        DoCStyleFormat( 'Could not create remote file!' ,
  269.         [ nil ] );
  270.       { Put result in progress and status line }
  271.       AddProgressText( TheReturnString );
  272.       ShowProgressErrorText( TheReturnString );
  273.       Socket2.CCSockCancelListen;
  274.       exit;
  275.     end;
  276.     Socket2.CCSockAccept;
  277.     if (( GlobalAbortedFlag ) or ( GlobalErrorCode <> 0 )) then
  278.     begin
  279.       TheReturnString :=
  280.        DoCStyleFormat( 'Could not establish send socket!' ,
  281.         [ nil ] );
  282.       { Put result in progress and status line }
  283.       AddProgressText( TheReturnString );
  284.       ShowProgressErrorText( TheReturnString );
  285.       exit;
  286.     end;
  287.     Through := false;
  288.     TotalBytesSent := 0;
  289.     BytesRead := _lread( OutputFileHandle , @CopyBuffer[ 1 ] , 255 );
  290.     repeat
  291.       if BytesRead = 0 then Through := true;
  292.       if BytesRead > 0 then
  293.       begin
  294.         CopyBuffer[ 0 ] := Chr( BytesRead );
  295.         Socket2.StringData := TheReturnString;
  296.         TotalBytesSent := TotalBytesSent + BytesRead;
  297.         UpdateGauge( TotalBytesSent , FileToSendSize );
  298.         BytesRead := _lread( OutputFileHandle , @CopyBuffer[ 1 ] , 255 );
  299.         if BytesRead = -1 then
  300.         begin
  301.           MessageDlg( 'File Read Error on ' + LocalName , mtError , [mbOK] , 0 );
  302.           GlobalAbortedFlag := True;
  303.         end;
  304.       end;
  305.       if GlobalAbortedFlag then
  306.       begin
  307.         Socket1.OutOfBand := 'ABOR'+#13#10;
  308.         repeat
  309.           TheResult := GetFTPServerResponse( TheReturnString );
  310.           { Put result in progress and status line }
  311.           AddProgressText( TheReturnString );
  312.           ShowProgressText( TheReturnString );
  313.         until (( GlobalAbortedFlag ) or ( TheResult <> TCPIP_STATUS_PRELIMINARY ));
  314.         exit;
  315.       end;
  316.     until Through;
  317.     FTPCommandInProgress := false;
  318.     { cancel listening on second socket and close it }
  319.     Socket2.CCSockCancelListen;
  320.     Socket2.CCSockClose;
  321.     TheReturnString := 'Transfer Succeeded' + #13#10;
  322.     AddProgressText( TheReturnString );
  323.     ShowProgressText( TheReturnString );
  324.     FTPCommandInProgress := false;
  325.     PerformFTPCommand( 'TYPE A',
  326.                                     [ nil ] );
  327.     Through := false;
  328.     repeat
  329.       GetFTPServerResponse( TheReturnString );
  330.       if Pos( 'TYPE' , Uppercase( TheReturnString )) > 0 then
  331.        Through := true;
  332.       { Put result in progress and status line }
  333.       AddProgressText( TheReturnString );
  334.       ShowProgressText( TheReturnString );
  335.     until (( GlobalAbortedFlag ) or Through );
  336.   end;
  337.   _lclose( OutputFileHandle );
  338.   FTPCommandInProgress := false;
  339. end;
  340.  
  341. { This sends a local file in ascii mode to remote server }
  342. procedure TFTPComponent.SendASCIILocalFile( LocalName : String );
  343. var TheReturnString : String;  { Internal string holder }
  344.     TheResult       : Integer; { Internal int holder    }
  345.     Through         : Boolean;
  346.     FileNamePChar   : array[ 0 .. 255 ] of char;
  347.     OutputFileHandle : Integer;
  348.     TotalBytesSent ,
  349.     BytesRead ,
  350.     FileToSendSize    : Longint;
  351.     CopyBuffer       : array[ 0 .. 255 ] of char absolute TheReturnString;
  352. begin
  353.   LocalName := ExpandFileName( LocalName );
  354.   StrPCopy( FileNamePChar , LocalName );
  355.   OutputFileHandle := _lopen( FileNamePChar , 0 );
  356.   if OutputFileHandle = -1 then
  357.   begin
  358.     MessageDlg( 'Cannot Open local file ' + LocalName ,
  359.      mtError , [mbOK] , 0 );
  360.     exit;
  361.   end;
  362.   FileToSendSize := _llseek( OutputFileHandle , 0 , 2 );
  363.   _llseek( OutputFileHandle , 0 , 0 );
  364.   TheReturnString :=
  365.    DoCStyleFormat( 'TYPE A' ,
  366.     [ nil ] );
  367.   { Put result in progress and status line }
  368.   AddProgressText( TheReturnString );
  369.   ShowProgressText( TheReturnString );
  370.   { Send Password sequence }
  371.   TheResult := PerformFTPCommand( 'TYPE A',
  372.                                   [ nil ] );
  373.   if TheResult <> TCPIP_STATUS_PRELIMINARY then
  374.   begin
  375.     FTPCommandInProgress := false;
  376.     exit;
  377.   end;
  378.   repeat
  379.     TheResult := GetFTPServerResponse( TheReturnString );
  380.     { Put result in progress and status line }
  381.     AddProgressText( TheReturnString );
  382.     ShowProgressText( TheReturnString );
  383.   until (( GlobalAbortedFlag ) or ( TheResult <> TCPIP_STATUS_PRELIMINARY ));
  384.   FTPCommandInProgress := false;
  385.   if ( GlobalAbortedFlag or ( TheResult <> TCPIP_STATUS_COMPLETED )) then
  386.   begin
  387.     { Do clever C formatting trick }
  388.     TheReturnString :=
  389.      DoCStyleFormat( 'FTP File Send Failed!' ,
  390.       [ nil ] );
  391.     { Put result in progress and status line }
  392.     AddProgressText( TheReturnString );
  393.     ShowProgressErrorText( TheReturnString );
  394.     { leave }
  395.     exit;
  396.   end
  397.   else
  398.   begin
  399.     { Set up socket 2 for listening }
  400.     Socket2.AsynchMode := False;
  401.     Socket2.NonAsynchTimeoutValue := 60;
  402.     { do a listen and send command to server that this is receipt socket }
  403.     if GetListeningPort = TCPIP_STATUS_FATAL_ERROR then
  404.     begin
  405.       Socket2.CCSockCancelListen;
  406.       exit;
  407.     end;
  408.     Socket1.NonAsynchTimeoutValue := 0; {infinite timeout}
  409.     TheReturnString :=
  410.      DoCStyleFormat( 'STOR %s' ,
  411.       [ ExtractFileName( LocalName ) ] );
  412.     { Put result in progress and status line }
  413.     AddProgressText( TheReturnString );
  414.     ShowProgressText( TheReturnString );
  415.     TheResult := PerformFTPCommand( 'STOR %s' , [ ExtractFileName( LocalName )]);
  416.     GetFTPServerResponse( TheReturnString );
  417.     AddProgressText( TheReturnString );
  418.     ShowProgressText( TheReturnString );
  419.     Socket1.NonAsynchTimeoutValue := 30;
  420.     if (( TheResult = TCPIP_STATUS_RETRY_COMMAND ) or
  421.        ( TheResult = TCPIP_STATUS_FATAL_ERROR )) then
  422.     begin
  423.       TheReturnString :=
  424.        DoCStyleFormat( 'Could not create remote file!' ,
  425.         [ nil ] );
  426.       { Put result in progress and status line }
  427.       AddProgressText( TheReturnString );
  428.       ShowProgressErrorText( TheReturnString );
  429.       Socket2.CCSockCancelListen;
  430.       exit;
  431.     end;
  432.     Socket2.CCSockAccept;
  433.     if (( GlobalAbortedFlag ) or ( GlobalErrorCode <> 0 )) then
  434.     begin
  435.       TheReturnString :=
  436.        DoCStyleFormat( 'Could not establish send socket!' ,
  437.         [ nil ] );
  438.       { Put result in progress and status line }
  439.       AddProgressText( TheReturnString );
  440.       ShowProgressErrorText( TheReturnString );
  441.       exit;
  442.     end;
  443.     Through := false;
  444.     TotalBytesSent := 0;
  445.     BytesRead := _lread( OutputFileHandle , @CopyBuffer[ 1 ] , 255 );
  446.     repeat
  447.       if BytesRead = 0 then Through := true;
  448.       if BytesRead > 0 then
  449.       begin
  450.         CopyBuffer[ 0 ] := Chr( BytesRead );
  451.         Socket2.StringData := TheReturnString;
  452.         TotalBytesSent := TotalBytesSent + BytesRead;
  453.         UpdateGauge( TotalBytesSent , FileToSendSize );
  454.         BytesRead := _lread( OutputFileHandle , @CopyBuffer[ 1 ] , 255 );
  455.         if BytesRead = -1 then
  456.         begin
  457.           MessageDlg( 'File Read Error on ' + LocalName , mtError , [mbOK] , 0 );
  458.           GlobalAbortedFlag := True;
  459.         end;
  460.       end;
  461.       if GlobalAbortedFlag then
  462.       begin
  463.         Socket1.OutOfBand := 'ABOR'+#13#10;
  464.         repeat
  465.           TheResult := GetFTPServerResponse( TheReturnString );
  466.           { Put result in progress and status line }
  467.           AddProgressText( TheReturnString );
  468.           ShowProgressText( TheReturnString );
  469.         until (( GlobalAbortedFlag ) or ( TheResult <> TCPIP_STATUS_PRELIMINARY ));
  470.         exit;
  471.       end;
  472.     until Through;
  473.     { cancel listening on second socket and close it }
  474.     Socket2.CCSockCancelListen;
  475.     Socket2.CCSockClose;
  476.     TheReturnString := 'Transfer Succeeded' + #13#10;
  477.     AddProgressText( TheReturnString );
  478.     ShowProgressText( TheReturnString );
  479.     FTPCommandInProgress := false;
  480.     PerformFTPCommand( 'TYPE A', [ nil ] );
  481.     Through := false;
  482.     repeat
  483.       GetFTPServerResponse( TheReturnString );
  484.       if Pos( 'TYPE' , Uppercase( TheReturnString )) > 0 then
  485.        Through := true;
  486.       { Put result in progress and status line }
  487.       AddProgressText( TheReturnString );
  488.       ShowProgressText( TheReturnString );
  489.     until (( GlobalAbortedFlag ) or Through );
  490.   end;
  491.   _lclose( OutputFileHandle );
  492.   FTPCommandInProgress := false;
  493. end;
  494.  
  495. { This function strips out the FTP response for bytes to send }
  496. function TFTPComponent.GetTotalBytesToReceive( TheString : String ) : Longint;
  497. var
  498.   LeftPosition ,
  499.   RightPosition  : integer;
  500.   TempString     : string;
  501. begin
  502.   LeftPosition := Pos( '(' , TheString );
  503.   TempString := Copy( TheString ,
  504.                       LeftPosition + 1 , 255 );
  505.   RightPosition := Pos( ' ' , TempString );
  506.   if (( LeftPosition = 0 ) or ( RightPosition = 0 )) then
  507.   begin
  508.     Result := 0;
  509.     exit;
  510.   end;
  511.   if RightPosition <> 0 then
  512.     TempString := Copy( TempString , 1 , RightPosition - 1  );
  513.   try
  514.     Result := StrToInt( TempString );
  515.   except
  516.     on EConvertError do Result := 0;
  517.   end;
  518. end;
  519.  
  520. procedure TFTPComponent.UpdateGauge( BytesFinished , TotalToHandle : longint );
  521. begin
  522.   CCInetCCForm.UpdateGauge( BytesFinished , TotalToHandle );
  523. end;
  524.  
  525. { This sends FTP progress text to the Inet form }
  526. procedure TFTPComponent.AddProgressText( WhatText : String );
  527. begin
  528.   CCInetCCForm.AddProgressText( WhatText );
  529. end;
  530.  
  531. { This sends FTP progress text to the Inet form }
  532. procedure TFTPComponent.ShowProgressText( WhatText : String );
  533. begin
  534.   CCInetCCForm.ShowProgressText( WhatText );
  535. end;
  536.  
  537. { This procedure receives a binary remote file }
  538. procedure TFTPComponent.ReceiveASCIIRemoteFileToMemo( RemoteName : String );
  539. var TheReturnString : String;  { Internal string holder }
  540.     TheResult       : Integer; { Internal int holder    }
  541.     Through         : Boolean;
  542.     TotalBytesSent ,
  543.     FileToGetSize    : Longint;
  544. begin
  545.   TheReturnString :=
  546.    DoCStyleFormat( 'TYPE A' ,
  547.     [ nil ] );
  548.   { Put result in progress and status line }
  549.   AddProgressText( TheReturnString );
  550.   ShowProgressText( TheReturnString );
  551.   { Send Password sequence }
  552.   FTPCommandInProgress := false;
  553.   TheResult := PerformFTPCommand( 'TYPE A',
  554.                                   [ nil ] );
  555.   if TheResult <> TCPIP_STATUS_PRELIMINARY then
  556.   begin
  557.     FTPCommandInProgress := false;
  558.     exit;
  559.   end;
  560.   repeat
  561.     TheResult := GetFTPServerResponse( TheReturnString );
  562.     { Put result in progress and status line }
  563.     AddProgressText( TheReturnString );
  564.     ShowProgressText( TheReturnString );
  565.   until (( GlobalAbortedFlag ) or ( TheResult <> TCPIP_STATUS_PRELIMINARY ));
  566.   FTPCommandInProgress := false;
  567.   if ( GlobalAbortedFlag or ( TheResult <> TCPIP_STATUS_COMPLETED )) then
  568.   begin
  569.     { Do clever C formatting trick }
  570.     TheReturnString :=
  571.      DoCStyleFormat( 'FTP File Receive Failed!' ,
  572.       [ nil ] );
  573.     { Put result in progress and status line }
  574.     AddProgressText( TheReturnString );
  575.     ShowProgressErrorText( TheReturnString );
  576.     { leave }
  577.     exit;
  578.   end
  579.   else
  580.   begin
  581.     { Set up socket 2 for listening }
  582.     Socket2.AsynchMode := False;
  583.     Socket2.NonAsynchTimeoutValue := 60;
  584.     { do a listen and send command to server that this is receipt socket }
  585.     if GetListeningPort = TCPIP_STATUS_FATAL_ERROR then
  586.     begin
  587.       Socket2.CCSockCancelListen;
  588.       exit;
  589.     end;
  590.     Socket1.NonAsynchTimeoutValue := 0; {infinite timeout}
  591.     TheReturnString :=
  592.      DoCStyleFormat( 'RETR %s' ,
  593.       [ RemoteName ] );
  594.     { Put result in progress and status line }
  595.     AddProgressText( TheReturnString );
  596.     ShowProgressText( TheReturnString );
  597.     TheResult := PerformFTPCommand( 'RETR %s' , [RemoteName] );
  598.     GetFTPServerResponse( TheReturnString );
  599.     AddProgressText( TheReturnString );
  600.     ShowProgressText( TheReturnString );
  601.     FileToGetSize := GetTotalBytesToReceive( TheReturnString );
  602.     Socket1.NonAsynchTimeoutValue := 30;
  603.     if (( TheResult = TCPIP_STATUS_RETRY_COMMAND ) or
  604.        ( TheResult = TCPIP_STATUS_FATAL_ERROR )) then
  605.     begin
  606.       TheReturnString :=
  607.        DoCStyleFormat( 'Could not obtain remote file!' ,
  608.         [ nil ] );
  609.       { Put result in progress and status line }
  610.       AddProgressText( TheReturnString );
  611.       ShowProgressErrorText( TheReturnString );
  612.       Socket2.CCSockCancelListen;
  613.       exit;
  614.     end;
  615.     Socket2.CCSockAccept;
  616.     if (( GlobalAbortedFlag ) or ( GlobalErrorCode <> 0 )) then
  617.     begin
  618.       TheReturnString :=
  619.        DoCStyleFormat( 'Could not establish receive socket!' ,
  620.         [ nil ] );
  621.       { Put result in progress and status line }
  622.       AddProgressText( TheReturnString );
  623.       ShowProgressErrorText( TheReturnString );
  624.       exit;
  625.     end;
  626.     Through := false;
  627.     TotalBytesSent := 0;
  628.     repeat
  629.       TheReturnString := Socket2.StringData;
  630.       if Length( TheReturnString ) = 0 then Through := true;
  631.       if Length( TheReturnString ) > 0 then
  632.       begin
  633.         TotalBytesSent := TotalBytesSent + Length( TheReturnString );
  634.         UpdateGauge( TotalBytesSent , FileToGetSize );
  635.         { Put result in progress and status line }
  636.         AddProgressText( TheReturnString );
  637.         ShowProgressText( TheReturnString );
  638.       end;
  639.       if GlobalAbortedFlag then
  640.       begin
  641.         Socket1.OutOfBand := 'ABOR'+#13#10;
  642.         repeat
  643.           TheResult := GetFTPServerResponse( TheReturnString );
  644.           { Put result in progress and status line }
  645.           AddProgressText( TheReturnString );
  646.           ShowProgressText( TheReturnString );
  647.         until (( GlobalAbortedFlag ) or ( TheResult <> TCPIP_STATUS_PRELIMINARY ));
  648.         exit;
  649.       end;
  650.     until Through;
  651.     { cancel listening on second socket and close it }
  652.     Socket2.CCSockCancelListen;
  653.     Socket2.CCSockClose;
  654.     FTPCommandInProgress := false;
  655.     PerformFTPCommand( 'TYPE A', [ nil ] );
  656.     Through := false;
  657.     repeat
  658.       GetFTPServerResponse( TheReturnString );
  659.       if Pos( 'TYPE' , Uppercase( TheReturnString )) > 0 then
  660.        Through := true;
  661.       { Put result in progress and status line }
  662.       AddProgressText( TheReturnString );
  663.       ShowProgressText( TheReturnString );
  664.     until (( GlobalAbortedFlag ) or Through );
  665.   end;
  666.   FTPCommandInProgress := false;
  667. end;
  668.  
  669. { This procedure receives a binary remote file }
  670. procedure TFTPComponent.ReceiveASCIIRemoteFile( RemoteName , LocalName : String );
  671. var TheReturnString : String;  { Internal string holder }
  672.     TheResult       : Integer; { Internal int holder    }
  673.     Through         : Boolean;
  674.     FileNamePChar   : array[ 0 .. 255 ] of char;
  675.     OutputFileHandle : Integer;
  676.     TotalBytesSent ,
  677.     FileToGetSize    : Longint;
  678.     CopyBuffer       : array[ 0 .. 255 ] of char;
  679. begin
  680.   LocalName := ExpandFileName( LocalName );
  681.   StrPCopy( FileNamePChar , LocalName );
  682.   OutputFileHandle := _lcreat( FileNamePChar , 0 );
  683.   if OutputFileHandle = -1 then
  684.   begin
  685.     MessageDlg( 'Cannot Create local file ' + LocalName ,
  686.      mtError , [mbOK] , 0 );
  687.     exit;
  688.   end;
  689.   TheReturnString :=
  690.    DoCStyleFormat( 'TYPE A' ,
  691.     [ nil ] );
  692.   { Put result in progress and status line }
  693.   AddProgressText( TheReturnString );
  694.   ShowProgressText( TheReturnString );
  695.   { Send Password sequence }
  696.   TheResult := PerformFTPCommand( 'TYPE A',
  697.                                   [ nil ] );
  698.   if TheResult <> TCPIP_STATUS_PRELIMINARY then
  699.   begin
  700.     FTPCommandInProgress := false;
  701.     exit;
  702.   end;
  703.   repeat
  704.     TheResult := GetFTPServerResponse( TheReturnString );
  705.     { Put result in progress and status line }
  706.     AddProgressText( TheReturnString );
  707.     ShowProgressText( TheReturnString );
  708.   until (( GlobalAbortedFlag ) or ( TheResult <> TCPIP_STATUS_PRELIMINARY ));
  709.   FTPCommandInProgress := false;
  710.   if ( GlobalAbortedFlag or ( TheResult <> TCPIP_STATUS_COMPLETED )) then
  711.   begin
  712.     { Do clever C formatting trick }
  713.     TheReturnString :=
  714.      DoCStyleFormat( 'FTP File Receive Failed!' ,
  715.       [ nil ] );
  716.     { Put result in progress and status line }
  717.     AddProgressText( TheReturnString );
  718.     ShowProgressErrorText( TheReturnString );
  719.     { leave }
  720.     exit;
  721.   end
  722.   else
  723.   begin
  724.     { Set up socket 2 for listening }
  725.     Socket2.AsynchMode := False;
  726.     Socket2.NonAsynchTimeoutValue := 60;
  727.     { do a listen and send command to server that this is receipt socket }
  728.     if GetListeningPort = TCPIP_STATUS_FATAL_ERROR then
  729.     begin
  730.       Socket2.CCSockCancelListen;
  731.       exit;
  732.     end;
  733.     Socket1.NonAsynchTimeoutValue := 0; {infinite timeout}
  734.     TheReturnString :=
  735.      DoCStyleFormat( 'RETR %s' ,
  736.       [ RemoteName ] );
  737.     { Put result in progress and status line }
  738.     AddProgressText( TheReturnString );
  739.     ShowProgressText( TheReturnString );
  740.     TheResult := PerformFTPCommand( 'RETR %s' , [RemoteName] );
  741.     GetFTPServerResponse( TheReturnString );
  742.     AddProgressText( TheReturnString );
  743.     ShowProgressText( TheReturnString );
  744.     FileToGetSize := GetTotalBytesToReceive( TheReturnString );
  745.     Socket1.NonAsynchTimeoutValue := 30;
  746.     if (( TheResult = TCPIP_STATUS_RETRY_COMMAND ) or
  747.        ( TheResult = TCPIP_STATUS_FATAL_ERROR )) then
  748.     begin
  749.       TheReturnString :=
  750.        DoCStyleFormat( 'Could not obtain remote file!' ,
  751.         [ nil ] );
  752.       { Put result in progress and status line }
  753.       AddProgressText( TheReturnString );
  754.       ShowProgressErrorText( TheReturnString );
  755.       Socket2.CCSockCancelListen;
  756.       exit;
  757.     end;
  758.     Socket2.CCSockAccept;
  759.     if (( GlobalAbortedFlag ) or ( GlobalErrorCode <> 0 )) then
  760.     begin
  761.       TheReturnString :=
  762.        DoCStyleFormat( 'Could not establish receive socket!' ,
  763.         [ nil ] );
  764.       { Put result in progress and status line }
  765.       AddProgressText( TheReturnString );
  766.       ShowProgressErrorText( TheReturnString );
  767.       exit;
  768.     end;
  769.     Through := false;
  770.     TotalBytesSent := 0;
  771.     repeat
  772.       TheReturnString := Socket2.StringData;
  773.       if Length( TheReturnString ) = 0 then Through := true;
  774.       if Length( TheReturnString ) > 0 then
  775.       begin
  776.         StrPCopy( CopyBuffer , TheReturnString );
  777.         TotalBytesSent := TotalBytesSent + Length( TheReturnString );
  778.         UpdateGauge( TotalBytesSent , FileToGetSize );
  779.         if _lwrite( OutputFileHandle , CopyBuffer , Length( TheReturnString ))
  780.          = -1 then
  781.         begin
  782.           MessageDlg( 'File Write Error on ' + LocalName , mtError , [mbOK] , 0 );
  783.           GlobalAbortedFlag := True;
  784.         end;
  785.       end;
  786.       if GlobalAbortedFlag then
  787.       begin
  788.         Socket1.OutOfBand := 'ABOR'+#13#10;
  789.         repeat
  790.           TheResult := GetFTPServerResponse( TheReturnString );
  791.           { Put result in progress and status line }
  792.           AddProgressText( TheReturnString );
  793.           ShowProgressText( TheReturnString );
  794.         until (( GlobalAbortedFlag ) or ( TheResult <> TCPIP_STATUS_PRELIMINARY ));
  795.         exit;
  796.       end;
  797.     until Through;
  798.     { cancel listening on second socket and close it }
  799.     Socket2.CCSockCancelListen;
  800.     Socket2.CCSockClose;
  801.     FTPCommandInProgress := false;
  802.     PerformFTPCommand( 'TYPE A', [ nil ] );
  803.     Through := false;
  804.     repeat
  805.       GetFTPServerResponse( TheReturnString );
  806.       if Pos( 'TYPE' , Uppercase( TheReturnString )) > 0 then
  807.        Through := true;
  808.       { Put result in progress and status line }
  809.       AddProgressText( TheReturnString );
  810.       ShowProgressText( TheReturnString );
  811.     until (( GlobalAbortedFlag ) or Through );
  812.   end;
  813.   _lclose( OutputFileHandle );
  814.   FTPCommandInProgress := false;
  815. end;
  816.  
  817. { This procedure receives a binary remote file }
  818. procedure TFTPComponent.ReceiveBinaryRemoteFile( RemoteName , LocalName : String );
  819. var TheReturnString : String;  { Internal string holder }
  820.     TheResult       : Integer; { Internal int holder    }
  821.     Through         : Boolean;
  822.     FileNamePChar   : array[ 0 .. 255 ] of char;
  823.     OutputFileHandle : Integer;
  824.     TotalBytesSent ,
  825.     FileToGetSize    : Longint;
  826.     CopyBuffer       : array[ 0 .. 255 ] of char;
  827. begin
  828.   LocalName := ExpandFileName( LocalName );
  829.   StrPCopy( FileNamePChar , LocalName );
  830.   OutputFileHandle := _lcreat( FileNamePChar , 0 );
  831.   if OutputFileHandle = -1 then
  832.   begin
  833.     MessageDlg( 'Cannot Create local file ' + LocalName ,
  834.      mtError , [mbOK] , 0 );
  835.     exit;
  836.   end;
  837.   TheReturnString :=
  838.    DoCStyleFormat( 'TYPE I' ,
  839.     [ nil ] );
  840.   { Put result in progress and status line }
  841.   AddProgressText( TheReturnString );
  842.   ShowProgressText( TheReturnString );
  843.   { Send Password sequence }
  844.   TheResult := PerformFTPCommand( 'TYPE I',
  845.                                   [ nil ] );
  846.   if TheResult <> TCPIP_STATUS_PRELIMINARY then
  847.   begin
  848.     FTPCommandInProgress := false;
  849.     exit;
  850.   end;
  851.   repeat
  852.     TheResult := GetFTPServerResponse( TheReturnString );
  853.     { Put result in progress and status line }
  854.     AddProgressText( TheReturnString );
  855.     ShowProgressText( TheReturnString );
  856.   until (( GlobalAbortedFlag ) or ( TheResult <> TCPIP_STATUS_PRELIMINARY ));
  857.   FTPCommandInProgress := false;
  858.   if ( GlobalAbortedFlag or ( TheResult <> TCPIP_STATUS_COMPLETED )) then
  859.   begin
  860.     { Do clever C formatting trick }
  861.     TheReturnString :=
  862.      DoCStyleFormat( 'FTP File Receive Failed!' ,
  863.       [ nil ] );
  864.     { Put result in progress and status line }
  865.     AddProgressText( TheReturnString );
  866.     ShowProgressErrorText( TheReturnString );
  867.     { leave }
  868.     exit;
  869.   end
  870.   else
  871.   begin
  872.     { Set up socket 2 for listening }
  873.     Socket2.AsynchMode := False;
  874.     Socket2.NonAsynchTimeoutValue := 60;
  875.     { do a listen and send command to server that this is receipt socket }
  876.     if GetListeningPort = TCPIP_STATUS_FATAL_ERROR then
  877.     begin
  878.       Socket2.CCSockCancelListen;
  879.       exit;
  880.     end;
  881.     Socket1.NonAsynchTimeoutValue := 0; {infinite timeout}
  882.     TheReturnString :=
  883.      DoCStyleFormat( 'RETR %s' ,
  884.       [ RemoteName ] );
  885.     { Put result in progress and status line }
  886.     AddProgressText( TheReturnString );
  887.     ShowProgressText( TheReturnString );
  888.     TheResult := PerformFTPCommand( 'RETR %s' , [RemoteName] );
  889.     GetFTPServerResponse( TheReturnString );
  890.     AddProgressText( TheReturnString );
  891.     ShowProgressText( TheReturnString );
  892.     FileToGetSize := GetTotalBytesToReceive( TheReturnString );
  893.     Socket1.NonAsynchTimeoutValue := 30;
  894.     if (( TheResult = TCPIP_STATUS_RETRY_COMMAND ) or
  895.        ( TheResult = TCPIP_STATUS_FATAL_ERROR )) then
  896.     begin
  897.       TheReturnString :=
  898.        DoCStyleFormat( 'Could not obtain remote file!' ,
  899.         [ nil ] );
  900.       { Put result in progress and status line }
  901.       AddProgressText( TheReturnString );
  902.       ShowProgressErrorText( TheReturnString );
  903.       Socket2.CCSockCancelListen;
  904.       exit;
  905.     end;
  906.     Socket2.CCSockAccept;
  907.     if (( GlobalAbortedFlag ) or ( GlobalErrorCode <> 0 )) then
  908.     begin
  909.       TheReturnString :=
  910.        DoCStyleFormat( 'Could not establish receive socket!' ,
  911.         [ nil ] );
  912.       { Put result in progress and status line }
  913.       AddProgressText( TheReturnString );
  914.       ShowProgressErrorText( TheReturnString );
  915.       exit;
  916.     end;
  917.     Through := false;
  918.     TotalBytesSent := 0;
  919.     repeat
  920.       TheReturnString := Socket2.StringData;
  921.       if Length( TheReturnString ) = 0 then Through := true;
  922.       if Length( TheReturnString ) > 0 then
  923.       begin
  924.         StrPCopy( CopyBuffer , TheReturnString );
  925.         TotalBytesSent := TotalBytesSent + Length( TheReturnString );
  926.         UpdateGauge( TotalBytesSent , FileToGetSize );
  927.         if _lwrite( OutputFileHandle , CopyBuffer , Length( TheReturnString ))
  928.          = -1 then
  929.         begin
  930.           MessageDlg( 'File Write Error on ' + LocalName , mtError , [mbOK] , 0 );
  931.           GlobalAbortedFlag := True;
  932.         end;
  933.       end;
  934.       if GlobalAbortedFlag then
  935.       begin
  936.         Socket1.OutOfBand := 'ABOR'+#13#10;
  937.         repeat
  938.           TheResult := GetFTPServerResponse( TheReturnString );
  939.           { Put result in progress and status line }
  940.           AddProgressText( TheReturnString );
  941.           ShowProgressText( TheReturnString );
  942.         until (( GlobalAbortedFlag ) or ( TheResult <> TCPIP_STATUS_PRELIMINARY ));
  943.         exit;
  944.       end;
  945.     until Through;
  946.     { cancel listening on second socket and close it }
  947.     Socket2.CCSockCancelListen;
  948.     Socket2.CCSockClose;
  949.     FTPCommandInProgress := false;
  950.     PerformFTPCommand( 'TYPE A', [ nil ] );
  951.     Through := false;
  952.     repeat
  953.       GetFTPServerResponse( TheReturnString );
  954.       if Pos( 'TYPE' , Uppercase( TheReturnString )) > 0 then
  955.        Through := true;
  956.       { Put result in progress and status line }
  957.       AddProgressText( TheReturnString );
  958.       ShowProgressText( TheReturnString );
  959.     until (( GlobalAbortedFlag ) or Through );
  960.   end;
  961.   _lclose( OutputFileHandle );
  962.   FTPCommandInProgress := false;
  963. end;
  964.  
  965. { This sends FTP progress text to the Inet form }
  966. procedure TFTPComponent.ShowProgressErrorText( WhatText : String );
  967. begin
  968.   CCInetCCForm.ShowProgressErrorText( WhatText );
  969. end;
  970.  
  971. { This is a core function! It performs an FTP command and if no timeout }
  972. { return a preliminary ok.                                              }
  973. function TFTPComponent.PerformFTPCommand(
  974.                  TheCommand        : string;
  975.            const TheArguments      : array of const ) : Integer;
  976. var TheBuffer : string; { Text buffer }
  977. begin
  978.   { If command in progress send back -1 error }
  979.   if FTPCommandInProgress then
  980.   begin
  981.     Result := -1;
  982.     exit;
  983.   end;
  984.   { Set status variable }
  985.   FTPCommandInProgress := True;
  986.   { Set global error code }
  987.   GlobalErrorCode := 0;
  988.   { Format output string }
  989.   TheBuffer := Format( TheCommand , TheArguments );
  990.   { Preset failure code }
  991.   Result := TCPIP_STATUS_FATAL_ERROR;
  992.   { If invalid socket or no connection abort }
  993.   if ( Socket1.TheSocket = INVALID_SOCKET ) or not Connection_Established then
  994.    exit;
  995.   { Send the buffer plus EOL chars }
  996.   Socket1.StringData := TheBuffer + #13#10;
  997.   { if abort due to timeout or other error exit }
  998.   if (( GlobalAbortedFlag ) or ( GlobalErrorCode <> 0 )) then exit;
  999.   { Otherwise return preliminary code }
  1000.   Result := TCPIP_STATUS_PRELIMINARY;
  1001. end;
  1002.  
  1003. { This function gets up to 255 chars of data plus a return code from FTP serv }
  1004. function TFTPComponent.GetFTPServerResponse(
  1005.           var ResponseString : String ) : integer;
  1006. var
  1007.   { Buffer string for response line }
  1008.   TheBuffer     : string;
  1009.   { Pointer to the response string }
  1010.   BufferPointer : array[0..255] of char absolute TheBuffer;
  1011.   { Character to check for response code }
  1012.   ResponseChar   : char;
  1013.   { Pointers into returned string }
  1014.   TheIndex ,
  1015.   TheLength     : integer;
  1016.   { Control variable }
  1017.   LeftoversInPan ,
  1018.   Finished      : Boolean;
  1019. begin
  1020.   { Preset fatal error }
  1021.   Result := TCPIP_STATUS_FATAL_ERROR;
  1022.   { Start loop control }
  1023.   LeftoversInPan := false;
  1024.   Finished := false;
  1025.   repeat
  1026.     { Do a peek }
  1027.     TheBuffer := Socket1.PeekData;
  1028.     { If timeout or other error exit }
  1029.     if (( GlobalAbortedFlag ) or ( GlobalErrorCode <> 0 )) then exit;
  1030.     { Find end of line character }
  1031.     TheIndex := Pos( #10 , TheBuffer );
  1032.     if TheIndex = 0 then
  1033.     begin
  1034.       TheIndex := Pos( #13 , TheBuffer );
  1035.       if TheIndex = 0 then
  1036.       begin
  1037.         TheIndex := Pos( #0 , TheBuffer );
  1038.         if TheIndex = 0 then
  1039.         begin
  1040.           TheIndex := Length( TheBuffer );
  1041.           LeftoversInPan := True;
  1042.           LeftoverText := LeftoverText + TheBuffer;
  1043.           LeftoversOnTable := false;
  1044.         end;
  1045.       end;
  1046.     end;
  1047.     { If an end of line then process the line }
  1048.     if TheIndex > 0 then
  1049.     begin
  1050.       { Get length of string }
  1051.       TheLength := TheIndex;
  1052.       { Receive actual data }
  1053.       Socket1.CCSockReceive( Socket1.TheSocket   ,
  1054.                              @BufferPointer[ 1 ] ,
  1055.                              TheLength              );
  1056.       { Abort if timeout or error }
  1057.       if (( GlobalAbortedFlag ) or ( GlobalErrorCode <> 0 )) then exit;
  1058.       { Put in the length byte }
  1059.       BufferPointer[ 0 ] := Chr( TheLength );
  1060.       if LeftOversOnTable then
  1061.       begin
  1062.         LeftOversOnTable := false;
  1063.         ResponseString := LeftoverText + TheBuffer;
  1064.         TheBuffer := ResponseString;
  1065.         LeftoverText := '';
  1066.       end;
  1067.       if LeftoversInPan then
  1068.       begin
  1069.         LeftoversInPan := false;
  1070.         LeftoversOnTable := true;
  1071.       end;
  1072.       { If not a continuation line }
  1073.       if TheBuffer[ 4 ] <> '-' then
  1074.       begin
  1075.         { Get first number character }
  1076.         ResponseChar := TheBuffer[ 1 ];
  1077.         { Get the value of the number from 1 to 5 }
  1078.         if (( ResponseChar >= '1' ) and ( ResponseChar <= '5' )) then
  1079.         begin
  1080.           Finished := true;
  1081.           Result := Ord( ResponseChar ) - 48;
  1082.         end;
  1083.       end
  1084.       else
  1085.       begin
  1086.         { otherwise return preliminary result }
  1087.         Finished := true;
  1088.         Result := TCPIP_STATUS_PRELIMINARY;
  1089.       end;
  1090.     end
  1091.     else
  1092.     begin
  1093.     end;
  1094.   until ( Finished and ( not LeftoversOnTable ));
  1095.   { Return buffer as response string }
  1096.   ResponseString := TheBuffer;
  1097. end;
  1098.  
  1099. { Boilerplate error routine }
  1100. procedure TFTPComponent.FTPSocketsErrorOccurred( Sender     : TObject;
  1101.                                                  ErrorCode  : Integer;
  1102.                                                  TheMessage : String   );
  1103. begin
  1104.   CCInetCCForm.SocketsErrorOccurred( Sender,ErrorCode,TheMessage );
  1105. end;
  1106.  
  1107. { This is the FTP components initial connection routine }
  1108. function TFTPComponent.EstablishConnection(
  1109.           PCRPointer : PConnectionsRecord ) : Boolean;
  1110. var TheReturnString : String;  { Internal string holder }
  1111.     TheResult       : Integer; { Internal int holder    }
  1112. begin
  1113.   { Set default FTP Port value }
  1114.   Socket1.PortName := '21';
  1115.   { Get the ip address from the record }
  1116.   Socket1.IPAddressName := PCRPointer^.CIPAddress;
  1117.   { Set blocking mode }
  1118.   Socket1.AsynchMode := False;
  1119.   { Clear condition variables }
  1120.   GlobalErrorCode := 0;
  1121.   GlobalAbortedFlag := false;
  1122.   { Actually attempt to connect }
  1123.   Socket1.CCSockConnect;
  1124.   { Check if connected }
  1125.   if (( GlobalAbortedFlag ) or ( GlobalErrorCode <> 0 ) or
  1126.       ( Socket1.TheSocket = INVALID_SOCKET )) then
  1127.   begin { Didn't connect; signal error and abort }
  1128.     { Do clever C formatting trick }
  1129.     TheReturnString :=
  1130.      DoCStyleFormat( 'FTP Host %s Connection Failed!' ,
  1131.       [ PCRPointer^.CIPAddress ] );
  1132.     { Put result in progress and status line }
  1133.     AddProgressText( TheReturnString );
  1134.     ShowProgressErrorText( TheReturnString );
  1135.     { Signal error }
  1136.     Result := False;
  1137.     { leave }
  1138.     exit;
  1139.   end
  1140.   else
  1141.   begin
  1142.     Connection_Established := true;
  1143.     { Signal successful connection }
  1144.     TheReturnString := DoCStyleFormat(
  1145.       'Connected on Local port: %s with IP: %s',
  1146.       [ Socket1.GetSocketPort( Socket1.TheSocket ),
  1147.         Socket1.GetSocketIPAddress( Socket1.TheSocket )]);
  1148.     { Put result in progress and status line }
  1149.     CCINetCCForm.AddProgressText( TheReturnString );
  1150.     CCINetCCForm.ShowProgressText( TheReturnString );
  1151.     TheReturnString := DoCStyleFormat(
  1152.      'Connected to Remote port: %s with IP: %s',
  1153.       [ Socket1.GetSocketPeerPort( Socket1.TheSocket ),
  1154.         Socket1.GetSocketPeerIPAddress( Socket1.TheSocket )]);
  1155.     { Put result in progress and status line }
  1156.     CCINetCCForm.AddProgressText( TheReturnString );
  1157.     CCINetCCForm.ShowProgressText( TheReturnString );
  1158.     TheReturnString := DoCStyleFormat( 'Successfully connected to %s',
  1159.      [ Socket1.IPAddressName ]);
  1160.     { Put result in progress and status line }
  1161.     CCINetCCForm.AddProgressText( TheReturnString );
  1162.     CCINetCCForm.ShowProgressText( TheReturnString );
  1163.     repeat
  1164.       TheResult := GetFTPServerResponse( TheReturnString );
  1165.       { Put result in progress and status line }
  1166.       AddProgressText( TheReturnString );
  1167.       ShowProgressText( TheReturnString );
  1168.     until (( GlobalAbortedFlag ) or ( TheResult <> TCPIP_STATUS_PRELIMINARY ));
  1169.     if ( GlobalAbortedFlag or ( TheResult <> TCPIP_STATUS_COMPLETED )) then
  1170.     begin
  1171.       { Do clever C formatting trick }
  1172.       TheReturnString :=
  1173.        DoCStyleFormat( 'FTP Host %s Connection Failed!' ,
  1174.         [ PCRPointer^.CIPAddress ] );
  1175.       { Put result in progress and status line }
  1176.       AddProgressText( TheReturnString );
  1177.       ShowProgressErrorText( TheReturnString );
  1178.       { Signal error }
  1179.       Result := False;
  1180.       { leave }
  1181.       exit;
  1182.     end
  1183.     else Result := true; { Signal no problem }
  1184.   end;
  1185. end;
  1186.  
  1187. { This is the FTP components USER login routine }
  1188. function TFTPComponent.LoginUser(
  1189.           PCRPointer : PConnectionsRecord ) : Boolean;
  1190. var TheReturnString : String;  { Internal string holder }
  1191.     TheResult       : Integer; { Internal int holder    }
  1192. begin
  1193.   TheReturnString :=
  1194.    DoCStyleFormat( 'USER %s' ,
  1195.     [ PCRPointer^.CUserName ] );
  1196.   { Put result in progress and status line }
  1197.   AddProgressText( TheReturnString );
  1198.   ShowProgressText( TheReturnString );
  1199.   { Begin login sequence with user name }
  1200.   TheResult := PerformFTPCommand( 'USER %s',
  1201.                                   [ PCRPointer^.CUserName ] );
  1202.   if TheResult <> TCPIP_STATUS_PRELIMINARY then
  1203.   begin
  1204.     FTPCommandInProgress := false;
  1205.     Result := false;
  1206.     exit;
  1207.   end;
  1208.   repeat
  1209.     TheResult := GetFTPServerResponse( TheReturnString );
  1210.     { Put result in progress and status line }
  1211.     AddProgressText( TheReturnString );
  1212.     ShowProgressText( TheReturnString );
  1213.   until (( GlobalAbortedFlag ) or ( TheResult <> TCPIP_STATUS_PRELIMINARY ));
  1214.   FTPCommandInProgress := false;
  1215.   if ( GlobalAbortedFlag or ( TheResult <> TCPIP_STATUS_CONTINUING )) then
  1216.   begin
  1217.     { Do clever C formatting trick }
  1218.     TheReturnString :=
  1219.      DoCStyleFormat( 'FTP Host %s Connection Failed!' ,
  1220.       [ PCRPointer^.CIPAddress ] );
  1221.     { Put result in progress and status line }
  1222.     AddProgressText( TheReturnString );
  1223.     ShowProgressErrorText( TheReturnString );
  1224.     { Signal error }
  1225.     Result := False;
  1226.     { leave }
  1227.     exit;
  1228.   end
  1229.   else Result := true; { Signal no problem }
  1230. end;
  1231.  
  1232. function TFTPComponent.DeleteRemoteDirectory( TheDir : String ) : Boolean;
  1233. var TheReturnString : String;  { Internal string holder }
  1234.     TheResult       : Integer; { Internal int holder    }
  1235. begin
  1236.   TheReturnString := DoCStyleFormat( 'RMD %s' ,
  1237.    [ TheDir ] );
  1238.   { Put result in progress and status line }
  1239.   AddProgressText( TheReturnString );
  1240.   ShowProgressText( TheReturnString );
  1241.   { Send Password sequence }
  1242.   TheResult := PerformFTPCommand( 'RMD %s',
  1243.                                   [ TheDir ] );
  1244.   if TheResult <> TCPIP_STATUS_PRELIMINARY then
  1245.   begin
  1246.     Result := false;
  1247.     FTPCommandInProgress := false;
  1248.     exit;
  1249.   end;
  1250.   repeat
  1251.     TheResult := GetFTPServerResponse( TheReturnString );
  1252.     { Put result in progress and status line }
  1253.     AddProgressText( TheReturnString );
  1254.     ShowProgressText( TheReturnString );
  1255.   until (( GlobalAbortedFlag ) or ( TheResult <> TCPIP_STATUS_PRELIMINARY ));
  1256.   FTPCommandInProgress := false;
  1257.   if ( GlobalAbortedFlag or ( TheResult <> TCPIP_STATUS_COMPLETED )) then
  1258.   begin
  1259.     { Do clever C formatting trick }
  1260.     TheReturnString :=
  1261.      DoCStyleFormat( 'Delete Directory %s Failed!' ,
  1262.       [ TheDir ] );
  1263.     { Put result in progress and status line }
  1264.     AddProgressText( TheReturnString );
  1265.     ShowProgressErrorText( TheReturnString );
  1266.     { Signal error }
  1267.     Result := False;
  1268.     { leave }
  1269.     exit;
  1270.   end
  1271.   else Result := true; { Signal no problem }
  1272. end;
  1273.  
  1274. function TFTPComponent.CreateRemoteDirectory( TheDir : String ) : Boolean;
  1275. var TheReturnString : String;  { Internal string holder }
  1276.     TheResult       : Integer; { Internal int holder    }
  1277. begin
  1278.   TheReturnString := DoCStyleFormat( 'MKD %s' ,
  1279.     [ TheDir ] );
  1280.   { Put result in progress and status line }
  1281.   AddProgressText( TheReturnString );
  1282.   ShowProgressText( TheReturnString );
  1283.   { Send Password sequence }
  1284.   TheResult := PerformFTPCommand( 'MKD %s',
  1285.                                   [ TheDir ] );
  1286.   if TheResult <> TCPIP_STATUS_PRELIMINARY then
  1287.   begin
  1288.     Result := false;
  1289.     FTPCommandInProgress := false;
  1290.     exit;
  1291.   end;
  1292.   repeat
  1293.     TheResult := GetFTPServerResponse( TheReturnString );
  1294.     { Put result in progress and status line }
  1295.     AddProgressText( TheReturnString );
  1296.     ShowProgressText( TheReturnString );
  1297.   until (( GlobalAbortedFlag ) or ( TheResult <> TCPIP_STATUS_PRELIMINARY ));
  1298.   FTPCommandInProgress := false;
  1299.   if ( GlobalAbortedFlag or ( TheResult <> TCPIP_STATUS_COMPLETED )) then
  1300.   begin
  1301.     { Do clever C formatting trick }
  1302.     TheReturnString :=
  1303.      DoCStyleFormat( 'Create Directory %s Failed!' ,
  1304.       [ TheDir ] );
  1305.     { Put result in progress and status line }
  1306.     AddProgressText( TheReturnString );
  1307.     ShowProgressErrorText( TheReturnString );
  1308.     { Signal error }
  1309.     Result := False;
  1310.     { leave }
  1311.     exit;
  1312.   end
  1313.   else Result := true; { Signal no problem }
  1314. end;
  1315.  
  1316.  
  1317. function TFTPComponent.DeleteRemoteFile( TheFileName : String ) : Boolean;
  1318. var TheReturnString : String;  { Internal string holder }
  1319.     TheResult       : Integer; { Internal int holder    }
  1320. begin
  1321.   TheReturnString := DoCStyleFormat( 'DELE %s' ,
  1322.     [ TheFileName ] );
  1323.   { Put result in progress and status line }
  1324.   AddProgressText( TheReturnString );
  1325.   ShowProgressText( TheReturnString );
  1326.   { Send Password sequence }
  1327.   TheResult := PerformFTPCommand( 'DELE %s',
  1328.                                   [ TheFileName ] );
  1329.   if TheResult <> TCPIP_STATUS_PRELIMINARY then
  1330.   begin
  1331.     Result := false;
  1332.     FTPCommandInProgress := false;
  1333.     exit;
  1334.   end;
  1335.   repeat
  1336.     TheResult := GetFTPServerResponse( TheReturnString );
  1337.     { Put result in progress and status line }
  1338.     AddProgressText( TheReturnString );
  1339.     ShowProgressText( TheReturnString );
  1340.   until (( GlobalAbortedFlag ) or ( TheResult <> TCPIP_STATUS_PRELIMINARY ));
  1341.   FTPCommandInProgress := false;
  1342.   if ( GlobalAbortedFlag or ( TheResult <> TCPIP_STATUS_COMPLETED )) then
  1343.   begin
  1344.     { Do clever C formatting trick }
  1345.     TheReturnString :=
  1346.      DoCStyleFormat( 'Delete File %s Failed!' ,
  1347.       [ TheFileName ] );
  1348.     { Put result in progress and status line }
  1349.     AddProgressText( TheReturnString );
  1350.     ShowProgressErrorText( TheReturnString );
  1351.     { Signal error }
  1352.     Result := False;
  1353.     { leave }
  1354.     exit;
  1355.   end
  1356.   else Result := true; { Signal no problem }
  1357. end;
  1358.  
  1359. { This is the FTP components PASSWORD routine }
  1360. function TFTPComponent.SendPassword(
  1361.           PCRPointer : PConnectionsRecord ) : Boolean;
  1362. var TheReturnString : String;  { Internal string holder }
  1363.     TheResult       : Integer; { Internal int holder    }
  1364. begin
  1365.   TheReturnString := 'PASS XXXXXX' + #13#10;
  1366.   { Put result in progress and status line }
  1367.   AddProgressText( TheReturnString );
  1368.   ShowProgressText( TheReturnString );
  1369.   { Send Password sequence }
  1370.   TheResult := PerformFTPCommand( 'PASS %s',
  1371.                                   [ PCRPointer^.CPassword ] );
  1372.   if TheResult <> TCPIP_STATUS_PRELIMINARY then
  1373.   begin
  1374.     Result := false;
  1375.     FTPCommandInProgress := false;
  1376.     exit;
  1377.   end;
  1378.   repeat
  1379.     TheResult := GetFTPServerResponse( TheReturnString );
  1380.     { Put result in progress and status line }
  1381.     AddProgressText( TheReturnString );
  1382.     ShowProgressText( TheReturnString );
  1383.   until (( GlobalAbortedFlag ) or ( TheResult <> TCPIP_STATUS_PRELIMINARY ));
  1384.   FTPCommandInProgress := false;
  1385.   if ( GlobalAbortedFlag or ( TheResult <> TCPIP_STATUS_COMPLETED )) then
  1386.   begin
  1387.     { Do clever C formatting trick }
  1388.     TheReturnString :=
  1389.      DoCStyleFormat( 'FTP Host %s Connection Failed!' ,
  1390.       [ PCRPointer^.CIPAddress ] );
  1391.     { Put result in progress and status line }
  1392.     AddProgressText( TheReturnString );
  1393.     ShowProgressErrorText( TheReturnString );
  1394.     { Signal error }
  1395.     Result := False;
  1396.     { leave }
  1397.     exit;
  1398.   end
  1399.   else Result := true; { Signal no problem }
  1400. end;
  1401.  
  1402. { This is the FTP components CWD routine }
  1403. function TFTPComponent.SetRemoteStartupDirectory(
  1404.           PCRPointer : PConnectionsRecord ) : Boolean;
  1405. var TheReturnString : String;  { Internal string holder }
  1406.     TheResult       : Integer; { Internal int holder    }
  1407. begin
  1408.   Result := true;
  1409.   if PCRPointer^.CStartDir <> '' then
  1410.   begin
  1411.     TheReturnString :=
  1412.      DoCStyleFormat( 'CWD %s' ,
  1413.       [ PCRPointer^.CStartDir ] );
  1414.     { Put result in progress and status line }
  1415.     AddProgressText( TheReturnString );
  1416.     ShowProgressText( TheReturnString );
  1417.     { Send Password sequence }
  1418.     TheResult := PerformFTPCommand( 'CWD %s',
  1419.                                     [ PCRPointer^.CStartDir ] );
  1420.     if TheResult <> TCPIP_STATUS_PRELIMINARY then
  1421.     begin
  1422.       Result := false;
  1423.       FTPCommandInProgress := false;
  1424.       exit;
  1425.     end;
  1426.     repeat
  1427.       TheResult := GetFTPServerResponse( TheReturnString );
  1428.       { Put result in progress and status line }
  1429.       AddProgressText( TheReturnString );
  1430.       ShowProgressText( TheReturnString );
  1431.    until (( GlobalAbortedFlag ) or ( TheResult <> TCPIP_STATUS_PRELIMINARY ));
  1432.    FTPCommandInProgress := false;
  1433.    if ( GlobalAbortedFlag or ( TheResult <> TCPIP_STATUS_COMPLETED )) then
  1434.     begin
  1435.       { Do clever C formatting trick }
  1436.       TheReturnString :=
  1437.        DoCStyleFormat( 'CWD to %s Failed!' ,
  1438.         [ PCRPointer^.CStartDir ] );
  1439.       { Put result in progress and status line }
  1440.       AddProgressText( TheReturnString );
  1441.       ShowProgressErrorText( TheReturnString );
  1442.       { Signal error }
  1443.       Result := False;
  1444.       { leave }
  1445.       exit;
  1446.     end
  1447.     else Result := true; { Signal no problem }
  1448.   end;
  1449. end;
  1450.  
  1451. { This is the FTP components CWD routine }
  1452. function TFTPComponent.SetRemoteDirectory( TheDir : String ) : Boolean;
  1453. var TheReturnString : String;  { Internal string holder }
  1454.     TheResult       : Integer; { Internal int holder    }
  1455. begin
  1456.   Result := true;
  1457.   if TheDir <> '' then
  1458.   begin
  1459.     TheReturnString :=
  1460.      DoCStyleFormat( 'CWD %s' ,
  1461.       [ TheDir ] );
  1462.     { Put result in progress and status line }
  1463.     AddProgressText( TheReturnString );
  1464.     ShowProgressText( TheReturnString );
  1465.     { Send Password sequence }
  1466.     TheResult := PerformFTPCommand( 'CWD %s',
  1467.                                     [ TheDir ] );
  1468.     if TheResult <> TCPIP_STATUS_PRELIMINARY then
  1469.     begin
  1470.       Result := false;
  1471.       FTPCommandInProgress := false;
  1472.       exit;
  1473.     end;
  1474.     repeat
  1475.       TheResult := GetFTPServerResponse( TheReturnString );
  1476.       { Put result in progress and status line }
  1477.       AddProgressText( TheReturnString );
  1478.       ShowProgressText( TheReturnString );
  1479.    until (( GlobalAbortedFlag ) or ( TheResult <> TCPIP_STATUS_PRELIMINARY ));
  1480.    FTPCommandInProgress := false;
  1481.    if ( GlobalAbortedFlag or ( TheResult <> TCPIP_STATUS_COMPLETED )) then
  1482.     begin
  1483.       { Do clever C formatting trick }
  1484.       TheReturnString :=
  1485.        DoCStyleFormat( 'CWD to %s Failed!' ,
  1486.         [ TheDir ] );
  1487.       { Put result in progress and status line }
  1488.       AddProgressText( TheReturnString );
  1489.       ShowProgressErrorText( TheReturnString );
  1490.       { Signal error }
  1491.       Result := False;
  1492.       { leave }
  1493.       exit;
  1494.     end
  1495.     else Result := true; { Signal no problem }
  1496.   end;
  1497. end;
  1498.  
  1499. { This is the FTP components QUIT routine }
  1500. function TFTPComponent.Disconnect : Boolean;
  1501. var TheReturnString : String;  { Internal string holder }
  1502.     TheResult       : Integer; { Internal int holder    }
  1503. begin
  1504.   TheReturnString :=
  1505.    DoCStyleFormat( 'QUIT' ,
  1506.     [ nil ] );
  1507.   { Put result in progress and status line }
  1508.   AddProgressText( TheReturnString );
  1509.   ShowProgressText( TheReturnString );
  1510.   { Begin login sequence with user name }
  1511.   PerformFTPCommand( 'QUIT', [ nil ] );
  1512.   repeat
  1513.     TheResult := GetFTPServerResponse( TheReturnString );
  1514.     { Put result in progress and status line }
  1515.     AddProgressText( TheReturnString );
  1516.     ShowProgressText( TheReturnString );
  1517.   until (( GlobalAbortedFlag ) or ( TheResult <> TCPIP_STATUS_PRELIMINARY ));
  1518.   FTPCommandInProgress := false;
  1519.   if ( GlobalAbortedFlag or ( TheResult <> TCPIP_STATUS_COMPLETED )) then
  1520.   begin
  1521.     { Do clever C formatting trick }
  1522.     TheReturnString :=
  1523.      DoCStyleFormat( 'FTP Host Connection Failed!' ,
  1524.       [ nil ] );
  1525.     { Put result in progress and status line }
  1526.     AddProgressText( TheReturnString );
  1527.     ShowProgressErrorText( TheReturnString );
  1528.     { Signal error }
  1529.     Result := False;
  1530.     { leave }
  1531.     exit;
  1532.   end
  1533.   else Result := true; { Signal no problem }
  1534. end;
  1535.  
  1536. { This is the FTP components PWD routine }
  1537. function TFTPComponent.GetRemoteWorkingDirectory( var RemoteDir : String )
  1538.           : Boolean;
  1539. var TheReturnString : String;  { Internal string holder }
  1540.     TheResult       : Integer; { Internal int holder    }
  1541. begin
  1542.   TheReturnString :=
  1543.    DoCStyleFormat( 'PWD' ,
  1544.     [ nil ] );
  1545.   { Put result in progress and status line }
  1546.   AddProgressText( TheReturnString );
  1547.   ShowProgressText( TheReturnString );
  1548.   { Send Password sequence }
  1549.   TheResult := PerformFTPCommand( 'PWD',
  1550.                                   [ nil ] );
  1551.   if TheResult <> TCPIP_STATUS_PRELIMINARY then
  1552.   begin
  1553.     Result := false;
  1554.     FTPCommandInProgress := false;
  1555.     exit;
  1556.   end;
  1557.   repeat
  1558.     TheResult := GetFTPServerResponse( TheReturnString );
  1559.     { Put result in progress and status line }
  1560.     AddProgressText( TheReturnString );
  1561.     ShowProgressText( TheReturnString );
  1562.   until (( GlobalAbortedFlag ) or ( TheResult <> TCPIP_STATUS_PRELIMINARY ));
  1563.   FTPCommandInProgress := false;
  1564.   if ( GlobalAbortedFlag or ( TheResult <> TCPIP_STATUS_COMPLETED )) then
  1565.   begin
  1566.     { Do clever C formatting trick }
  1567.     TheReturnString :=
  1568.      DoCStyleFormat( 'FTP Host Connection Failed!' ,
  1569.       [ nil ] );
  1570.     { Put result in progress and status line }
  1571.     AddProgressText( TheReturnString );
  1572.     ShowProgressErrorText( TheReturnString );
  1573.     { Signal error }
  1574.     Result := False;
  1575.     { leave }
  1576.     exit;
  1577.   end
  1578.   else
  1579.   begin
  1580.     Result := true; { Signal no problem }
  1581.     RemoteDir := TheReturnString; { Send back last string on faith }
  1582.   end;
  1583. end;
  1584.  
  1585. { This function sets up a listening port on socekt 2 and handle text replies }
  1586. function TFTPComponent.GetListeningPort : Integer;
  1587. var
  1588.   Address1 ,
  1589.   Address2 ,
  1590.   Address3 ,
  1591.   Address4        : integer; { Address integer conversions }
  1592.   IPAddress       : string;  { IP Address holder           }
  1593.   PortCommand     : string;  { Command holder              }
  1594.   TheResult       : Integer; { Result holder               }
  1595.   TheReturnString : String;  { ditto                       }
  1596. begin
  1597.   { Set up any port on socket 2 }
  1598.   Socket2.PortName := '0';
  1599.   { Listen on a socket }
  1600.   Socket2.CCSockListen;
  1601.   { Get the IP Address of socket 1 and convert it to numbers }
  1602.   IPAddress := Socket1.GetSocketIPAddress( Socket1.TheSocket );
  1603.   Address1 := StrToInt( copy( IPAddress , 1 , Pos( '.' , IPAddress ) -1 ));
  1604.   IPAddress := copy( IPAddress , Pos( '.' , IPAddress ) + 1 , 255 );
  1605.   Address2 := StrToInt( copy( IPAddress , 1 , Pos( '.' , IPAddress) -1 ));
  1606.   IPAddress := copy( IPAddress , Pos( '.' , IPAddress ) + 1 , 255 );
  1607.   Address3 := StrToInt( copy( IPAddress , 1 , Pos( '.' , IPAddress ) -1 ));
  1608.   Address4 := StrToInt( copy( IPAddress , Pos( '.' , IPAddress ) + 1 , 255 ));
  1609.   { Turn it into a command and add socket 2 stuff }
  1610.   PortCommand := format( 'PORT %d,%d,%d,%d,%d,%d' ,
  1611.    [ Address1 , Address2 , Address3 , Address4 ,
  1612.     StrToInt( Socket2.GetSocketPort( Socket2.TheMasterSocket )) Shr 8,
  1613.     StrToInt( Socket2.GetSocketPort( Socket2.TheMasterSocket )) and $ff ]);
  1614.   { Put result in progress and status line }
  1615.   AddProgressText( PortCommand + #13#10 );
  1616.   ShowProgressText( PortCommand  + #13#10 );
  1617.   TheResult := PerformFTPCommand( PortCommand , [nil] );
  1618.   if TheResult <> TCPIP_STATUS_PRELIMINARY then
  1619.   begin
  1620.     Result := TCPIP_STATUS_FATAL_ERROR;
  1621.     FTPCommandInProgress := false;
  1622.     exit;
  1623.   end;
  1624.   repeat
  1625.     TheResult := GetFTPServerResponse( TheReturnString );
  1626.     { Put result in progress and status line }
  1627.     AddProgressText( TheReturnString );
  1628.     ShowProgressText( TheReturnString );
  1629.   until (( GlobalAbortedFlag ) or ( TheResult <> TCPIP_STATUS_PRELIMINARY ));
  1630.   FTPCommandInProgress := false;
  1631.   if ( GlobalAbortedFlag or ( TheResult <> TCPIP_STATUS_COMPLETED )) then
  1632.   begin
  1633.     { Do clever C formatting trick }
  1634.     TheReturnString :=
  1635.      DoCStyleFormat( 'FTP Host Connection Failed!' ,
  1636.       [ nil ] );
  1637.     { Put result in progress and status line }
  1638.     AddProgressText( TheReturnString );
  1639.     ShowProgressErrorText( TheReturnString );
  1640.     { Signal error }
  1641.     Result := TheResult;
  1642.     { leave }
  1643.     exit;
  1644.   end
  1645.   else
  1646.   begin
  1647.     { Return good result and leave }
  1648.     Result := TheResult;
  1649.     exit;
  1650.   end;
  1651. end;
  1652.  
  1653. { This function returns part of a unit text string }
  1654. function TFTPComponent.GetUNIXTextString( var StringIn : String ) : String;
  1655. var
  1656.   ReturnString : String;
  1657.   TheLength ,
  1658.   Counter_1   : integer;
  1659. begin
  1660.   TheLength := Length( StringIn );
  1661.   if TheLength > 1 then
  1662.   begin
  1663.     for Counter_1 := 1 to TheLength do
  1664.     begin
  1665.       if StringIn[ Counter_1 ] = #10 then
  1666.       begin
  1667.         ReturnString := HolderLine;
  1668.         HolderLine := '';
  1669.         StringIn := Copy( StringIn , Counter_1 + 1 , 255 );
  1670.         Result := ReturnString;
  1671.         exit;
  1672.       end
  1673.       else
  1674.       begin
  1675.         if StringIn[ Counter_1 ] <> #0 then
  1676.         begin
  1677.           if StringIn[ Counter_1 ] <> #13 then
  1678.            HolderLine := HolderLine + StringIn[ Counter_1 ];
  1679.         end
  1680.         else
  1681.         begin
  1682.           Result := '';
  1683.           StringIn := '';
  1684.         end;
  1685.       end;
  1686.     end;
  1687.   end;
  1688.   Result := '';
  1689.   StringIn := '';
  1690. end;
  1691.  
  1692. procedure TFTPComponent.GetFileNameFromUNIXFileName( var TheName : String );
  1693. var Counter_1 : Integer;
  1694.     ResultString : String;
  1695.     Finished : Boolean;
  1696. begin
  1697.   if Pos( 'TOTAL' , Uppercase( TheName )) <> 0 then
  1698.   begin
  1699.     TheName := '';
  1700.     exit;
  1701.   end;
  1702.   Counter_1 := Length( TheName );
  1703.   ResultString := '';
  1704.   Finished := false;
  1705.   while not Finished do
  1706.   begin
  1707.     if TheName[ Counter_1 ] <> ' ' then
  1708.     begin
  1709.       Counter_1 := Counter_1 - 1;
  1710.       if Counter_1 = 0 then
  1711.       begin
  1712.         ResultString := TheName;
  1713.         Finished := true;
  1714.       end;
  1715.     end
  1716.     else
  1717.     begin
  1718.       Finished := true;
  1719.       ResultString := Copy( TheName , Counter_1 + 1 , 255 );
  1720.     end;
  1721.   end;
  1722.   TheName := ResultString;
  1723. end;
  1724.  
  1725. { This is the FTP components get remote directory listing into a list box }
  1726. function TFTPComponent.GetRemoteDirectoryListing( TheListBox : TListBox )
  1727.           : Boolean;
  1728. var TheReturnString : String;  { Internal string holder }
  1729.     TheResult       : Integer; { Internal int holder    }
  1730.     InputString     : String;
  1731.     Through ,
  1732.     Finished        : Boolean;
  1733. begin
  1734.   TheListBox.Clear;
  1735.   TheListbox.Tag := 2;
  1736.   TheListBox.Items.Add('..');
  1737.   Result := true;
  1738.   TheReturnString :=
  1739.    DoCStyleFormat( 'TYPE A' ,
  1740.     [ nil ] );
  1741.   { Put result in progress and status line }
  1742.   AddProgressText( TheReturnString );
  1743.   ShowProgressText( TheReturnString );
  1744.   { Send Password sequence }
  1745.   TheResult := PerformFTPCommand( 'TYPE A',
  1746.                                   [ nil ] );
  1747.   if TheResult <> TCPIP_STATUS_PRELIMINARY then
  1748.   begin
  1749.     Result := true;
  1750.     FTPCommandInProgress := false;
  1751.     exit;
  1752.   end;
  1753.   repeat
  1754.     TheResult := GetFTPServerResponse( TheReturnString );
  1755.     { Put result in progress and status line }
  1756.     AddProgressText( TheReturnString );
  1757.     ShowProgressText( TheReturnString );
  1758.   until (( GlobalAbortedFlag ) or ( TheResult <> TCPIP_STATUS_PRELIMINARY ));
  1759.   FTPCommandInProgress := false;
  1760.   if ( GlobalAbortedFlag or ( TheResult <> TCPIP_STATUS_COMPLETED )) then
  1761.   begin
  1762.     { Do clever C formatting trick }
  1763.     TheReturnString :=
  1764.      DoCStyleFormat( 'FTP Host Connection Failed!' ,
  1765.       [ nil ] );
  1766.     { Put result in progress and status line }
  1767.     AddProgressText( TheReturnString );
  1768.     ShowProgressErrorText( TheReturnString );
  1769.     { Signal error }
  1770.     Result := true;
  1771.     { leave }
  1772.     exit;
  1773.   end
  1774.   else
  1775.   begin
  1776.     { Set up socket 2 for listening }
  1777.     Socket2.AsynchMode := False;
  1778.     Socket2.NonAsynchTimeoutValue := 60;
  1779.     { do a listen and send command to server that this is receipt socket }
  1780.     if GetListeningPort = TCPIP_STATUS_FATAL_ERROR then
  1781.     begin
  1782.       Socket2.CCSockCancelListen;
  1783.       exit;
  1784.     end;
  1785.     Socket1.NonAsynchTimeoutValue := 0; {infinite timeout}
  1786.     TheResult := PerformFTPCommand( 'LIST' , [nil] );
  1787.     GetFTPServerResponse( TheReturnString );
  1788.     AddProgressText( TheReturnString );
  1789.     ShowProgressText( TheReturnString );
  1790.     Socket1.NonAsynchTimeoutValue := 30;
  1791.     if (( TheResult = TCPIP_STATUS_RETRY_COMMAND ) or
  1792.        ( TheResult = TCPIP_STATUS_FATAL_ERROR )) then
  1793.     begin
  1794.       TheReturnString :=
  1795.        DoCStyleFormat( 'Could not obtain remote directory!' ,
  1796.         [ nil ] );
  1797.       { Put result in progress and status line }
  1798.       AddProgressText( TheReturnString );
  1799.       ShowProgressErrorText( TheReturnString );
  1800.       Socket2.CCSockCancelListen;
  1801.       Result := true;
  1802.       exit;
  1803.     end;
  1804.     Socket2.CCSockAccept;
  1805.     if (( GlobalAbortedFlag ) or ( GlobalErrorCode <> 0 )) then
  1806.     begin
  1807.       TheReturnString :=
  1808.        DoCStyleFormat( 'Could not establish receive socket!' ,
  1809.         [ nil ] );
  1810.       { Put result in progress and status line }
  1811.       AddProgressText( TheReturnString );
  1812.       ShowProgressErrorText( TheReturnString );
  1813.       Result := true;
  1814.       exit;
  1815.     end;
  1816.     Through := false;
  1817.     repeat
  1818.       TheReturnString := Socket2.StringData;
  1819.       if Length( TheReturnString ) = 0 then Through := true;
  1820.       if Length( TheReturnString ) > 0 then
  1821.       begin
  1822.         finished := false;
  1823.         while not finished do
  1824.         begin
  1825.           InputString := GetUNIXTextString( TheReturnString );
  1826.           if InputString = '' then Finished := true else
  1827.           begin
  1828.             GetFileNameFromUNIXFileName( InputString);
  1829.             If InputString <> '' then
  1830.             TheListBox.Items.Add( InputString );
  1831.           end;
  1832.         end;
  1833.       end;
  1834.       if GlobalAbortedFlag then
  1835.       begin
  1836.         Socket1.OutOfBand := 'ABOR'+#13#10;
  1837.         repeat
  1838.           TheResult := GetFTPServerResponse( TheReturnString );
  1839.           { Put result in progress and status line }
  1840.           AddProgressText( TheReturnString );
  1841.           ShowProgressText( TheReturnString );
  1842.         until (( GlobalAbortedFlag ) or ( TheResult <> TCPIP_STATUS_PRELIMINARY ));
  1843.         result := true;
  1844.         exit;
  1845.       end;
  1846.     until Through;
  1847.     GetFTPServerResponse( TheReturnString );
  1848.     AddProgressText( TheReturnString );
  1849.     ShowProgressText( TheReturnString );
  1850.     { cancel listening on second socket and close it }
  1851.     Socket2.CCSockCancelListen;
  1852.     Socket2.CCSockClose;
  1853.   end;
  1854.   FTPCommandInProgress := false;
  1855. end;
  1856.  
  1857. { This is the FTP components get remote directory listing into a list box }
  1858. function TFTPComponent.GetRemoteDirectoryListingToMemo : Boolean;
  1859. var TheReturnString : String;  { Internal string holder }
  1860.     TheResult       : Integer; { Internal int holder    }
  1861.     Through         : Boolean;
  1862. begin
  1863.   Result := true;
  1864.   TheReturnString :=
  1865.    DoCStyleFormat( 'TYPE A' ,
  1866.     [ nil ] );
  1867.   { Put result in progress and status line }
  1868.   AddProgressText( TheReturnString );
  1869.   ShowProgressText( TheReturnString );
  1870.   { Send Password sequence }
  1871.   TheResult := PerformFTPCommand( 'TYPE A',
  1872.                                   [ nil ] );
  1873.   if TheResult <> TCPIP_STATUS_PRELIMINARY then
  1874.   begin
  1875.     Result := true;
  1876.     FTPCommandInProgress := false;
  1877.     exit;
  1878.   end;
  1879.   repeat
  1880.     TheResult := GetFTPServerResponse( TheReturnString );
  1881.     { Put result in progress and status line }
  1882.     AddProgressText( TheReturnString );
  1883.     ShowProgressText( TheReturnString );
  1884.   until (( GlobalAbortedFlag ) or ( TheResult <> TCPIP_STATUS_PRELIMINARY ));
  1885.   FTPCommandInProgress := false;
  1886.   if ( GlobalAbortedFlag or ( TheResult <> TCPIP_STATUS_COMPLETED )) then
  1887.   begin
  1888.     { Do clever C formatting trick }
  1889.     TheReturnString :=
  1890.      DoCStyleFormat( 'FTP Host Connection Failed!' ,
  1891.       [ nil ] );
  1892.     { Put result in progress and status line }
  1893.     AddProgressText( TheReturnString );
  1894.     ShowProgressErrorText( TheReturnString );
  1895.     { Signal error }
  1896.     Result := true;
  1897.     { leave }
  1898.     exit;
  1899.   end
  1900.   else
  1901.   begin
  1902.     { Set up socket 2 for listening }
  1903.     Socket2.AsynchMode := False;
  1904.     Socket2.NonAsynchTimeoutValue := 30;
  1905.     { do a listen and send command to server that this is receipt socket }
  1906.     if GetListeningPort = TCPIP_STATUS_FATAL_ERROR then
  1907.     begin
  1908.       Socket2.CCSockCancelListen;
  1909.       exit;
  1910.     end;
  1911.     Socket1.NonAsynchTimeoutValue := 0; {infinite timeout}
  1912.     TheResult := PerformFTPCommand( 'LIST' , [nil] );
  1913.     GetFTPServerResponse( TheReturnString );
  1914.     AddProgressText( TheReturnString );
  1915.     ShowProgressText( TheReturnString );
  1916.     Socket1.NonAsynchTimeoutValue := 30;
  1917.     if (( TheResult = TCPIP_STATUS_RETRY_COMMAND ) or
  1918.        ( TheResult = TCPIP_STATUS_FATAL_ERROR )) then
  1919.     begin
  1920.       TheReturnString :=
  1921.        DoCStyleFormat( 'Could not obtain remote directory!' ,
  1922.         [ nil ] );
  1923.       { Put result in progress and status line }
  1924.       AddProgressText( TheReturnString );
  1925.       ShowProgressErrorText( TheReturnString );
  1926.       Socket2.CCSockCancelListen;
  1927.       Result := true;
  1928.       exit;
  1929.     end;
  1930.     Socket2.CCSockAccept;
  1931.     if (( GlobalAbortedFlag ) or ( GlobalErrorCode <> 0 )) then
  1932.     begin
  1933.       TheReturnString :=
  1934.        DoCStyleFormat( 'Could not establish receive socket!' ,
  1935.         [ nil ] );
  1936.       { Put result in progress and status line }
  1937.       AddProgressText( TheReturnString );
  1938.       ShowProgressErrorText( TheReturnString );
  1939.       Result := true;
  1940.       exit;
  1941.     end;
  1942.     Through := false;
  1943.     repeat
  1944.       TheReturnString := Socket2.StringData;
  1945.       if Length( TheReturnString ) = 0 then Through := true;
  1946.       if Length( TheReturnString ) > 0 then
  1947.       begin
  1948.         { Put result in progress and status line }
  1949.         AddProgressText( TheReturnString );
  1950.         ShowProgressText( TheReturnString );
  1951.       end;
  1952.       if GlobalAbortedFlag then
  1953.       begin
  1954.         Socket1.OutOfBand := 'ABOR'+#13#10;
  1955.         repeat
  1956.           TheResult := GetFTPServerResponse( TheReturnString );
  1957.           { Put result in progress and status line }
  1958.           AddProgressText( TheReturnString );
  1959.           ShowProgressText( TheReturnString );
  1960.         until (( GlobalAbortedFlag ) or ( TheResult <> TCPIP_STATUS_PRELIMINARY ));
  1961.         result := true;
  1962.         exit;
  1963.       end;
  1964.     until Through;
  1965.     GetFTPServerResponse( TheReturnString );
  1966.     AddProgressText( TheReturnString );
  1967.     ShowProgressText( TheReturnString );
  1968.     { cancel listening on second socket and close it }
  1969.     Socket2.CCSockCancelListen;
  1970.     Socket2.CCSockClose;
  1971.   end;
  1972. end;
  1973.  
  1974. { This is the FTP components get local directory listing into a list box }
  1975. function TFTPComponent.GetLocalDirectoryAndListing( var TheString : String;
  1976.                                                         TheListBox : TListBox )
  1977.           : Boolean;
  1978. var TheFLB : TFileListBox;
  1979. begin
  1980.   { Get the working directory }
  1981.   GetDir( 0 , TheString );
  1982.   { Clear incoming LB }
  1983.   TheListBox.Clear;
  1984.   TheListBox.Tag := 2;
  1985.   TheFLB := TFileListBox.Create( Application.MainForm );
  1986.   TheFLB.Visible := false;
  1987.   TheFLB.Parent := Application.MainForm;
  1988.   TheFLB.FileType := [ ftNormal , ftDirectory ];
  1989.   TheFLB.Directory := TheString;
  1990.   TheFLB.Update;
  1991.   TheListBox.Items.Assign( TheFLB.Items );
  1992.   TheFLB.Free;
  1993.   result := true;
  1994. end;
  1995.  
  1996. { This is a clever c-style formatting trick }
  1997. function TFTPComponent.DoCStyleFormat(
  1998.                 TheText      : string;
  1999.           const TheArguments : array of const ) : String;
  2000. begin
  2001.   Result := Format( TheText , TheArguments ) + #13#10;
  2002. end;
  2003.  
  2004. function TFTPComponent.GetQuotedString( TheString : String ) : String;
  2005. var TheIndex     : Integer; { Holder var }
  2006.     ResultString : String;  { ditto      }
  2007. begin
  2008.   { Find out if " present at all }
  2009.   TheIndex := Pos( '"' , TheString );
  2010.   If TheIndex = 0 then
  2011.   begin
  2012.     { If not, return null string and exit }
  2013.     Result := '';
  2014.     exit;
  2015.   end
  2016.   else
  2017.   begin
  2018.     { Get from first " to end of string in holder }
  2019.     ResultString := Copy( TheString , TheIndex + 1 , 255 );
  2020.     { Find position to second " }
  2021.     TheIndex := Pos( '"' , ResultString );
  2022.     { If no ending " then return whole string and leave }
  2023.     if TheIndex = 0 then
  2024.     begin
  2025.       Result := ResultString;
  2026.       exit;
  2027.     end
  2028.     else
  2029.     begin
  2030.       { Get internal text between quotes and exit }
  2031.       ResultString := Copy( ResultString , 1 , TheIndex - 1 );
  2032.       Result := ResultString;
  2033.     end;
  2034.   end;
  2035. end;
  2036.  
  2037. end.
  2038.