| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318 |
- {
- $Project$
- $Workfile$
- $Revision$
- $DateUTC$
- $Id$
- This file is part of the Indy (Internet Direct) project, and is offered
- under the dual-licensing agreement described on the Indy website.
- (http://www.indyproject.org/)
- Copyright:
- (c) 1993-2005, Chad Z. Hower and the Indy Pit Crew. All rights reserved.
- }
- {
- $Log$
- }
- {
- Rev 1.29 1/15/05 2:28:28 PM RLebeau
- Added local variables to TIdReplyRFC.GetFormattedReply() to reduce the number
- of repeated string operations that were being performed.
- Updated TIdRepliesRFC.UpdateText() to ignore the TIdReply that was passed in
- when looking for a TIdReply to extract Text from.
- Rev 1.28 10/26/2004 8:43:00 PM JPMugaas
- Should be more portable with new references to TIdStrings and TIdStringList.
- Rev 1.27 6/11/2004 8:48:28 AM DSiders
- Added "Do not Localize" comments.
- Rev 1.26 18/05/2004 23:17:18 CCostelloe
- Bug fix
- Rev 1.25 5/18/04 2:39:02 PM RLebeau
- Added second constructor to TIdRepliesRFC
- Rev 1.24 5/17/04 9:50:08 AM RLebeau
- Changed TIdRepliesRFC constructor to use 'reintroduce' instead
- Rev 1.23 5/16/04 5:12:04 PM RLebeau
- Added construvtor to TIdRepliesRFC class
- Rev 1.22 2004.03.01 5:12:36 PM czhower
- -Bug fix for shutdown of servers when connections still existed (AV)
- -Implicit HELP support in CMDserver
- -Several command handler bugs
- -Additional command handler functionality.
- Rev 1.21 2004.02.29 8:17:20 PM czhower
- Minor cosmetic changes to code.
- Rev 1.20 2004.02.03 4:16:50 PM czhower
- For unit name changes.
- Rev 1.19 1/3/2004 8:06:18 PM JPMugaas
- Bug fix: Sometimes, replies will appear twice due to the way functionality
- was enherited.
- Rev 1.18 2003.10.18 9:33:28 PM czhower
- Boatload of bug fixes to command handlers.
- Rev 1.17 9/20/2003 10:01:04 AM JPMugaas
- Minor change. WIll now accept all 3 digit numbers (not just ones below 600).
- The reason is that developers may want something in 600-999 range. RFC 2228
- defines a 6xx reply range for protected replies.
- Rev 1.16 2003.09.20 10:33:14 AM czhower
- Bug fix to allow clearing code field (Return to default value)
- Rev 1.15 2003.06.05 10:08:52 AM czhower
- Extended reply mechanisms to the exception handling. Only base and RFC
- completed, handing off to J Peter.
- Rev 1.14 6/3/2003 04:09:30 PM JPMugaas
- class function TIdReplyRFC.IsEndMarker(const ALine: string): Boolean had the
- wrong parameters causing FTP to freeze. It probably effected other stuff.
- Rev 1.13 5/30/2003 8:37:42 PM BGooijen
- Changed virtual to override
- Rev 1.12 2003.05.30 10:25:58 PM czhower
- Implemented IsEndMarker
- Rev 1.11 2003.05.30 10:06:08 PM czhower
- Changed code property mechanisms.
- Rev 1.10 2003.05.26 10:48:12 PM czhower
- 1) Removed deprecated code.
- 2) Removed POP3 bastardizations as they are now in IdReplyPOP3.
- Rev 1.9 5/26/2003 12:19:52 PM JPMugaas
- Rev 1.8 2003.05.26 11:38:20 AM czhower
- Rev 1.7 5/25/2003 03:16:54 AM JPMugaas
- Rev 1.6 2003.05.25 10:23:46 AM czhower
- Rev 1.5 5/21/2003 08:43:38 PM JPMugaas
- Overridable hook for the SMTP Reply object.
- Rev 1.4 5/20/2003 12:43:48 AM BGooijen
- changeable reply types
- Rev 1.3 5/19/2003 12:26:50 PM JPMugaas
- Now uses base class.
- Rev 1.2 11/05/2003 23:29:04 CCostelloe
- IMAP-specific code moved up to TIdIMAP4.pas
- Rev 1.1 11/14/2002 02:51:54 PM JPMugaas
- Added FormatType property. If it is rfIndentMidLines, it will accept
- properly parse reply lines that begin with a space. Setting this to
- rfIndentMidLines will also cause the reply object to generate lines that
- start with a space if the Text.Line starts with a space. This should
- accommodate the FTP MLSD and FEAT commands on both the client and server.
- Rev 1.0 11/13/2002 08:45:50 AM JPMugaas
- }
- unit IdReplyRFC;
- interface
- {$I IdCompilerDefines.inc}
- uses
- Classes,
- IdReply;
- type
- TIdReplyRFC = class(TIdReply)
- protected
- procedure AssignTo(ADest: TPersistent); override;
- function CheckIfCodeIsValid(const ACode: string): Boolean; override;
- function GetFormattedReply: TStrings; override;
- procedure SetFormattedReply(const AValue: TStrings); override;
- public
- class function IsEndMarker(const ALine: string): Boolean; override;
- procedure RaiseReplyError; override;
- function ReplyExists: Boolean; override;
- end;
- TIdRepliesRFC = class(TIdReplies)
- public
- constructor Create(AOwner: TPersistent); reintroduce; overload; virtual;
- constructor Create(AOwner: TPersistent; const AReplyClass: TIdReplyClass); overload; override;
- procedure UpdateText(AReply: TIdReply); override;
- end;
- // This exception is for protocol errors such as 404 HTTP error and also
- // SendCmd / GetResponse
- EIdReplyRFCError = class(EIdReplyError)
- protected
- FErrorCode: Integer;
- public
- // Params must be in this order to avoid conflict with CreateHelp
- // constructor in CBuilder as CB does not differentiate constructors
- // by name as Delphi does
- constructor CreateError(const AErrorCode: Integer;
- const AReplyMessage: string); reintroduce; virtual;
- //
- property ErrorCode: Integer read FErrorCode;
- end;
- implementation
- uses
- IdGlobal,
- SysUtils;
- { TIdReplyRFC }
- procedure TIdReplyRFC.AssignTo(ADest: TPersistent);
- var
- LR: TIdReplyRFC;
- begin
- if ADest is TIdReplyRFC then begin
- LR := TIdReplyRFC(ADest);
- //set code first as it possibly clears the reply
- LR.NumericCode := NumericCode;
- LR.Text.Assign(Text);
- end else begin
- inherited AssignTo(ADest);
- end;
- end;
- function TIdReplyRFC.CheckIfCodeIsValid(const ACode: string): Boolean;
- var
- LCode: Integer;
- begin
- LCode := IndyStrToInt(ACode, 0);
- {Replaced 600 with 999 because some developers may want 6xx, 7xx, and 8xx reply
- codes for their protocols. It also turns out that RFC 2228 defines 6xx reply codes.
- From RFC 2228
- A new class of reply types (6yz) is also introduced for protected
- replies.
- }
- Result := ((LCode >= 100) and (LCode < 1000)) or (Trim(ACode) = '');
- end;
- function TIdReplyRFC.GetFormattedReply: TStrings;
- var
- I, LCode: Integer;
- LCodeStr: String;
- begin
- Result := GetFormattedReplyStrings;
- LCode := NumericCode;
- if LCode > 0 then begin
- LCodeStr := IntToStr(LCode);
- if Text.Count > 0 then begin
- for I := 0 to Text.Count - 1 do begin
- if I < Text.Count - 1 then begin
- Result.Add(LCodeStr + '-' + Text[I]);
- end else begin
- Result.Add(LCodeStr + ' ' + Text[I]);
- end;
- end;
- end else begin
- Result.Add(LCodeStr);
- end;
- end else if FText.Count > 0 then begin
- Result.AddStrings(FText);
- end;
- end;
- class function TIdReplyRFC.IsEndMarker(const ALine: string): Boolean;
- begin
- if Length(ALine) >= 4 then begin
- Result := ALine[4] = ' ';
- end else begin
- Result := True;
- end;
- end;
- procedure RaiseRFCError(ANumericCode: Integer; const AText: string);
- {$IFDEF USE_NORETURN}noreturn;{$ENDIF}
- begin
- raise EIdReplyRFCError.CreateError(ANumericCode, AText);
- end;
- procedure TIdReplyRFC.RaiseReplyError;
- begin
- RaiseRFCError(NumericCode, Text.Text);
- end;
- function TIdReplyRFC.ReplyExists: Boolean;
- begin
- Result := (NumericCode > 0) or (FText.Count > 0);
- end;
- procedure TIdReplyRFC.SetFormattedReply(const AValue: TStrings);
- // Just parse and put in items, no need to store after parse
- var
- i: Integer;
- s: string;
- begin
- Clear;
- if AValue.Count > 0 then begin
- s := Trim(Copy(AValue[0], 1, 3));
- Code := s;
- for i := 0 to AValue.Count - 1 do begin
- Text.Add(Copy(AValue[i], 5, MaxInt));
- end;
- end;
- end;
- { EIdReplyRFCError }
- constructor EIdReplyRFCError.CreateError(const AErrorCode: Integer;
- const AReplyMessage: string);
- begin
- inherited Create(AReplyMessage);
- FErrorCode := AErrorCode;
- end;
- { TIdReplies }
- constructor TIdRepliesRFC.Create(AOwner: TPersistent);
- begin
- inherited Create(AOwner, TIdReplyRFC);
- end;
- constructor TIdRepliesRFC.Create(AOwner: TPersistent; const AReplyClass: TIdReplyClass);
- begin
- inherited Create(AOwner, AReplyClass);
- end;
- procedure TIdRepliesRFC.UpdateText(AReply: TIdReply);
- var
- LGenericNumCode: Integer;
- LReply: TIdReply;
- begin
- inherited UpdateText(AReply);
- // If text is still blank after inherited see if we can find a generic version
- if AReply.Text.Count = 0 then begin
- LGenericNumCode := (AReply.NumericCode div 100) * 100;
- // RLebeau - in cases where the AReply.Code is the same as the
- // generic code, ignore the AReply as it doesn't have any text
- // to assign, or else the code wouldn't be this far
- LReply := Find(IntToStr(LGenericNumCode), AReply);
- if LReply = nil then begin
- // If no generic was found, then use defaults.
- case LGenericNumCode of
- 100: AReply.Text.Text := 'Information'; {do not localize}
- 200: AReply.Text.Text := 'Ok'; {do not localize}
- 300: AReply.Text.Text := 'Temporary Error'; {do not localize}
- 400: AReply.Text.Text := 'Permanent Error'; {do not localize}
- 500: AReply.Text.Text := 'Unknown Internal Error'; {do not localize}
- end;
- end else begin
- AReply.Text.Assign(LReply.Text);
- end;
- end;
- end;
- end.
|