⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 idsaslcollection.pas

📁 photo.163.com 相册下载器 多线程下载
💻 PAS
字号:
{ $HDR$}
{**********************************************************************}
{ Unit archived using Team Coherence                                   }
{ Team Coherence is Copyright 2002 by Quality Software Components      }
{                                                                      }
{ For further information / comments, visit our WEB site at            }
{ http://www.TeamCoherence.com                                         }
{**********************************************************************}
{}
{ $Log:  55713: IdSASLCollection.pas
{
{   Rev 1.3    10/26/2004 10:55:32 PM  JPMugaas
{ Updated refs.
}
{
    Rev 1.2    6/11/2004 9:38:38 AM  DSiders
  Added "Do not Localize" comments.
}
{
{   Rev 1.1    2004.02.03 5:45:50 PM  czhower
{ Name changes
}
{
{   Rev 1.0    1/25/2004 3:09:54 PM  JPMugaas
{ New collection class for SASL mechanism processing.
}
unit IdSASLCollection;

interface
uses
  Classes, IdBaseComponent, IdSASL, IdTCPConnection, IdException,
  IdTStrings;

type
  TIdSASLListEntry = class(TCollectionItem)
  protected
    FSASL : TIdSASL;
  public
    procedure Assign(Source: TPersistent); override;
  published
    property SASL : TIdSASL read FSASL write FSASL;
  end;
  TIdSASLEntries = class ( TOwnedCollection )
  protected
    function GetItem ( Index: Integer ) : TIdSASLListEntry;
    procedure SetItem ( Index: Integer; const Value: TIdSASLListEntry );
  public
    constructor Create ( AOwner : TPersistent ); reintroduce;
    function Add: TIdSASLListEntry;
    function LoginSASL(const ACmd: String;
      const AOkReplies, AContinueRplies: array of string;
      AClient : TIdTCPConnection;
      ACapaReply : TIdStrings;
      const AAuthString : String = 'AUTH'): Boolean;      {Do not Localize}
    function ParseCapaReply(ACapaReply: TIdStrings;
      const AAuthString: String = 'AUTH') : TIdStrings; {do not localize}
    function Insert(Index: Integer): TIdSASLListEntry;
    procedure RemoveByComp(AComponent : TComponent);
    function IndexOfComp(AItem : TIdSASL): Integer;
    property Items [ Index: Integer ] : TIdSASLListEntry read GetItem write
      SetItem; default;
  end;

  EIdSASLException = class(EIdException);
  EIdEmptySASLList = class(EIdSASLException);
  EIdSASLNotSupported = class(EIdSASLException);
  EIdSASLMechNeeded = class(EIdSASLException);
  // for use in implementing components
  TAuthenticationType = (atNone, atUserPass, atAPOP, atSASL);
  TAuthenticationTypes = set of TAuthenticationType;
  EIdSASLMsg = class(EIdException);
  EIdSASLNotValidForProtocol = class(EIdSASLMsg);

implementation

uses
  IdCoderMIME,
  IdGlobal,
  IdGlobalProtocols,
  SysUtils;

{ TIdSASLListEntry }

procedure TIdSASLListEntry.Assign(Source: TPersistent);
begin
  if Source is TIdSASLListEntry then
  begin
    FSASL := TIdSASLListEntry(Source).SASL;
  end
  else
  begin
    inherited;
  end;
end;

{ TIdSASLEntries }

function TIdSASLEntries.Add: TIdSASLListEntry;
begin
  Result := TIdSASLListEntry ( inherited Add );
end;

constructor TIdSASLEntries.Create(AOwner: TPersistent);
begin
   inherited Create ( AOwner, TIdSASLListEntry );
end;

function TIdSASLEntries.GetItem(Index: Integer): TIdSASLListEntry;
begin
  Result := TIdSASLListEntry ( inherited Items [ Index ] );
end;

function TIdSASLEntries.IndexOfComp(AItem: TIdSASL): Integer;
begin
  for Result := 0 to Count -1 do
  begin
    if Items[Result].FSASL = AItem then
    begin
      Exit;
    end;
  end;
  Result := -1;
end;

function TIdSASLEntries.Insert(Index: Integer): TIdSASLListEntry;
begin
  Result := Inherited Insert(Index) as TIdSASLListEntry;
end;

function TIdSASLEntries.LoginSASL(const ACmd: String; const AOkReplies,
  AContinueRplies: array of string; AClient: TIdTCPConnection;
  ACapaReply: TIdStrings; const AAuthString: String): Boolean;
var i : Integer;
  LSASLMechanisms: TIdSASLEntries;
  LE : TIdEncoderMIME;
  LD : TIdDecoderMIME;
  LSupportedSASL : TIdStrings;
  LS : TIdSASLListEntry;

  function CheckStrFail(const AStr : String; const AOk, ACont: array of string) : Boolean;
  begin
    Result := ( PosInStrArray (AStr,AOk)=-1) and
          (PosInStrArray(AStr,ACont)=-1)
  end;

begin
//  if (AuthenticationType = atSASL) and ((SASLMechanisms=nil) or (SASLMechanisms.Count = 0)) then begin
//    raise EIdSASLMechNeeded.Create(RSASLRequired);
//  end;
  Result := False;

    LSASLMechanisms := TIdSASLEntries.Create(nil);
    LE := TIdEncoderMIME.Create(nil);
    LD := TIdDecoderMIME.Create(nil);
    try
      LSupportedSASL := ParseCapaReply(ACapaReply);
      //create a list of supported mechanisms we also support
      for i := Count - 1 downto 0 do begin
        if Assigned(Items[i].FSASL) then
        begin
          if LSupportedSASL.IndexOf(Items[i].FSASL.ServiceName) >= 0 then begin
            LS := LSASLMechanisms.Add;
            LS.SASL.Assign(Items[i].SASL);
          end;
        end;
      end;
      //now do it
      for i := 0 to LSASLMechanisms.Count - 1 do begin
        AClient.SendCmd(ACmd+' '+LSASLMechanisms.Items[i].SASL.ServiceName,[]);//[334, 504]);
        if CheckStrFail(AClient.LastCmdResult.Code,AOkReplies,AContinueRplies) then begin
          break; // this mechanism is not supported, skip to the next
        end else begin
          if (PosInStrArray(AClient.LastCmdResult.Code,AOkReplies)>-1) then begin
            Result := True;
            break; // we've authenticated successfully :)
          end;
        end;
        AClient.SendCmd(LE.Encode(LSASLMechanisms.Items[i].SASL.StartAuthenticate(
          LD.DecodeString(TrimRight(AClient.LastCmdResult.Text.Text))
        )));
        if CheckStrFail(AClient.LastCmdResult.Code,AOkReplies,AContinueRplies) then
        begin
          AClient.RaiseExceptionForLastCmdResult;
        end;
        while PosInStrArray(AClient.LastCmdResult.Code,AContinueRplies)>-1 do begin
          AClient.SendCmd( LE.Encode(LSASLMechanisms.Items[i].SASL.ContinueAuthenticate(
            LD.DecodeString(TrimRight(AClient.LastCmdResult.Text.Text))
          )));
          if CheckStrFail(AClient.LastCmdResult.Code,AOkReplies,AContinueRplies) then
          begin
            AClient.RaiseExceptionForLastCmdResult;
          end;
        end;
        if PosInStrArray(AClient.LastCmdResult.Code,AOkReplies)>-1 then begin
          Result := True;
          break; // we've authenticated successfully :)
        end;
      end;
    finally
      FreeAndNil(LSupportedSASL);
      FreeAndNil(LSASLMechanisms);
      FreeAndNil(LE);
      FreeAndNil(LD);
    end;
end;

function TIdSASLEntries.ParseCapaReply(ACapaReply: TIdStrings;
  const AAuthString: String = 'AUTH'): TIdStrings; {do not localize}
var
  i: Integer;
  s: string;
  LEntry : String;

begin
  Result := TIdStringList.Create;
  for i := 0 to ACapaReply.Count - 1 do begin
    s := UpperCase(ACapaReply[i]);
    if TextIsSame(Copy(s, 1, Length(AAuthString)+1), AAuthString+' ') or TextIsSame(Copy(s, 1, Length(AAuthString)+1), AAuthString+'=') then begin    {Do not Localize}
      s := Copy(s, Length(AAuthString)+1, MaxInt);
      while Length(s) > 0 do begin
        s := StringReplace(s, '=', ' ', [rfReplaceAll]);    {Do not Localize}
        LEntry := Fetch(s, ' ');    {Do not Localize}
        if LEntry<>'' then
        begin
          if Result.IndexOf(LEntry) = -1 then begin
            Result.Add(LEntry);
          end;
        end;
      end;
    end;
  end;
end;

procedure TIdSASLEntries.RemoveByComp(AComponent: TComponent);
var i : Integer;
begin
  for i := Self.Count-1 downto 0 do
  begin
    if Items[i].FSASL = AComponent then
    begin
      Delete(i);
    end;
  end;
end;

procedure TIdSASLEntries.SetItem(Index: Integer;
  const Value: TIdSASLListEntry);
begin
  inherited SetItem ( Index, Value );
end;

end.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -