home *** CD-ROM | disk | FTP | other *** search
/ Delphi 2 - Developers' Solutions / Delphi 2 Developers' Solutions.iso / dds / chap10 / howto02 / delphi10 / ccicnntp.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1996-06-12  |  23.2 KB  |  665 lines

  1. unit Ccicnntp;
  2.  
  3. interface
  4.  
  5. uses
  6.   SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
  7.   Forms, Dialogs, ExtCtrls, StdCtrls, Buttons, Menus, FileCtrl, CCWSock, CCICCInf,
  8.   CCICCPrf, IniFiles, Gauges, CCiccfrm;
  9. type
  10.   { Component to hold NNTP handling capabilities }
  11.   TNNTPComponent = class( TWinControl )
  12.   public
  13.     NNTPCommandInProgress ,
  14.     Connection_Established : Boolean;
  15.     Socket1 : TCCSocket;
  16.     constructor Create( AOwner : TComponent ); override;
  17.     destructor Destroy; override;
  18.     function EstablishConnection( PCRPointer : PConnectionsRecord ) : Boolean;
  19.     function Disconnect : Boolean;
  20.     function DoCStyleFormat(       TheText      : string;
  21.                              const TheArguments : array of const ) : String;
  22.     procedure UpdateGauge( BytesFinished , TotalToHandle : longint );
  23.     procedure AddProgressText( WhatText : String );
  24.     procedure ShowProgressText( WhatText : String );
  25.     procedure ShowProgressErrorText( WhatText : String );
  26.     function GetNNTPServerResponse( var ResponseString : String ) : integer;
  27.     procedure NNTPSocketsErrorOccurred( Sender     : TObject;
  28.                                      ErrorCode  : Integer;
  29.                                      TheMessage : String   );
  30.     function PerformNNTPCommand(
  31.                     TheCommand   : string;
  32.               const TheArguments : array of const ) : Integer;
  33.     function PerformBlindNNTPCommand( TheCommand   : string ) : Integer;
  34.     function PerformNNTPExtendedCommand(
  35.                     TheCommand   : string;
  36.               const TheArguments : array of const ) : Integer;
  37.     function GetNNTPServerExtendedResponse( ResponseString : PChar ) : integer;
  38.     function GetNextSDItem(     WorkingString : String;
  39.                             var TheIndex      : Integer ) : String;
  40.     function GetListOfAvailableNewsGroups : Boolean;
  41.     procedure ParseNewsGroupListing(     TheListing : String;
  42.                                      var GroupName  : String;
  43.                                      var LowCurrent : Longint;
  44.                                      var HighCurrent : Longint;
  45.                                      var Postable    : Boolean  );
  46.   end;
  47.  
  48. implementation
  49.  
  50. { This function calls an extended response NNTP command routine }
  51. function TNNTPComponent.PerformNNTPExtendedCommand(
  52.                TheCommand   : string;
  53.          const TheArguments : array of const ) : Integer;
  54. var TheBuffer : string; { Text buffer }
  55. begin
  56.   { If command in progress send back -1 error }
  57.   if NNTPCommandInProgress then
  58.   begin
  59.     Result := -1;
  60.     exit;
  61.   end;
  62.   { Set status variable }
  63.   NNTPCommandInProgress := True;
  64.   { Set global error code }
  65.   GlobalErrorCode := 0;
  66.   { Format output string }
  67.   TheBuffer := Format( TheCommand , TheArguments );
  68.   { Preset failure code }
  69.   Result := TCPIP_STATUS_FATAL_ERROR;
  70.   { If invalid socket or no connection abort }
  71.   if ( Socket1.TheSocket = INVALID_SOCKET ) or not Connection_Established then
  72.    exit;
  73.   { Send the buffer plus EOL chars }
  74.   Socket1.StringData := TheBuffer + #13#10;
  75.   { if abort due to timeout or other error exit }
  76.   if (( GlobalAbortedFlag ) or ( GlobalErrorCode <> 0 )) then exit;
  77.   { Otherwise return preliminary code }
  78.   Result := TCPIP_STATUS_PRELIMINARY;
  79. end;
  80.  
  81. { This function gets an extended period-ended multiline response from the server }
  82. function TNNTPComponent.GetNNTPServerExtendedResponse( ResponseString : PChar ) : integer;
  83. var
  84.   { Assume ResponseString already allocated as 0..513 }
  85.   { Pointer to the response string }
  86.   TheBuffer ,
  87.   BufferPointer : array[0..255] of char;
  88.   HolderBuffer : array[0..513] of char;
  89.   { Character to check for response code }
  90.   ResponseChar   : char;
  91.   { Pointers into returned string }
  92.   TheIndex ,
  93.   TheLength     : integer;
  94.   { Control variable }
  95.   LeftoversInPan ,
  96.   Finished      : Boolean;
  97.   BufferString : String;
  98. begin
  99.   { Preset fatal error }
  100.   Result := TCPIP_STATUS_FATAL_ERROR;
  101.   { Start loop control }
  102.   LeftoversInPan := false;
  103.   Finished := false;
  104.   StrCopy( HolderBuffer , '' );
  105.   repeat
  106.     { Do a peek }
  107.     BufferString := Socket1.PeekData;
  108.     { If timeout or other error exit }
  109.     if (( GlobalAbortedFlag ) or ( GlobalErrorCode <> 0 )) then exit;
  110.     { Find end of line character }
  111.     TheIndex := Pos( #10 , BufferString );
  112.     if TheIndex = 0 then
  113.     begin
  114.       TheIndex := Pos( #13 , BufferString );
  115.       if TheIndex = 0 then
  116.       begin
  117.         TheIndex := Pos( #0 , BufferString );
  118.         if TheIndex = 0 then
  119.         begin
  120.           TheIndex := Length( BufferString );
  121.           LeftoversInPan := True;
  122.           StrPCopy( TheBuffer , BufferString );
  123.           StrCat( HolderBuffer , TheBuffer );
  124.           LeftoversOnTable := false;
  125.         end;
  126.       end;
  127.     end;
  128.     { If an end of line then process the line }
  129.     if TheIndex > 0 then
  130.     begin
  131.       { Get length of string }
  132.       TheLength := TheIndex;
  133.       { Receive actual data }
  134.       Socket1.CCSockReceive( Socket1.TheSocket   ,
  135.                              @BufferPointer[ 0 ] ,
  136.                              TheLength              );
  137.       { Abort if timeout or error }
  138.       if (( GlobalAbortedFlag ) or ( GlobalErrorCode <> 0 )) then exit;
  139.       { Put in the length byte }
  140.       BufferPointer[ TheLength ] := Chr( 0 );
  141.       if LeftOversOnTable then
  142.       begin
  143.         LeftOversOnTable := false;
  144.         StrCopy( ResponseString , HolderBuffer );
  145.         StrCat( ResponseString , BufferPointer );
  146.       end
  147.       else
  148.       begin
  149.         if not LeftoversInPan then StrCopy( ResponseString , BufferPointer );
  150.       end;
  151.       if LeftoversInPan then
  152.       begin
  153.         LeftoversInPan := false;
  154.         LeftoversOnTable := true;
  155.       end
  156.       else
  157.       begin
  158.         ResponseChar := ResponseString[ 0 ];
  159.         if (( ResponseChar = '.' ) and ( StrLen( ResponseString ) <= 3 )) then
  160.         begin
  161.           Finished := true;
  162.           Result := TCPIP_STATUS_COMPLETED;
  163.         end
  164.         else
  165.         begin
  166.           if ResponseChar = '.' then ResponseString[ 0 ] := ' ';
  167.           Finished := true;
  168.           Result := TCPIP_STATUS_PRELIMINARY;
  169.         end;
  170.       end;
  171.     end;
  172.   until ( Finished and ( not LeftoversOnTable ));
  173.   StrLCopy( ResponseString , ResponseString , StrLen( ResponseString ) - 2 );
  174. end;
  175.  
  176. { This function moves along a string from an index, getting the next }
  177. { string delimited item or last one on string.                       }
  178. function TNNTPComponent.GetNextSDItem(     WorkingString : String;
  179.                                        var TheIndex      : Integer ) : String;
  180. var HoldingString : String;
  181. begin
  182.   HoldingString := Copy( WorkingString , TheIndex + 1 , 255 );
  183.   TheIndex := Pos( ' ' , HoldingString );
  184.   if TheIndex = 0 then
  185.   begin
  186.     Result := HoldingString;
  187.   end
  188.   else
  189.   begin
  190.     HoldingString := Copy( HoldingString , 1 , TheIndex - 1 );
  191.     Result := HoldingString;
  192.   end;
  193. end;
  194.  
  195. { This is the first true "network" function; it sends a LIST command, eats }
  196. { a single 215 response and then grabs PChars of data from the server till }
  197. { It returns a period character. The returned line is sent to a NEWSGRP    }
  198. { file and a status update is send through.                                }
  199. function TNNTPComponent.GetListOfAvailableNewsGroups : Boolean;
  200. var TheReturnString : String;  { Internal string holder }
  201.     TheResult       : Integer; { Internal int holder    }
  202.     HoldPChar ,
  203.     TheHoldingPChar ,
  204.     TheReturnPChar  : PChar;
  205.     TheNGFile       : TextFile;
  206.     D1 , D2     : Longint;
  207.     D3          : Boolean;
  208.     GroupString : String;
  209.     TotalGroups : Longint;
  210. begin
  211.   Result := false;
  212.   TheReturnString :=
  213.    DoCStyleFormat( 'LIST' ,
  214.     [ nil ] );
  215.   { Put result in progress and status line }
  216.   AddProgressText( TheReturnString );
  217.   ShowProgressText( TheReturnString );
  218.   { Begin login sequence with user name }
  219.   TheResult := PerformNNTPCommand( 'LIST', [ nil ] );
  220.   if TheResult <> TCPIP_STATUS_PRELIMINARY then
  221.   begin
  222.     NNTPCommandInProgress := false;
  223.     Result := false;
  224.     exit;
  225.   end;
  226.   repeat
  227.     TheResult := GetNNTPServerResponse( TheReturnString );
  228.     { Put result in progress and status line }
  229.     AddProgressText( TheReturnString );
  230.     ShowProgressText( TheReturnString );
  231.   until (( GlobalAbortedFlag ) or ( TheResult <> TCPIP_STATUS_PRELIMINARY ));
  232.   NNTPCommandInProgress := false;
  233.   if ( GlobalAbortedFlag or ( TheResult <> TCPIP_STATUS_COMPLETED )) then
  234.   begin
  235.     { Do clever C formatting trick }
  236.     TheReturnString :=
  237.      DoCStyleFormat( 'LIST Failed!' ,
  238.       [ nil ] );
  239.     { Put result in progress and status line }
  240.     AddProgressText( TheReturnString );
  241.     ShowProgressErrorText( TheReturnString );
  242.     { Signal error }
  243.     Result := False;
  244.     { leave }
  245.     exit;
  246.   end;
  247.   try
  248.     AssignFile( TheNGFile , NewsPath + '\NEWSGRP.TXT' );
  249.     Rewrite( TheNGFile );
  250.   except
  251.     Socket1.OutOfBand := 'ABOR'+#13#10;
  252.     repeat
  253.       TheResult := GetNNTPServerResponse( TheReturnString );
  254.       { Put result in progress and status line }
  255.       AddProgressText( TheReturnString );
  256.       ShowProgressText( TheReturnString );
  257.     until (( GlobalAbortedFlag ) or ( TheResult <> TCPIP_STATUS_PRELIMINARY ));
  258.     Result := false;
  259.     exit;
  260.   end;
  261.   GetMem( TheReturnPChar , 514 );
  262.   HoldPChar := TheReturnPChar;
  263.   TotalGroups := 0;
  264.   CCICInfoDlg.ListBox1.Clear;
  265.   repeat
  266.     Application.ProcessMessages;
  267.     if GlobalAbortedFlag then exit;
  268.     Inc(TotalGroups );
  269.     TheResult := GetNNTPServerExtendedResponse( TheReturnPChar );
  270.     if StrLen( TheReturnPChar ) > 255 then
  271.     begin
  272.       Getmem( TheHoldingPChar , 255 );
  273.       while StrLen( TheReturnPChar ) > 255 do
  274.       begin
  275.         StrCopy( TheHoldingPChar , '' );
  276.         StrMove( TheHoldingPChar , TheReturnPChar , 255 );
  277.         TheReturnPChar := TheReturnPChar + 256;
  278.         TheReturnString := StrPas( TheHoldingPChar );
  279.         ParseNewsGroupListing( TheReturnString, GroupString, D1 , D2 , D3 );
  280.       end;
  281.       FreeMem( TheHoldingPChar , 255 );
  282.       Writeln( TheNGFile , GroupString );
  283.       CCICInfoDlg.ListBox1.Items.Add( GroupString );
  284.       CCINetCCForm.Panel1.Caption := GroupString +
  285.        '(' + IntToStr( TotalGroups ) + ')';
  286.     end
  287.     else
  288.     begin
  289.       TheReturnString := StrPas( TheReturnPChar );
  290.       ParseNewsGroupListing( TheReturnString, GroupString, D1 , D2 , D3 );
  291.       Writeln( TheNGFile , GroupString );
  292.       CCICInfoDlg.ListBox1.Items.Add( GroupString );
  293.       CCINetCCForm.Panel1.Caption := GroupString +
  294.        '(' + IntToStr( TotalGroups ) + ')';
  295.     end;
  296.   until (( GlobalAbortedFlag ) or ( TheResult = TCPIP_STATUS_COMPLETED ));
  297.   FreeMem( HoldPChar , 514 );
  298.   CloseFile( TheNGFile );
  299.   Result := true;
  300.   CCINetCCForm.Panel1.Caption := 'Finished LIST!';
  301. end;
  302.  
  303. procedure TNNTPComponent.ParseNewsGroupListing(     TheListing : String;
  304.                                 var GroupName  : String;
  305.                                 var LowCurrent : Longint;
  306.                                 var HighCurrent : Longint;
  307.                                 var Postable    : Boolean  );
  308. var HoldingString ,
  309.     HoldingString2 : String;
  310.     WorkingIndex  : Integer;
  311. begin
  312.   WorkingIndex := Pos( ' ' , TheListing );
  313.   if WorkingIndex = 0 then
  314.   begin
  315.     GroupName := TheListing;
  316.     LowCurrent :=  -1;
  317.     HighCurrent := -1;
  318.     Postable := false;
  319.     exit;
  320.   end;
  321.   GroupName := Copy( TheListing , 1 , WorkingIndex - 1 );
  322.   HoldingString := Copy( TheListing , WorkingIndex + 1 , 255 );
  323.   WorkingIndex := Pos(  ' ' , HoldingString );
  324.   HoldingString2 := Copy( HoldingString , 1 , WorkingIndex - 1 );
  325.   LowCurrent := StrToInt( HoldingString2 );
  326.   HoldingString := Copy( HoldingString , WorkingIndex + 1 , 255 );
  327.   WorkingIndex := Pos(  ' ' , HoldingString );
  328.   HoldingString2 := Copy( HoldingString , 1 , WorkingIndex - 1 );
  329.   HighCurrent := StrToInt( HoldingString2 );
  330.   HoldingString := Copy( HoldingString , WorkingIndex + 1 , 255 );
  331.   if (( HoldingString[ 1 ] = 'y' ) or ( HoldingString[ 1 ] = 'Y' )) then
  332.    Postable := true else Postable := false;
  333. end;
  334.  
  335. { This is another "Network" command which sets the GROUP to the name of the }
  336. { This sends FTP progress text to the Inet form }
  337. procedure TNNTPComponent.ShowProgressErrorText( WhatText : String );
  338. begin
  339.   CCInetCCForm.ShowProgressErrorText( WhatText );
  340. end;
  341.  
  342. { This is a core function! It performs an FTP command and if no timeout }
  343. { return a preliminary ok.                                              }
  344. function TNNTPComponent.PerformNNTPCommand(
  345.                  TheCommand        : string;
  346.            const TheArguments      : array of const ) : Integer;
  347. var TheBuffer : string; { Text buffer }
  348. begin
  349.   { If command in progress send back -1 error }
  350.   if NNTPCommandInProgress then
  351.   begin
  352.     Result := -1;
  353.     exit;
  354.   end;
  355.   { Set status variable }
  356.   NNTPCommandInProgress := True;
  357.   { Set global error code }
  358.   GlobalErrorCode := 0;
  359.   { Format output string }
  360.   TheBuffer := Format( TheCommand , TheArguments );
  361.   { Preset failure code }
  362.   Result := TCPIP_STATUS_FATAL_ERROR;
  363.   { If invalid socket or no connection abort }
  364.   if ( Socket1.TheSocket = INVALID_SOCKET ) or not Connection_Established then
  365.    exit;
  366.   { Send the buffer plus EOL chars }
  367.   Socket1.StringData := TheBuffer + #13#10;
  368.   { if abort due to timeout or other error exit }
  369.   if (( GlobalAbortedFlag ) or ( GlobalErrorCode <> 0 )) then exit;
  370.   { Otherwise return preliminary code }
  371.   Result := TCPIP_STATUS_PRELIMINARY;
  372. end;
  373.  
  374. { This is a core function! It performs an FTP command and if no timeout }
  375. { return a preliminary ok.                                              }
  376. function TNNTPComponent.PerformBlindNNTPCommand( TheCommand : string ) : Integer;
  377. var TheBuffer : string; { Text buffer }
  378. begin
  379.   { If command in progress send back -1 error }
  380.   if NNTPCommandInProgress then
  381.   begin
  382.     Result := -1;
  383.     exit;
  384.   end;
  385.   { Set status variable }
  386.   NNTPCommandInProgress := True;
  387.   { Set global error code }
  388.   GlobalErrorCode := 0;
  389.   { Format output string }
  390.   TheBuffer := TheCommand;
  391.   { Preset failure code }
  392.   Result := TCPIP_STATUS_FATAL_ERROR;
  393.   { If invalid socket or no connection abort }
  394.   if ( Socket1.TheSocket = INVALID_SOCKET ) or not Connection_Established then
  395.    exit;
  396.   { Send the buffer plus EOL chars }
  397.   Socket1.StringData := TheBuffer + #13#10;
  398.   { if abort due to timeout or other error exit }
  399.   if (( GlobalAbortedFlag ) or ( GlobalErrorCode <> 0 )) then exit;
  400.   { Otherwise return preliminary code }
  401.   Result := TCPIP_STATUS_PRELIMINARY;
  402. end;
  403.  
  404. { This function gets up to 255 chars of data plus a return code from FTP serv }
  405. function TNNTPComponent.GetNNTPServerResponse(
  406.           var ResponseString : String ) : integer;
  407. var
  408.   { Buffer string for response line }
  409.   TheBuffer     : string;
  410.   { Pointer to the response string }
  411.   BufferPointer : array[0..255] of char absolute TheBuffer;
  412.   { Character to check for response code }
  413.   ResponseChar   : char;
  414.   { Pointers into returned string }
  415.   TheIndex ,
  416.   TheLength     : integer;
  417.   { Control variable }
  418.   LeftoversInPan ,
  419.   Finished      : Boolean;
  420. begin
  421.   { Preset fatal error }
  422.   Result := TCPIP_STATUS_FATAL_ERROR;
  423.   { Start loop control }
  424.   LeftoversInPan := false;
  425.   Finished := false;
  426.   repeat
  427.     { Do a peek }
  428.     TheBuffer := Socket1.PeekData;
  429.     { If timeout or other error exit }
  430.     if (( GlobalAbortedFlag ) or ( GlobalErrorCode <> 0 )) then exit;
  431.     { Find end of line character }
  432.     TheIndex := Pos( #10 , TheBuffer );
  433.     if TheIndex = 0 then
  434.     begin
  435.       TheIndex := Pos( #13 , TheBuffer );
  436.       if TheIndex = 0 then
  437.       begin
  438.         TheIndex := Pos( #0 , TheBuffer );
  439.         if TheIndex = 0 then
  440.         begin
  441.           TheIndex := Length( TheBuffer );
  442.           LeftoversInPan := True;
  443.           LeftoverText := LeftoverText + TheBuffer;
  444.           LeftoversOnTable := false;
  445.         end;
  446.       end;
  447.     end;
  448.     { If an end of line then process the line }
  449.     if TheIndex > 0 then
  450.     begin
  451.       { Get length of string }
  452.       TheLength := TheIndex;
  453.       { Receive actual data }
  454.       Socket1.CCSockReceive( Socket1.TheSocket   ,
  455.                              @BufferPointer[ 1 ] ,
  456.                              TheLength              );
  457.       { Abort if timeout or error }
  458.       if (( GlobalAbortedFlag ) or ( GlobalErrorCode <> 0 )) then exit;
  459.       { Put in the length byte }
  460.       BufferPointer[ 0 ] := Chr( TheLength );
  461.       if LeftOversOnTable then
  462.       begin
  463.         LeftOversOnTable := false;
  464.         ResponseString := LeftoverText + TheBuffer;
  465.         TheBuffer := ResponseString;
  466.         LeftoverText := '';
  467.       end;
  468.       if LeftoversInPan then
  469.       begin
  470.         LeftoversInPan := false;
  471.         LeftoversOnTable := true;
  472.       end;
  473.       { Get first number character }
  474.       ResponseChar := TheBuffer[ 1 ];
  475.       { Get the value of the number from 1 to 5 }
  476.       if (( ResponseChar >= '1' ) and ( ResponseChar <= '5' )) then
  477.       begin
  478.         Finished := true;
  479.         Result := Ord( ResponseChar ) - 48;
  480.       end;
  481.     end
  482.     else
  483.     begin
  484.     end;
  485.   until ( Finished and ( not LeftoversOnTable ));
  486.   { Return buffer as response string }
  487.   ResponseString := TheBuffer;
  488. end;
  489.  
  490. { Boilerplate error routine }
  491. procedure TNNTPComponent.NNTPSocketsErrorOccurred( Sender     : TObject;
  492.                                                  ErrorCode  : Integer;
  493.                                                  TheMessage : String   );
  494. begin
  495.   CCInetCCForm.SocketsErrorOccurred( Sender,ErrorCode,TheMessage );
  496. end;
  497.  
  498. { This is the FTP components initial connection routine }
  499. function TNNTPComponent.EstablishConnection(
  500.           PCRPointer : PConnectionsRecord ) : Boolean;
  501. var TheReturnString : String;  { Internal string holder }
  502.     TheResult       : Integer; { Internal int holder    }
  503. begin
  504.   { Set default FTP Port value }
  505.   Socket1.PortName := '119';
  506.   { Get the ip address from the record }
  507.   Socket1.IPAddressName := PCRPointer^.CIPAddress;
  508.   { Set blocking mode }
  509.   Socket1.AsynchMode := False;
  510.   { Clear condition variables }
  511.   GlobalErrorCode := 0;
  512.   GlobalAbortedFlag := false;
  513.   { Actually attempt to connect }
  514.   Socket1.CCSockConnect;
  515.   { Check if connected }
  516.   if (( GlobalAbortedFlag ) or ( GlobalErrorCode <> 0 ) or
  517.       ( Socket1.TheSocket = INVALID_SOCKET )) then
  518.   begin { Didn't connect; signal error and abort }
  519.     { Do clever C formatting trick }
  520.     TheReturnString :=
  521.      DoCStyleFormat( 'NNTP Host %s Connection Failed!' ,
  522.       [ PCRPointer^.CIPAddress ] );
  523.     { Put result in progress and status line }
  524.     AddProgressText( TheReturnString );
  525.     ShowProgressErrorText( TheReturnString );
  526.     { Signal error }
  527.     Result := False;
  528.     { leave }
  529.     exit;
  530.   end
  531.   else
  532.   begin
  533.     Connection_Established := true;
  534.     { Signal successful connection }
  535.     TheReturnString := DoCStyleFormat(
  536.       'Connected on Local port: %s with IP: %s',
  537.       [ Socket1.GetSocketPort( Socket1.TheSocket ),
  538.         Socket1.GetSocketIPAddress( Socket1.TheSocket )]);
  539.     { Put result in progress and status line }
  540.     CCINetCCForm.AddProgressText( TheReturnString );
  541.     CCINetCCForm.ShowProgressText( TheReturnString );
  542.     TheReturnString := DoCStyleFormat(
  543.      'Connected to Remote port: %s with IP: %s',
  544.       [ Socket1.GetSocketPeerPort( Socket1.TheSocket ),
  545.         Socket1.GetSocketPeerIPAddress( Socket1.TheSocket )]);
  546.     { Put result in progress and status line }
  547.     CCINetCCForm.AddProgressText( TheReturnString );
  548.     CCINetCCForm.ShowProgressText( TheReturnString );
  549.     TheReturnString := DoCStyleFormat( 'Successfully connected to %s',
  550.      [ Socket1.IPAddressName ]);
  551.     { Put result in progress and status line }
  552.     CCINetCCForm.AddProgressText( TheReturnString );
  553.     CCINetCCForm.ShowProgressText( TheReturnString );
  554.     repeat
  555.       TheResult := GetNNTPServerResponse( TheReturnString );
  556.       { Put result in progress and status line }
  557.       AddProgressText( TheReturnString );
  558.       ShowProgressText( TheReturnString );
  559.     until (( GlobalAbortedFlag ) or ( TheResult <> TCPIP_STATUS_PRELIMINARY ));
  560.     if ( GlobalAbortedFlag or ( TheResult <> TCPIP_STATUS_COMPLETED )) then
  561.     begin
  562.       { Do clever C formatting trick }
  563.       TheReturnString :=
  564.        DoCStyleFormat( 'NNTP Host %s Connection Failed!' ,
  565.         [ PCRPointer^.CIPAddress ] );
  566.       { Put result in progress and status line }
  567.       AddProgressText( TheReturnString );
  568.       ShowProgressErrorText( TheReturnString );
  569.       { Signal error }
  570.       Result := False;
  571.       { leave }
  572.       exit;
  573.     end
  574.     else Result := true; { Signal no problem }
  575.   end;
  576. end;
  577.  
  578. { This is the FTP component constructor; it creates 2 sockets }
  579. constructor TNNTPComponent.Create( AOwner : TComponent );
  580. begin
  581.   { do inherited create }
  582.   inherited Create( AOwner );
  583.   { Create socket, put in their parent, and error procs }
  584.   Socket1 := TCCSocket.Create( Self );
  585.   Socket1.Parent := Self;
  586.   Socket1.OnErrorOccurred := NNTPSocketsErrorOccurred;
  587.   { Set up booleans }
  588.   Connection_Established := false;
  589.   NNTPCommandInProgress := false;
  590. end;
  591.  
  592. { This is the FTP component destructor; it frees 2 sockets }
  593. destructor TNNTPComponent.Destroy;
  594. begin
  595.   { Free the socket }
  596.   Socket1.Free;
  597.   { and call inherited }
  598.   inherited Destroy;
  599. end;
  600.  
  601. procedure TNNTPComponent.UpdateGauge( BytesFinished , TotalToHandle : longint );
  602. begin
  603.   CCInetCCForm.UpdateGauge( BytesFinished , TotalToHandle );
  604. end;
  605.  
  606. { This sends FTP progress text to the Inet form }
  607. procedure TNNTPComponent.AddProgressText( WhatText : String );
  608. begin
  609.   CCInetCCForm.AddProgressText( WhatText );
  610. end;
  611.  
  612. { This sends FTP progress text to the Inet form }
  613. procedure TNNTPComponent.ShowProgressText( WhatText : String );
  614. begin
  615.   CCInetCCForm.ShowProgressText( WhatText );
  616. end;
  617.  
  618. { This is the FTP components QUIT routine }
  619. function TNNTPComponent.Disconnect : Boolean;
  620. var TheReturnString : String;  { Internal string holder }
  621.     TheResult       : Integer; { Internal int holder    }
  622. begin
  623.   TheReturnString :=
  624.    DoCStyleFormat( 'QUIT' ,
  625.     [ nil ] );
  626.   { Put result in progress and status line }
  627.   AddProgressText( TheReturnString );
  628.   ShowProgressText( TheReturnString );
  629.   { Begin login sequence with user name }
  630.   PerformNNTPCommand( 'QUIT', [ nil ] );
  631.   repeat
  632.     TheResult := GetNNTPServerResponse( TheReturnString );
  633.     { Put result in progress and status line }
  634.     AddProgressText( TheReturnString );
  635.     ShowProgressText( TheReturnString );
  636.   until (( GlobalAbortedFlag ) or ( TheResult <> TCPIP_STATUS_PRELIMINARY ));
  637.   NNTPCommandInProgress := false;
  638.   if ( GlobalAbortedFlag or ( TheResult <> TCPIP_STATUS_COMPLETED )) then
  639.   begin
  640.     { Do clever C formatting trick }
  641.     TheReturnString :=
  642.      DoCStyleFormat( 'NNTP Host Connection Failed!' ,
  643.       [ nil ] );
  644.     { Put result in progress and status line }
  645.     AddProgressText( TheReturnString );
  646.     ShowProgressErrorText( TheReturnString );
  647.     { Signal error }
  648.     Result := False;
  649.     { leave }
  650.     exit;
  651.   end
  652.   else Result := true; { Signal no problem }
  653. end;
  654.  
  655. { This is a clever c-style formatting trick }
  656. function TNNTPComponent.DoCStyleFormat(
  657.                 TheText      : string;
  658.           const TheArguments : array of const ) : String;
  659. begin
  660.   Result := Format( TheText , TheArguments ) + #13#10;
  661. end;
  662.  
  663.  
  664. end.
  665.