Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- unit EvilIrc;
- interface
- uses
- Windows, Classes, SysUtils,
- EvilStrings, EvilWinUtils, EvilClasses, EvilTCPSocket;
- const
- CWHO: string = 'WHO';
- CTIME: string = 'TIME';
- CPASS: string = 'PASS';
- CNICK: string = 'NICK';
- CUSER: string = 'USER';
- CPING: string = 'PING';
- CPONG: string = 'PONG';
- CJOIN: string = 'JOIN';
- CPART: string = 'PART';
- CKICK: string = 'KICK';
- CMODE: string = 'MODE';
- CQUIT: string = 'QUIT';
- CKILL: string = 'KILL';
- CTOPIC: string = 'TOPIC';
- CNAMES: string = 'NAMES';
- CERROR: string = 'ERROR';
- CINVITE: string = 'INVITE';
- CNOTICE: string = 'NOTICE';
- CACTION: string = 'ACTION';
- CFINGER: string = 'FINGER';
- CVERSION: string = 'VERSION';
- CWALLOPS: string = 'WALLOPS';
- CPRIVMSG: string = 'PRIVMSG';
- CBold: char = #$02;
- CColor: char = #$03;
- COrdinary: char = #$0F;
- CReverse: char = #$16;
- CItalic: char = #$1D;
- CUnderline: char = #$1F;
- type
- { Forward declarations }
- TIrc = class;
- { TIrcMsgParser }
- TIrcMsgParser = class
- strict private
- type
- TSourceType = (stServer, stUser, stNotPresent);
- TWordMarker = record
- Start: word;
- Length: word;
- end;
- strict private
- FRaw : string; { Parsed IRC command }
- FSourceType : TSourceType;
- FSource : TWordMarker;
- FSourceNickName: TWordMarker;
- FSourceUserName: TWordMarker;
- FSourceHostName: TWordMarker;
- FCommand : TWordMarker;
- FParams : TWordMarker;
- FParamsArray : array of TWordMarker;
- FParamCount : integer;
- FTrailings : TWordMarker;
- FTrailingsArray: array of TWordMarker;
- FTrailingCount : integer;
- function GetParam(aIndex: integer): string;
- function GetTrailing(aIndex: integer): string;
- private
- procedure AddParam(const aStart, aLength: integer);
- procedure AddTrailing(const aStart, aLength: integer);
- procedure Clear;
- public
- constructor Create;
- destructor Destroy; override;
- function Parse(const aRaw: string): boolean; { Parses a RAW IRC message }
- property Raw: string read FRaw; { Returns the last RAW passed to Parse(); }
- property SourceType: TSourceType read FSourceType; { Type of message source prefix. }
- function Source: string; { Returns the message source, if present; Client or server that sent the message. }
- function SourceNickName: string; { Returns NickName from Source if Source is a Client, full source string otherwise }
- function SourceUserName: string; { Returns UserName from Source if Source is a Client, full source string otherwise }
- function SourceHostName: string; { Returns HostName from Source if Source is a Client, full source string otherwise }
- function Command: string; { Returns IRC Command that was parsed from RAW }
- property Param[aIndex: integer]: string read GetParam; { Array of parsed Parameters. This excludes trailing Parameters }
- property ParamCount: integer read FParamCount; { Number of parsed Parameters. }
- function Params: string; { Returns all Parameters as a single string }
- function ParamsFrom(const aIndex: integer): string; { Returns parameters from and including token at aIndex. }
- property Trailing[aIndex: integer]: string read GetTrailing; { Array of parsed trailing Parameters. }
- property TrailingCount: integer read FTrailingCount; { Number of parsed trailing Parameters. }
- function Trailings: string; { Returns all trailing Parameters as a single string }
- function TrailingsFrom(const aIndex: integer): string; { Returns trailing parameters from and including token at aIndex. }
- function AllParams: string; { Returns all middle and trailing params as a single string. }
- end;
- { TIrcChannel }
- TIrcChannel = class(TPersistent)
- end;
- { TIrcNickname }
- TIrcNickname = class(TPersistent)
- private
- FNickname: string;
- FUsername: string;
- FRealname: string;
- FHostname: string;
- procedure SetNickname(const Value: string);
- procedure SetRealName(const Value: string);
- procedure SetUsername(const Value: string);
- procedure SetHostname(const Value: string);
- public
- function GetHostMask: string; overload;
- function GetHostMask(const aType: byte): string; overload;
- published
- property Nickname: string read FNickname write SetNickname;
- property Username: string read FUsername write SetUsername;
- property Realname: string read FRealname write SetRealName;
- property Hostname: string read FHostname write SetHostname;
- end;
- { TInternalAddressList }
- TInternalAddressList = class(TPersistent)
- private
- FOwner : TIrc;
- FEnabled: boolean;
- procedure SetEnabled(const Value: boolean);
- function GetIrcChannel(const aIndex: integer): TIrcChannel;
- function GetChannelCount: integer;
- function GetNickname(const aIndex: integer): TIrcNickname;
- function GetNicknameCount: integer;
- procedure SetIrcChannel(const aIndex: integer; const Value: TIrcChannel);
- procedure SetNickname(const aIndex: integer; const Value: TIrcNickname);
- protected
- public
- constructor Create(aIrc: TIrc);
- destructor Destroy; override;
- public
- property Channels[const aIndex: integer]: TIrcChannel read GetIrcChannel write SetIrcChannel;
- property ChannelCount : integer read GetChannelCount;
- property Nicknames[const aIndex: integer]: TIrcNickname read GetNickname write SetNickname;
- property NicknameCount : integer read GetNicknameCount;
- published
- property Enabled: boolean read FEnabled write SetEnabled default True;
- end;
- { Events }
- TOnIrcEvent = procedure(aClient: TIrc) of object;
- TOnIrcTextEvent = procedure(aClient: TIrc; const aText: string) of object;
- TOnIrcRaw = procedure(aClient: TIrc; const aCmd: string; aIn: boolean; var aBlockIt: boolean) of object;
- TOnIrcJoin = procedure(aClient: TIrc; const aNick, aHost, aChannel: string) of object;
- TOnIrcPart = procedure(aClient: TIrc; const aNick, aHost, aChannel, aReason: string) of object;
- TOnIrcKick = procedure(aClient: TIrc; const aKicker, aKicked, aChannel, aReason: string) of object;
- TOnIrcKill = procedure(aClient: TIrc; const aKiller, aKilled, aReason: string) of object;
- TOnIrcQuit = procedure(aClient: TIrc; const aNick, aHost, aReason: string) of object;
- TOnIrcPrivMsg = procedure(aClient: TIrc; const aFromNick, aFromHost, aTarget, aText: string) of object;
- TOnIrcServerNotice = procedure(aClient: TIrc; const aSource, aText: string) of object;
- TOnIrcCTCP = procedure(aClient: TIrc; const aFromNick, aFromHost, aTarget, aCommand, aParameters: string) of object;
- TOnNick = procedure(aClient: TIrc; const aOldNick, aNewNick, aHost: string) of object;
- TOnMode = procedure(aClient: TIrc; const aSource, aTarget, aMode: string) of object;
- TOnIrcStatus = procedure(aClient: TIrc; const aStatus: string) of object;
- TOnIrcError = procedure(aClient: TIrc; const aError: string) of object;
- { TIrc }
- TIrc = class(TCustomTCPSocket)
- private
- FNickname : string;
- FRealname : string;
- FUsername : string;
- FPassword : string;
- FAltNicknames : TStrings;
- FUserMode : string;
- FRejoinWhenKicked : boolean;
- FReconnectWhenKilled: boolean;
- private
- FIAL: TInternalAddressList;
- private
- FOnRaw : TOnIrcRaw;
- FOnServerWelcome: TOnIrcEvent;
- FOnCTCP : TOnIrcCTCP;
- FOnJoin : TOnIrcJoin;
- FOnPrivMsg : TOnIrcPrivMsg;
- FOnNotice : TOnIrcPrivMsg;
- FOnQuit : TOnIrcQuit;
- FOnPart : TOnIrcPart;
- FOnKick : TOnIrcKick;
- FOnNick : TOnNick;
- FOnKill : TOnIrcKill;
- FOnServerNotice : TOnIrcServerNotice;
- FOnMode : TOnMode;
- procedure SetNickname(const Value: string);
- procedure SetRealname(const Value: string);
- procedure SetUsername(const Value: string);
- procedure SetPassword(const Value: string);
- procedure SetAltNicknames(const Value: TStrings);
- procedure SetUserMode(const Value: string);
- procedure SetRejoinWhenKicked(const Value: boolean);
- procedure SetReconnectWhenKilled(const Value: boolean);
- protected
- FTokenizer : TTokenizer;
- FParser : TIrcMsgParser;
- FIncompleteCmd: string; { Stores an incomplete command text in case of incomplete socket receive. }
- procedure EventConnect(const aError: word); override;
- procedure EventClose(const aError: word; const aClosedByRemote: boolean); override;
- procedure EventRead(const aError: word); override;
- procedure ParseCommand(const aLine: string);
- procedure Handle_PING;
- procedure Handle_JOIN;
- procedure Handle_PART;
- procedure Handle_KICK;
- procedure Handle_QUIT;
- procedure Handle_KILL;
- procedure Handle_NICK;
- procedure Handle_MODE;
- procedure Handle_PRIVMSG;
- procedure Handle_NOTICE;
- procedure Handle_INVITE;
- procedure Handle_WALLOPS;
- procedure Handle_ERROR;
- procedure Handle_319_RPL_WHOISCHANNELS;
- procedure Handle_322_RPL_LIST;
- procedure Handle_352_RPL_WHOREPLY;
- procedure Handle_353_RPL_NAMEREPLY;
- procedure Handle_333;
- procedure Handle_Numeric(const aCode: integer);
- public
- constructor Create(aOwner: TComponent); override;
- destructor Destroy; override;
- procedure Assign(aSource: TPersistent); override;
- procedure Raw(const aText: string); { Sends raw text, terminates with CRLF. }
- procedure Cmd_Join(const aChannel: string; const aKey: string = CEmpty);
- procedure Cmd_Part(const aChannel: string; const aPartMsg: string = CEmpty);
- procedure Cmd_Msg(const aTarget, aMessage: string);
- procedure Cmd_Nick(const aNewNickname: string);
- published
- property AddressFamily;
- property SocketState;
- property ReceiveBufferSize;
- property BindHost;
- property BindPort;
- property RemoteHost;
- property RemotePort;
- property ProxyHost;
- property ProxyPort;
- property ProxyType;
- property SSLType;
- property SSLPrivateKeyFile;
- property SSLCertificateChainFile;
- property SSLTrustedAuthoritiesFile;
- property SSLVerifyCertificate;
- property ConnectTimeout;
- property ConnectRetryDelay;
- property ConnectRetryCount;
- property ReconnectOnError;
- property ReconnectOnClose;
- property Nickname : string read FNickname write SetNickname;
- property Username : string read FUsername write SetUsername;
- property Realname : string read FRealname write SetRealname;
- property Password : string read FPassword write SetPassword;
- property UserMode : string read FUserMode write SetUserMode;
- property AltNicknames: TStrings read FAltNicknames write SetAltNicknames;
- property IAL: TInternalAddressList read FIAL;
- property RejoinWhenKicked : boolean read FRejoinWhenKicked write SetRejoinWhenKicked default True;
- property ReconnectWhenKilled: boolean read FReconnectWhenKilled write SetReconnectWhenKilled default True;
- property OnResolving;
- property OnResolved;
- property OnConnecting;
- property OnConnectTimeout;
- property OnConnected;
- property OnDisconnected;
- property OnError;
- property OnRaw: TOnIrcRaw read FOnRaw write FOnRaw;
- property OnServerWelcome: TOnIrcEvent read FOnServerWelcome write FOnServerWelcome;
- property OnJoin : TOnIrcJoin read FOnJoin write FOnJoin;
- property OnPart : TOnIrcPart read FOnPart write FOnPart;
- property OnKick : TOnIrcKick read FOnKick write FOnKick;
- property OnQuit : TOnIrcQuit read FOnQuit write FOnQuit;
- property OnKill : TOnIrcKill read FOnKill write FOnKill;
- property OnPrivMsg : TOnIrcPrivMsg read FOnPrivMsg write FOnPrivMsg;
- property OnNotice : TOnIrcPrivMsg read FOnNotice write FOnNotice;
- property OnServerNotice : TOnIrcServerNotice read FOnServerNotice write FOnServerNotice;
- property OnCTCP : TOnIrcCTCP read FOnCTCP write FOnCTCP;
- property OnNick : TOnNick read FOnNick write FOnNick;
- property OnMode : TOnMode read FOnMode write FOnMode;
- end;
- implementation
- { TELIrc.TELIrcMsgParser }
- constructor TIrcMsgParser.Create;
- begin
- Clear;
- end;
- destructor TIrcMsgParser.Destroy;
- begin
- Clear;
- inherited;
- end;
- procedure TIrcMsgParser.AddParam(const aStart, aLength: integer);
- begin
- Inc(FParamCount);
- SetLength(FParamsArray, FParamCount);
- FParamsArray[FParamCount - 1].Start := aStart;
- FParamsArray[FParamCount - 1].Length := aLength;
- end;
- procedure TIrcMsgParser.AddTrailing(const aStart, aLength: integer);
- begin
- Inc(FTrailingCount);
- SetLength(FTrailingsArray, FTrailingCount);
- FTrailingsArray[FTrailingCount - 1].Start := aStart;
- FTrailingsArray[FTrailingCount - 1].Length := aLength;
- end;
- procedure TIrcMsgParser.Clear;
- begin
- FRaw := CEmpty;
- FSourceType := stNotPresent;
- FSource.Start := 0;
- FSource.Length := 0;
- FSourceNickName.Start := 0;
- FSourceNickName.Length := 0;
- FSourceUserName.Start := 0;
- FSourceUserName.Length := 0;
- FSourceHostName.Start := 0;
- FSourceHostName.Length := 0;
- FCommand.Start := 0;
- FCommand.Length := 0;
- FParams.Start := 0;
- FParams.Length := 0;
- SetLength(FParamsArray, 0);
- FParamCount := 0;
- FTrailings.Start := 0;
- FTrailings.Length := 0;
- SetLength(FTrailingsArray, 0);
- FTrailingCount := 0;
- end;
- function TIrcMsgParser.Parse(const aRaw: string): boolean;
- var
- a: integer; // Copy start/Last Copy end position.
- b: integer; // Parse cursor.
- t: integer; // Temp cursor.
- l: integer; // Length of input string.
- function DoTrim: boolean;
- begin
- Result := False;
- while (b <= l) do
- begin
- if (b > l) then
- Exit(False);
- if (FRaw[b] <= CSpace) then
- Inc(b)
- else
- begin
- a := b;
- Exit(True);
- end;
- end;
- end;
- function FindSpace: boolean;
- begin
- b := TextPos(FRaw, CSpace, True, b);
- Result := (b <> 0);
- end;
- begin
- // <message> ::=
- //
- // [':' <prefix> <SPACE> ] <command> <Trailing> <crlf>
- //
- // <prefix> ::=
- // <servername> | <nick> [ '!' <user> ] [ '@' <host> ]
- //
- // <command> ::=
- // <letter> { <letter> } | <number> <number> <number>
- //
- // <SPACE> ::=
- // ' ' { ' ' }
- //
- // <Trailing> ::=
- // <SPACE> [ ':' <Trailings> | <middle> <Trailing> ]
- //
- // <middle> ::=
- // <Any *non-empty* sequence of octets not including SPACE or NUL or CR or LF, the first of which may not be ':'>
- //
- // <Trailings> ::=
- // <Any, possibly *empty*, sequence of octets not including NUL or CR or LF>
- //
- // <crlf> ::=
- // CR LF
- { Check and initialize }
- Result := False;
- l := Length(aRaw);
- if (l = 0) then
- Exit;
- Clear;
- FRaw := aRaw;
- a := 1;
- b := 1;
- if (DoTrim = False) then
- Exit;
- { Optional Message Source Prefix. }
- if (FRaw[b] = CColon) then
- begin
- if (FindSpace = False) then
- Exit;
- Inc(a);
- FSource.Start := a;
- FSource.Length := (b - a);
- { If msg source is an user, split it to <nick>!<user>@<host>. }
- t := TextPos(FRaw, CExclam, True, a);
- if (t > 0) and (t < b) then
- begin
- FSourceNickName.Start := a;
- FSourceNickName.Length := (t - a);
- a := t;
- Inc(a);
- t := TextPos(FRaw, CMonkey, True, a);
- if (t > 0) and (t < b) then
- begin
- FSourceUserName.Start := a;
- FSourceUserName.Length := (t - a);
- a := t;
- Inc(a);
- t := TextPos(FRaw, CSpace, True, a);
- if (t = b) then
- begin
- FSourceHostName.Start := a;
- FSourceHostName.Length := (t - a);
- FSourceType := stUser;
- end;
- end;
- end
- else
- FSourceType := stServer;
- a := b;
- { Trim }
- if (DoTrim = False) then
- Exit;
- end;
- { Parse out command }
- if (FindSpace) then
- begin
- FCommand.Start := a;
- FCommand.Length := (b - a);
- a := b;
- { If no params, exit. }
- if (DoTrim = False) then
- Exit(True);
- end
- else
- begin
- { If no params, exit }
- FCommand.Start := a;
- FCommand.Length := (l - a);
- Exit(True);
- end;
- { Parse parameters }
- { If there are trailing params, parse middle first }
- t := TextPos(FRaw, CColon, True, a);
- if (t <> 0) then
- begin
- FParams.Start := a;
- FParams.Length := (t - a);
- // Get the pre-Trailings params.
- while (b < t) and (FindSpace) do
- begin
- AddParam(a, b - a);
- Inc(b);
- a := b;
- end;
- // If no space before Trailings colon..
- if (a < t) then
- AddParam(a, t - a);
- // Move cursor to start of Trailings.
- a := t + 1;
- b := a;
- end
- else
- begin
- FParams.Start := a;
- FParams.Length := (l + 1 - a);
- end;
- if (t <> 0) then
- begin
- FTrailings.Start := t + 1;
- FTrailings.Length := (l + 1 - a);
- end;
- while (FindSpace) do
- begin
- if (t <> 0) then
- AddTrailing(a, b - a)
- else
- AddParam(a, b - a);
- Inc(b);
- a := b;
- end;
- // Last chunk.
- if (b < l) then
- begin
- if (t <> 0) then
- AddTrailing(a, MaxInt)
- else
- AddParam(a, MaxInt);
- end;
- // Done.
- Result := True;
- end;
- function TIrcMsgParser.Source: string;
- begin
- if (FSource.Length = 0) then
- Result := CEmpty
- else
- Result := TextCopy(FRaw, FSource.Start, FSource.Length);
- end;
- function TIrcMsgParser.SourceNickName: string;
- begin
- if (FSourceNickName.Length = 0) then
- Result := CEmpty
- else
- Result := TextCopy(FRaw, FSourceNickName.Start, FSourceNickName.Length);
- end;
- function TIrcMsgParser.SourceUserName: string;
- begin
- if (FSourceUserName.Length = 0) then
- Result := CEmpty
- else
- Result := TextCopy(FRaw, FSourceUserName.Start, FSourceUserName.Length);
- end;
- function TIrcMsgParser.SourceHostName: string;
- begin
- if (FSourceHostName.Length = 0) then
- Result := CEmpty
- else
- Result := TextCopy(FRaw, FSourceHostName.Start, FSourceHostName.Length);
- end;
- function TIrcMsgParser.Command: string;
- begin
- if (FCommand.Length = 0) then
- Result := CEmpty
- else
- Result := TextCopy(FRaw, FCommand.Start, FCommand.Length);
- end;
- function TIrcMsgParser.Params: string;
- begin
- if (FParams.Length = 0) then
- Result := CEmpty
- else
- Result := Trim(TextCopy(FRaw, FParams.Start, FParams.Length));
- end;
- function TIrcMsgParser.ParamsFrom(const aIndex: integer): string;
- begin
- if (aIndex < 0) or (aIndex >= FParamCount) then
- Result := CEmpty
- else
- Result := TextCopy(FRaw, FParamsArray[aIndex].Start, MaxInt);
- end;
- function TIrcMsgParser.Trailings: string;
- begin
- if (FTrailings.Length = 0) then
- Result := CEmpty
- else
- Result := TextCopy(FRaw, FTrailings.Start, FTrailings.Length);
- end;
- function TIrcMsgParser.TrailingsFrom(const aIndex: integer): string;
- begin
- if (aIndex < 0) or (aIndex >= FTrailingCount) then
- Result := CEmpty
- else
- Result := TextCopy(FRaw, FTrailingsArray[aIndex].Start, MaxInt);
- end;
- function TIrcMsgParser.AllParams: string;
- begin
- if (FParams.Length > 0) then
- Result := Params
- else
- Result := CEmpty;
- if (FParams.Length > 0) then
- begin
- if (FTrailings.Length > 0) then
- Result := Result + CSpace + Trailings;
- end
- else
- begin
- if (FTrailings.Length > 0) then
- Result := Trailings;
- end;
- end;
- function TIrcMsgParser.GetParam(aIndex: integer): string;
- begin
- if (aIndex < 0) or (aIndex >= FParamCount) then
- Result := CEmpty
- else
- Result := TextCopy(FRaw, FParamsArray[aIndex].Start, FParamsArray[aIndex].Length);
- end;
- function TIrcMsgParser.GetTrailing(aIndex: integer): string;
- begin
- if (aIndex < 0) or (aIndex >= FTrailingCount) then
- Result := CEmpty
- else
- Result := TextCopy(FRaw, FTrailingsArray[aIndex].Start, FTrailingsArray[aIndex].Length);
- end;
- { TIrcNickname }
- function TIrcNickname.GetHostMask: string;
- begin
- if (FNickname = CEmpty) or (FUsername = CEmpty) or (FHostname = CEmpty) then
- Exit(CEmpty);
- Result := FNickname + CExclam + FUsername + CMonkey + FHostname;
- end;
- function TIrcNickname.GetHostMask(const aType: byte): string;
- begin
- if (FNickname = CEmpty) or (FUsername = CEmpty) or (FHostname = CEmpty) then
- Exit(CEmpty);
- case aType of
- 0:
- Result := FNickname + CExclam + CAsterisk + CMonkey + CAsterisk; // nick!*@*
- 1:
- Result := CAsterisk + CExclam + FUsername + CMonkey + CAsterisk; // *!user@*
- 2:
- Result := CAsterisk + CExclam + CAsterisk + CMonkey + FHostname; // *!*@host
- 3:
- Result := FNickname + CExclam + FUsername + CMonkey + CAsterisk; // nick!user@*
- 4:
- Result := CAsterisk + CExclam + FUsername + CMonkey + FHostname; // *!user@host
- 5:
- Result := FNickname + CExclam + CAsterisk + CMonkey + FHostname; // nick!*@host
- else
- Result := FNickname + CExclam + FUsername + CMonkey + FHostname; // nick!user@host
- end;
- end;
- procedure TIrcNickname.SetHostname(const Value: string);
- begin
- FHostname := Value;
- end;
- procedure TIrcNickname.SetNickname(const Value: string);
- begin
- FNickname := Value;
- end;
- procedure TIrcNickname.SetRealName(const Value: string);
- begin
- FRealName := Value;
- end;
- procedure TIrcNickname.SetUsername(const Value: string);
- begin
- FUsername := Value;
- end;
- { TELInternalAddressList }
- constructor TInternalAddressList.Create(aIrc: TIrc);
- begin
- FOwner := aIrc;
- FEnabled := True;
- end;
- destructor TInternalAddressList.Destroy;
- begin
- end;
- function TInternalAddressList.GetChannelCount: integer;
- begin
- Result := 0;
- end;
- function TInternalAddressList.GetIrcChannel(const aIndex: integer): TIrcChannel;
- begin
- Result := nil;
- end;
- function TInternalAddressList.GetNickname(const aIndex: integer): TIrcNickname;
- begin
- Result := nil;
- end;
- function TInternalAddressList.GetNicknameCount: integer;
- begin
- Result := 0;
- end;
- procedure TInternalAddressList.SetEnabled(const Value: boolean);
- begin
- if (FEnabled = Value) then
- Exit;
- FEnabled := Value;
- end;
- procedure TInternalAddressList.SetIrcChannel(const aIndex: integer; const Value: TIrcChannel);
- begin
- end;
- procedure TInternalAddressList.SetNickname(const aIndex: integer; const Value: TIrcNickname);
- begin
- end;
- { TELIrc }
- constructor TIrc.Create(aOwner: TComponent);
- begin
- inherited Create(aOwner);
- FAltNicknames := TStringList.Create;
- FTokenizer := TTokenizer.Create;
- FParser := TIrcMsgParser.Create;
- FUserMode := '+ix';
- FIAL := TInternalAddressList.Create(Self);
- FRejoinWhenKicked := True;
- FReconnectWhenKilled := True;
- end;
- destructor TIrc.Destroy;
- begin
- FIAL.Free;
- FAltNicknames.Free;
- FParser.Free;
- FTokenizer.Free;
- inherited;
- end;
- procedure TIrc.Assign(aSource: TPersistent);
- begin
- if (aSource is TIrc) then
- begin
- Nickname := TIrc(aSource).Nickname;
- Username := TIrc(aSource).Username;
- RealName := TIrc(aSource).RealName;
- Password := TIrc(aSource).Password;
- UserMode := TIrc(aSource).UserMode;
- RejoinWhenKicked := TIrc(aSource).RejoinWhenKicked;
- ReconnectWhenKilled := TIrc(aSource).ReconnectWhenKilled;
- AltNicknames.Assign(TIrc(aSource).AltNicknames);
- end
- else
- inherited;
- end;
- procedure TIrc.EventClose(const aError: word; const aClosedByRemote: boolean);
- begin
- inherited;
- end;
- procedure TIrc.EventConnect(const aError: word);
- begin
- inherited;
- { Login }
- if (FPassword <> CEmpty) then
- Raw('PASS' + CSpace + FPassword);
- Raw('NICK' + CSpace + FNickname);
- Raw('USER' + CSpace + FUsername + CSpace + FUserMode + CSpace + CAsterisk + CSpace + CColon + FRealname);
- end;
- procedure TIrc.EventRead(const aError: word);
- var
- s: string;
- i: integer;
- begin
- inherited;
- while (RecvString(s)) do
- begin
- { Split on CRLF }
- if (FIncompleteCmd <> CEmpty) then
- begin
- { If there was incomplete command present in last parse prepend that to received data. }
- FTokenizer.Split(FIncompleteCmd + s, CCrLf, [esoCSQot, esoCSSep]);
- FIncompleteCmd := CEmpty;
- end
- else
- { Otherwise split the incoming data. }
- FTokenizer.Split(s, CCrLf, [esoCSQot, esoCSSep]);
- if (TextRight(s, 2) = CCrLf) then
- begin
- { If received data was CRLF terminated parse all commands now. }
- for i := 0 to FTokenizer.Count - 1 do
- ParseCommand(FTokenizer[i]);
- end
- else
- begin
- { Otherwise add last token as incomplete command if not CRLF terminated }
- if (FTokenizer.Count = 1) then
- FIncompleteCmd := FTokenizer[0]
- else
- begin
- for i := 0 to FTokenizer.Count - 2 do
- ParseCommand(FTokenizer[i]);
- FIncompleteCmd := FTokenizer[FTokenizer.Count - 1];
- end;
- end;
- end;
- end;
- procedure TIrc.ParseCommand(const aLine: string);
- var
- Code : integer;
- Block: boolean;
- begin
- { Fire event }
- if (Assigned(FOnRaw)) then
- begin
- Block := False;
- FOnRaw(Self, aLine, True, Block);
- if (Block) then
- Exit;
- end;
- FParser.Parse(aLine);
- if (SameText(FParser.Command, CPING)) then
- begin
- Handle_PING;
- Exit;
- end;
- if (SameText(FParser.Command, CJOIN)) then
- begin
- Handle_JOIN;
- Exit;
- end;
- if (SameText(FParser.Command, CPART)) then
- begin
- Handle_PART;
- Exit;
- end;
- if (SameText(FParser.Command, CKICK)) then
- begin
- Handle_KICK;
- Exit;
- end;
- if (SameText(FParser.Command, CQUIT)) then
- begin
- Handle_QUIT;
- Exit;
- end;
- if (SameText(FParser.Command, CKILL)) then
- begin
- Handle_KILL;
- Exit;
- end;
- if (SameText(FParser.Command, CNICK)) then
- begin
- Handle_NICK;
- Exit;
- end;
- if (SameText(FParser.Command, CMODE)) then
- begin
- Handle_MODE;
- Exit;
- end;
- if (SameText(FParser.Command, CPRIVMSG)) then
- begin
- Handle_PRIVMSG;
- Exit;
- end;
- if (SameText(FParser.Command, CNOTICE)) then
- begin
- Handle_NOTICE;
- Exit;
- end;
- if (SameText(FParser.Command, CERROR)) then
- begin
- Handle_ERROR;
- Exit;
- end;
- if (SameText(FParser.Command, CINVITE)) then
- begin
- Handle_INVITE;
- Exit;
- end;
- if (SameText(FParser.Command, CWALLOPS)) then
- begin
- Handle_WALLOPS;
- Exit;
- end;
- Code := StrToIntDef(FParser.Command, -1);
- if (Code <> -1) then
- Handle_Numeric(Code);
- end;
- procedure TIrc.Handle_PING;
- begin
- if (FParser.TrailingCount > 0) then
- Raw(CPONG + CSpace + CColon + FParser.Trailings)
- else
- Raw(CPONG);
- end;
- procedure TIrc.Handle_JOIN;
- begin
- { Fire event }
- if (Assigned(FOnJoin)) then
- FOnJoin(Self, FParser.SourceNickName, FParser.Source, FParser.AllParams);
- end;
- procedure TIrc.Handle_PART;
- begin
- { Fire event }
- if (Assigned(FOnPart)) then
- FOnPart(Self, FParser.SourceNickName, FParser.Source, FParser.Param[0], FParser.Trailings);
- end;
- procedure TIrc.Handle_KICK;
- begin
- { Fire event }
- if (Assigned(FOnKick)) then
- FOnKick(Self, FParser.SourceNickName, FParser.Param[1], FParser.Param[0], FParser.Trailings);
- { Auto rejoin }
- if (SameText(FParser.Param[1], FNickname)) then
- if (FRejoinWhenKicked) then
- Cmd_Join(FParser.Param[0]);
- end;
- procedure TIrc.Handle_QUIT;
- begin
- { Fire event }
- if (Assigned(FOnQuit)) then
- FOnQuit(Self, FParser.SourceNickName, FParser.Source, FParser.Trailings);
- end;
- procedure TIrc.Handle_KILL;
- begin
- { Fire event }
- if (Assigned(FOnKill)) then
- FOnKill(Self, FParser.Source, FParser.Param[0], FParser.Trailings);
- end;
- procedure TIrc.Handle_NICK;
- begin
- { Fire event }
- if (Assigned(FOnNick)) then
- FOnNick(Self, FParser.SourceNickName, FParser.Param[0], FParser.Source);
- end;
- procedure TIrc.Handle_MODE;
- begin
- // -> :evilworks!evilworks@staff.anonops.li MODE #evilden +i
- // -> :evilworks!evilworks@staff.anonops.li MODE #evilden -i
- // -> :evilworks!evilworks@staff.anonops.li MODE #evilden +i
- // -> :evilworks!evilworks@staff.anonops.li MODE #evilden +DM-i+o win32
- // -> :evilworks!evilworks@staff.anonops.li MODE #evilden -DM+i-o win32
- // -> :evilworks!evilworks@staff.anonops.li MODE #evilden +DM-i+o win32
- // -> :evilworks!evilworks@staff.anonops.li MODE #evilden -DM+i-o win32
- // -> :evilworks!evilworks@staff.anonops.li MODE #evilden +DM-i+ov win32 evilworks
- //
- // <- :evilworks!evilworks@evil.machine MODE #anonops +i-i
- //
- // -> shitstorm.anonops.in MODE evilworks -i
- // <- :evilworks!evilworks@evil.machine MODE evilworks -i
- // -> shitstorm.anonops.in SAMODE p0ke -i
- // <- :shitstorm.anonops.in NOTICE evilworks :*** ANNOUNCEMENT: evilworks used SAMODE: p0ke -i
- if (Assigned(FOnMode)) then
- FOnMode(Self, FParser.Source, FParser.Param[0], FParser.ParamsFrom(1));
- end;
- procedure TIrc.Handle_PRIVMSG;
- var
- cmd : string;
- params: string;
- begin
- if (TextEnclosed(FParser.Trailings, #01, True)) then
- begin
- if (Assigned(FOnCTCP)) then
- begin
- params := TextUnEnclose(FParser.Trailings, #01, True);
- cmd := TextGet(params, CSpace, True, True);
- FOnCTCP(Self, FParser.SourceNickName, FParser.Source, FParser.Param[0], cmd, params);
- end;
- end
- else
- begin
- if (Assigned(FOnPrivMsg)) then
- FOnPrivMsg(Self, FParser.SourceNickName, FParser.Source, FParser.Param[0], FParser.Trailings);
- end;
- end;
- procedure TIrc.Handle_NOTICE;
- var
- cmd : string;
- params: string;
- begin
- if (TextEnclosed(FParser.Trailings, #01, True)) then
- begin
- if (Assigned(FOnCTCP)) then
- begin
- cmd := TextRight(FParser.Trailing[0], Length(FParser.Trailing[0]) - 1);
- params := TextLeft(FParser.TrailingsFrom(1), Length(FParser.TrailingsFrom(1)) - 1);
- FOnCTCP(Self, FParser.SourceNickName, FParser.Source, FParser.Param[0], cmd, params);
- end;
- end
- else
- begin
- if (FParser.SourceType = stServer) then
- begin
- if (Assigned(FOnServerNotice)) then
- FOnServerNotice(Self, FParser.Source, FParser.Trailings);
- end
- else
- begin
- if (Assigned(FOnNotice)) then
- FOnNotice(Self, FParser.SourceNickName, FParser.Source, FParser.Param[0], FParser.Trailings);
- end;
- end;
- end;
- procedure TIrc.Handle_INVITE;
- begin
- // -> :evilworks!evilworks@evil.machine INVITE win32 :#evilden
- end;
- procedure TIrc.Handle_WALLOPS;
- begin
- end;
- procedure TIrc.Handle_ERROR;
- begin
- end;
- procedure TIrc.Handle_319_RPL_WHOISCHANNELS;
- begin
- end;
- procedure TIrc.Handle_322_RPL_LIST;
- begin
- end;
- procedure TIrc.Handle_352_RPL_WHOREPLY;
- begin
- end;
- procedure TIrc.Handle_353_RPL_NAMEREPLY;
- begin
- end;
- procedure TIrc.Handle_333;
- begin
- end;
- procedure TIrc.Handle_Numeric(const aCode: integer);
- begin
- case aCode of
- 001:
- begin
- if (Assigned(FOnServerWelcome)) then
- FOnServerWelcome(Self);
- { :corey.anonops.in 001 win32 :Welcome to the AnonOps IRC Network win32!win32@188.129.57.61 }
- end;
- 002:
- begin
- { :corey.anonops.in 002 win32 :Your host is corey.anonops.in, running version InspIRCd-2.0 }
- end;
- 003:
- begin
- { :corey.anonops.in 003 win32 :This server was created 00:58:35 Sep 6 2011 }
- end;
- 004:
- begin
- { :corey.anonops.in 004 win32 corey.anonops.in InspIRCd-2.0 BHIRSWghiorswx ACDFIKLMNOQRSTYabcfhijklmnopqrstuvz FILYabfhjkloqv }
- end;
- 005:
- begin
- { :corey.anonops.in 005 win32 AWAYLEN=31 CALLERID=g CASEMAPPING=rfc1459 CHANMODES=IYb,k,FLfjl,ACDKMNOQRSTcimnprstuz CHANTYPES=# CHARSET=ascii ELIST=MU EXTBAN=,ACNOQRSTcmz FNC INVEX=I KICKLEN=151 MAP MAXBANS=60 :are supported by this server }
- { :corey.anonops.in 005 win32 MAXCHANNELS=50 MAXPARA=32 MAXTARGETS=20 MODES=20 NETWORK=AnonOps NICKLEN=32 OVERRIDE PREFIX=(qaohv)~&@%+ SECURELIST SSL=93.114.44.112:6697 STARTTLS STATUSMSG=~&@%+ TOPICLEN=308 :are supported by this server }
- { :corey.anonops.in 005 win32 VBANLIST WALLCHOPS WALLVOICES WATCH=32 :are supported by this server }
- end;
- 042:
- begin
- { :corey.anonops.in 042 win32 750AACQH7 :your unique ID }
- end;
- 251:
- begin
- { :corey.anonops.in 251 win32 :There are 52 users and 469 invisible on 8 servers }
- end;
- 252:
- begin
- { :corey.anonops.in 252 win32 8 :operator(s) online }
- end;
- 253:
- begin
- { :corey.anonops.in 253 win32 1 :unknown connections }
- end;
- 254:
- begin
- { :corey.anonops.in 254 win32 195 :channels formed }
- end;
- 255:
- begin
- { :corey.anonops.in 255 win32 :I have 411 clients and 1 servers }
- end;
- 265:
- begin
- { :corey.anonops.in 265 win32 :Current Local Users: 411 Max: 541 }
- end;
- 266:
- begin
- { :corey.anonops.in 266 win32 :Current Global Users: 521 Max: 679 }
- end;
- 319:
- begin
- Handle_319_RPL_WHOISCHANNELS;
- { RPL_WHOISCHANNELS }
- end;
- 321:
- begin
- { RPL_LISTSTART - :src 321 tgt chan :usrs nam }
- end;
- 322:
- begin
- Handle_322_RPL_LIST;
- { RPL_LIST }
- end;
- 331:
- begin
- { RPL_NOTOPIC }
- end;
- 332:
- begin
- { RPL_TOPIC }
- { :corey.anonops.in 332 win32 #anonops :Some topic text here }
- end;
- 333:
- begin
- Handle_333;
- { :corey.anonops.in 333 win32 #anonops Jupiler 1317771878 }
- end;
- 341:
- begin
- { RPL_INVITING }
- end;
- 352:
- begin
- Handle_352_RPL_WHOREPLY;
- { RPL_WHOREPLY }
- end;
- 353:
- begin
- Handle_353_RPL_NAMEREPLY;
- { RPL_NAMEREPLY }
- { Replies to /names }
- { :corey.anonops.in 353 win32 = #anonops :SpecialBit Thought_Criminal mnx }
- end;
- 366:
- begin
- { END OF NAMES LIST }
- { :corey.anonops.in 366 win32 #anonops :End of /NAMES list. }
- end;
- 372:
- begin
- { MOTD line }
- end;
- 375:
- begin
- { MOTD start }
- { :corey.anonops.in 375 win32 :corey.anonops.in message of the day }
- end;
- 376:
- begin
- { MOTD end }
- { :corey.anonops.in 376 win32 :End of message of the day. }
- end;
- 396:
- begin
- { :corey.anonops.in 396 win32 AN-0jb.13v.2j3fss.IP :is now your displayed host }
- end;
- 482:
- begin
- { :corey.anonops.in 482 win32 #evilden :You must have a registered nickname to create a new channel }
- end;
- end; { case }
- end;
- procedure TIrc.Raw(const aText: string);
- var
- Block: boolean;
- begin
- if (SocketState <> ssConnected) then
- Exit;
- { Fire event }
- if (Assigned(FOnRaw)) then
- begin
- Block := False;
- FOnRaw(Self, aText, False, Block);
- if (Block) then
- Exit;
- end;
- SendLine(aText);
- end;
- procedure TIrc.Cmd_Join(const aChannel, aKey: string);
- begin
- if (aKey <> CEmpty) then
- Raw(CJOIN + CSpace + aChannel + CSpace + aKey)
- else
- Raw(CJOIN + CSpace + aChannel);
- end;
- procedure TIrc.Cmd_Part(const aChannel, aPartMsg: string);
- begin
- if (aPartMsg <> CEmpty) then
- Raw(CPART + CSpace + aChannel + CSpace + CColon + aPartMsg)
- else
- Raw(CPART + CSpace + aChannel);
- end;
- procedure TIrc.Cmd_Msg(const aTarget, aMessage: string);
- begin
- Raw(CPRIVMSG + CSpace + aTarget + CSpace + CColon + aMessage);
- end;
- procedure TIrc.Cmd_Nick(const aNewNickname: string);
- begin
- Raw(CNICK + CSpace + aNewNickname);
- end;
- procedure TIrc.SetPassword(const Value: string);
- begin
- if (FPassword = Value) then
- Exit;
- FPassword := Value;
- end;
- procedure TIrc.SetAltNicknames(const Value: TStrings);
- begin
- FAltNicknames.Assign(Value);
- end;
- procedure TIrc.SetNickname(const Value: string);
- begin
- if (FNickname = Value) then
- Exit;
- FNickname := Value;
- Cmd_Nick(FNickname);
- end;
- procedure TIrc.SetRealname(const Value: string);
- begin
- if (SocketState <> ssDisconnected) then
- Exit;
- if (FRealname = Value) then
- Exit;
- FRealname := Value;
- end;
- procedure TIrc.SetReconnectWhenKilled(const Value: boolean);
- begin
- if (FReconnectWhenKilled = Value) then
- Exit;
- FReconnectWhenKilled := Value;
- end;
- procedure TIrc.SetRejoinWhenKicked(const Value: boolean);
- begin
- if (FRejoinWhenKicked = Value) then
- Exit;
- FRejoinWhenKicked := Value;
- end;
- procedure TIrc.SetUserMode(const Value: string);
- begin
- if (FUserMode = Value) then
- Exit;
- FUserMode := Value;
- if (TextLeft(FUserMode, 1) <> CPlus) then
- FUserMode := CPlus + FUserMode;
- end;
- procedure TIrc.SetUsername(const Value: string);
- begin
- if (SocketState <> ssDisconnected) then
- Exit;
- if (FUsername = Value) then
- Exit;
- FUsername := Value;
- end;
- end.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement