Advertisement
Guest User

Untitled

a guest
May 8th, 2017
81
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Delphi 50.15 KB | None | 0 0
  1. //
  2. // IRC engine by reiser
  3. //
  4.  
  5. unit ReiIRC;
  6.  
  7. interface
  8.  
  9. uses
  10.   Windows, WinSock2, ReiGlobal, ReiDCC, ReiStringArray, ReiThread, ReiCommandDispatcher;
  11.  
  12. const
  13.   IRC_DEFAULT_PORT = 6667; // Default port IRC servera
  14.   AllowedChars     = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789[]\`_^{|}-';
  15.  
  16. type
  17.   TReiIRC = class;
  18.  
  19.   TRawEvent                  = procedure(ASender : TReiIRC; const AMessage : String; const AIn : Boolean) of object;
  20.   TMOTD                      = procedure of object;
  21.   TPingEvent                 = procedure(ASender : TReiIRC; const AFrom : String; var returnPong : Boolean) of object;
  22.   TJoinEvent                 = procedure(ASender : TReiIRC; const ANickname, AUser, AHost, AChannel, AKeyword : String) of object;
  23.   TPartEvent                 = procedure(ASender : TReiIRC; const ANickname, AUser, AHost, AChannel, AReason : String) of object;
  24.   TPrivMsgEvent              = procedure(ASender : TReiIRC; const ANickname, AUser, AHost, ATarget, AMessage : String) of object;
  25.   TCTCPEvent                 = procedure(ASender : TReiIRC; const ANickname, AUser, AHost, ATarget, AMessage : String) of object;
  26.   TNoticeEvent               = procedure(ASender : TReiIRC; const ANicknameFrom, AUser, AHost, ANicknameTo, AMessage : String) of object;
  27.   TModeChangeEvent           = procedure(ASender : TReiIRC; const ATarget, AMode, AParams : String) of object;
  28.   TOPEvent                   = procedure(ASender : TReiIRC; const ANickname, AUser, AHost, AChannel, ATarget : String) of object;
  29.   THOPEvent                  = procedure(ASender : TReiIRC; const ANickname, AUser, AHost, AChannel, ATarget : String) of object;
  30.   TVoiceEvent                = procedure(ASender : TReiIRC; const ANickname, AUser, AHost, AChannel, ATarget : String) of object;
  31.   TDeOPEvent                 = procedure(ASender : TReiIRC; const ANickname, AUser, AHost, AChannel, ATarget : String) of object;
  32.   TDeHOPEvent                = procedure(ASender : TReiIRC; const ANickname, AUser, AHost, AChannel, ATarget : String) of object;
  33.   TDeVoiceEvent              = procedure(ASender : TReiIRC; const ANickname, AUser, AHost, AChannel, ATarget : String) of object;
  34.   TKickEvent                 = procedure(ASender : TReiIRC; const ANickname, AUser, AHost, AChannel, ATarget : String) of object;
  35.   TInviteEvent               = procedure(ASender : TReiIRC; const ANickname, AUser, AHost, AChannel, ATarget : String) of object;
  36.   TQuitEvent                 = procedure(ASender : TReiIRC; const ANickname, AUser, AHost, AReason : String) of object;
  37.   TNicknameChangeEvent       = procedure(ASender : TReiIRC; const ANickname, AUser, AHost, ANewNickname : String) of object;
  38.   TTopicChangeEvent          = procedure(ASender : TReiIRC; const ANickname, AUser, AHost, AChannel, ANewTopic : String) of object;
  39.   TBanEvent                  = procedure(ASender : TReiIRC; const ANickname, AUser, AHost, AHostmask : String) of object;
  40.   TUnbanEvent                = procedure(ASender : TReiIRC; const ANickname, AUser, AHost, AHostmask : String) of object;
  41.   TTopicReceiveEvent         = procedure(ASender : TReiIRC; const AChannel, ATopic : String) of object;
  42.   TNicknamesListReceiveEvent = procedure(ASender : TReiIRC; const AChannel : String; const ANicknames : TStringArray) of object;
  43.   TNicknameInUse             = procedure(ASender : TReiIRC; const ANickname : String; var ANewNickname : String) of object;
  44.   TNicknameNotify            = procedure(ASender : TReiIRC; const ANickname : String; const AOnline : Boolean) of object;
  45.   TErrorReceive              = procedure(ASender : TReiIRC; const AError : String) of object;
  46.   TDCCChatIncoming           = procedure(ASender : TReiIRC; const AAddress : String; const APort : Integer; var AAccept : Boolean) of object;
  47.   TDCCChatOutgoing           = procedure(ASender : TReiIRC; const AAddress : String; const APort : Integer) of object;
  48.   TDCCChatMessage            = procedure(ASenderIRC : TReiIRC; ASenderDCC : TReiDCC; const AMessage : String) of object;
  49.   TDCCFileIncoming           = procedure(ASender : TReiIRC; const AFilename, AAddress : String; const APort, AFilesize : Integer; var AAccept : Boolean) of object;
  50.   TDCCFileOutgoing           = procedure(ASender : TReiIRC; const AFilename, AAddress : String; const APort, AFilesize : Integer) of object;
  51.  
  52.   TIRCChannels  = class
  53.                   protected
  54.                     Channels : TReiStringArray;
  55.                     Keywords : TReiStringArray;
  56.  
  57.                     FCount : DWORD;
  58.                   public
  59.                     constructor Create;
  60.                     destructor Free;
  61.                     function GetChannel(const AIndex : DWORD; var AChannel, AKeyword : String) : Integer;
  62.                     function FindChannel(const AChannel : String; var AIndex : DWORD) : Integer;
  63.                     function DeleteChannel(const AIndex : DWORD) : Integer;
  64.                     function AddChannel(const AChannel, AKeyword : String) : Integer;
  65.                     function SwapChannels(const AFirstIndex, ASecondIndex : DWORD) : Integer;
  66.                     procedure ClearChannels;
  67.                   published
  68.                     property Count : DWORD read FCount;
  69.                   end;
  70.  
  71.   TRawMessageInfo = record
  72.                       Prefix  : record
  73.                                   AType    : Integer;
  74.                                   Server   : String;
  75.                                   Nickname : String;
  76.                                   Username : String;
  77.                                   Hostmask : String;
  78.                                 end;
  79.                       Command : record
  80.                                   AType  : Integer;
  81.                                   Number : Integer;
  82.                                   Text   : String;
  83.                                 end;
  84.                       Params  : TStringArray;
  85.                     end;
  86.  
  87.   TDCC = record
  88.            Count : Integer;
  89.            Items : Array of TReiDCC;
  90.          end;
  91.  
  92.   TReiIRC = class
  93.             protected
  94.               FConnected : Boolean;
  95.               FSock      : TSocket;
  96.               FPort      : DWORD;
  97.               FServer    : String;
  98.               FPassword  : String;
  99.               FNickname  : String;
  100.               FHostmask  : String;
  101.               FUsername  : String;
  102.               FRealname  : String;
  103.  
  104.               FSenderNick : String;
  105.               FSenderUser : String;
  106.               FSenderHost : String;
  107.  
  108.               FAutoRejoin : Boolean;
  109.  
  110.               FPingRespond          : Boolean;
  111.               FVersionRespondString : String;
  112.  
  113.               FMessageContainer  : TReiStringArray;
  114.               FChannels          : TIRCChannels;
  115.               FAntiFlood         : Boolean;
  116.  
  117.               FMOTDReceived : Boolean;
  118.  
  119.               FNotifyList        : TReiStringArray;
  120.               FNotifyListOnline  : TReiStringArray;
  121.               FNotifyListEnabled : Boolean;
  122.  
  123.               MsgContainerThread : TReiThread;
  124.               DataRecvThread     : TReiThread;
  125.               NotifyListThread   : TReiThread;
  126.  
  127.               FOnRaw                  : TRawEvent;
  128.               FOnMOTD                 : TMOTD;
  129.               FOnPing                 : TPingEvent;
  130.               FOnJoin                 : TJoinEvent;
  131.               FOnPart                 : TPartEvent;
  132.               FOnPrivMsg              : TPrivMsgEvent;
  133.               FOnCTCP                 : TCTCPEvent;
  134.               FOnNotice               : TNoticeEvent;
  135.               FOnModeChange           : TModeChangeEvent;
  136.               FOnOP                   : TOPEvent;
  137.               FOnHOP                  : THOPEvent;
  138.               FOnVoice                : TVoiceEvent;
  139.               FOnDeOP                 : TDeOPEvent;
  140.               FOnDeHOP                : TDeHOPEvent;
  141.               FOnDeVoice              : TDeVoiceEvent;
  142.               FOnKick                 : TKickEvent;
  143.               FOnInvite               : TInviteEvent;
  144.               FOnQuit                 : TQuitEvent;
  145.               FOnNicknameChange       : TNicknameChangeEvent;
  146.               FOnTopicChange          : TTopicChangeEvent;
  147.               FOnBan                  : TBanEvent;
  148.               FOnUnban                : TUnbanEvent;
  149.               FOnTopicReceive         : TTopicReceiveEvent;
  150.               FOnNicknamesListReceive : TNicknamesListReceiveEvent;
  151.               FOnNicknameInUse        : TNicknameInUse;
  152.               FOnNicknameNotify       : TNicknameNotify;
  153.               FOnErrorReceive         : TErrorReceive;
  154.               FOnDCCChatIncoming      : TDCCChatIncoming;
  155.               FOnDCCChatOutgoing      : TDCCChatOutgoing;
  156.               FOnDCCChatMessage       : TDCCChatMessage;
  157.               FOnDCCFileIncoming      : TDCCFileIncoming;
  158.               FOnDCCFileOutgoing      : TDCCFileOutgoing;
  159.  
  160.               FCommands  : TReiCommandDispatcher;
  161.  
  162.               FTag       : Integer;
  163.  
  164.               MCLastSend  : DWORD;
  165.               MCNextDelay : DWORD;
  166.  
  167.               FUserModes : record
  168.                              Away            : Boolean;
  169.                              RecvWallops     : Boolean;
  170.                              Invisible       : Boolean;
  171.                            end;
  172.  
  173.               function CommandMOTD(ACommand : TReiCommandData) : Integer;
  174.               function CommandPing(ACommand : TReiCommandData) : Integer;
  175.               function CommandJoin(ACommand : TReiCommandData) : Integer;
  176.               function CommandPart(ACommand : TReiCommandData) : Integer;
  177.               function CommandPrivMsg(ACommand : TReiCommandData) : Integer;
  178.               function CommandNotice(ACommand : TReiCommandData) : Integer;
  179.               function CommandModeChange(ACommand : TReiCommandData) : Integer;
  180.               function CommandKick(ACommand : TReiCommandData) : Integer;
  181.               function CommandInvite(ACommand : TReiCommandData) : Integer;
  182.               function CommandQuit(ACommand : TReiCommandData) : Integer;
  183.               function CommandNicknameChange(ACommand : TReiCommandData) : Integer;
  184.               function CommandTopicChange(ACommand : TReiCommandData) : Integer;
  185.               function CommandTopicReceive(ACommand : TReiCommandData) : Integer;
  186.               function CommandNicknamesListReceive(ACommand : TReiCommandData) : Integer;
  187.               function CommandNicknameInUse(ACommand : TReiCommandData) : Integer;
  188.               function CommandNicknameNotify(ACommand : TReiCommandData) : Integer;
  189.               function CommandErrorReceive(ACommand : TReiCommandData) : Integer;
  190.               procedure CommandDCCChatMessage(ASenderDCC : TReiDCC; const AMessage : String);
  191.  
  192.               procedure MessageContainerThread(const AParam : pointer);
  193.               procedure RecvThread(const AParam : pointer);
  194.               procedure SetNickname(const AValue : String);
  195.               procedure SetUsername(const AValue : String);
  196.               procedure ProcessRawParams(const AParams : TStringArray);
  197.               procedure SetInvisible(const AValue : Boolean);
  198.               procedure SetRecvWallops(const AValue : Boolean);
  199.               procedure SetNotifyListEnabled(const AValue : Boolean);
  200.               procedure SendISON(const AParam : pointer);
  201.             public
  202.               DCC : TDCC;
  203.  
  204.               constructor Create;
  205.               destructor Free;
  206.  
  207.               procedure AssignIRCClientCommands;
  208.  
  209.               function Connect : Integer;
  210.               function Quit(const AReason : String) : Integer;
  211.  
  212.               procedure ParseRawMessage(const ARaw : String; out ARawMessageInfo : TRawMessageInfo);
  213.  
  214.               procedure SetAway(const AReason : String);
  215.               procedure UnsetAway;
  216.  
  217.               procedure Raw(const AMsg : String; const Instant : Boolean = FALSE);
  218.               procedure Join(const AChannel : String; const AKeyword : String = '');
  219.               procedure Part(const AChannel : String; const AReason : String = '');
  220.               procedure Say(const ATarget, AMessage : String);
  221.               procedure Ping(const ATarget : String);
  222.               procedure Pong(const ATarget : String);
  223.               procedure Notice(const ATarget, AMessage : String);
  224.               procedure SendCTCP(const ATarget, AMessage : String);
  225.               procedure SetMode(const ATarget, AMode : String);
  226.               procedure Kick(const AChannel, ANickname, AReason : String);
  227.               procedure Ban(const AChannel, AHostmask : String);
  228.               procedure Unban(const AChannel, AHostmask : String);
  229.               procedure GiveOP(const AChannel, ANickname : String);
  230.               procedure GiveHOP(const AChannel, ANickname : String);
  231.               procedure GiveVoice(const AChannel, ANickname : String);
  232.               procedure TakeOP(const AChannel, ANickname : String);
  233.               procedure TakeHOP(const AChannel, ANickname : String);
  234.               procedure TakeVoice(const AChannel, ANickname : String);
  235.               procedure Invite(const AChannel, ANickname : String);
  236.               procedure SendDCCFile(const ATarget, AFilename : String);
  237.             published
  238.               property Port     : DWORD read FPort write FPort;
  239.               property Server   : String read FServer write FServer;
  240.               property Password : String read FPassword write FPassword;
  241.               property Nickname : String read FNickname write SetNickname;
  242.               property Hostmask : String read FHostmask;
  243.               property Username : String read FUsername write SetUsername;
  244.               property Realname : String read FRealname write FRealname;
  245.  
  246.               property AutoRejoin : Boolean read FAutoRejoin write FAutoRejoin;
  247.  
  248.               property Connected : Boolean read FConnected;
  249.  
  250.               property PingRespond          : Boolean read FPingRespond write FPingRespond;
  251.               property VersionRespondString : String read FVersionRespondString write FVersionRespondString;
  252.  
  253.               property Away        : Boolean read FUserModes.Away;
  254.               property Invisible   : Boolean read FUserModes.Invisible write SetInvisible;
  255.               property RecvWallops : Boolean read FUserModes.RecvWallops write SetRecvWallops;
  256.  
  257.               property Channels          : TIRCChannels read FChannels;
  258.               property MessageContainer  : TReiStringArray read FMessageContainer write FMessageContainer;
  259.               property AntiFlood         : Boolean read FAntiFlood write FAntiFlood;
  260.  
  261.               property NotifyList        : TReiStringArray read FNotifyList write FNotifyList;
  262.               property NotifyListEnabled : Boolean read FNotifyListEnabled write SetNotifyListEnabled;
  263.  
  264.               property MOTDReceived : Boolean read FMOTDReceived;
  265.  
  266.               property Tag : Integer read FTag write FTag;
  267.  
  268.               property OnRaw                  : TRawEvent read FOnRaw write FOnRaw;
  269.               property OnMOTD                 : TMOTD read FOnMOTD write FOnMOTD;
  270.               property OnPing                 : TPingEvent read FOnPing write FOnPing;
  271.               property OnJoin                 : TJoinEvent read FOnJoin write FOnJoin;
  272.               property OnPart                 : TPartEvent read FOnPart write FOnPart;
  273.               property OnPrivMsg              : TPrivMsgEvent read FOnPrivMsg write FOnPrivMsg;
  274.               property OnCTCP                 : TCTCPEvent read FOnCTCP write FOnCTCP;
  275.               property OnNotice               : TNoticeEvent read FOnNotice write FOnNotice;
  276.               property OnModeChange           : TModeChangeEvent read FOnModeChange write FOnModeChange;
  277.               property OnOP                   : TOPEvent read FOnOP write FOnOP;
  278.               property OnHOP                  : THOPEvent read FOnHOP write FOnHOP;
  279.               property OnVoice                : TVoiceEvent read FOnVoice write FOnVoice;
  280.               property OnDeOP                 : TDeOPEvent read FOnDeOP write FOnDeOP;
  281.               property OnDeHOP                : TDeHOPEvent read FOnDeHOP write FOnDeHOP;
  282.               property OnDeVoice              : TDeVoiceEvent read FOnDeVoice write FOnDeVoice;
  283.               property OnKick                 : TKickEvent read FOnKick write FOnKick;
  284.               property OnInvite               : TInviteEvent read FOnInvite write FOnInvite;
  285.               property OnQuit                 : TQuitEvent read FOnQuit write FOnQuit;
  286.               property OnNicknameChange       : TNicknameChangeEvent read FOnNicknameChange write FOnNicknameChange;
  287.               property OnTopicChange          : TTopicChangeEvent read FOnTopicChange write FOnTopicChange;
  288.               property OnBan                  : TBanEvent read FOnBan write FOnBan;
  289.               property OnUnban                : TUnbanEvent read FOnUnban write FOnUnban;
  290.               property OnTopicReceive         : TTopicReceiveEvent read FOnTopicReceive write FOnTopicReceive;
  291.               property OnNicknamesListReceive : TNicknamesListReceiveEvent read FOnNicknamesListReceive write FOnNicknamesListReceive;
  292.               property OnNicknameInUse        : TNicknameInUse read FOnNicknameInUse write FOnNicknameInUse;
  293.               property OnNicknameNotify       : TNicknameNotify read FOnNicknameNotify write FOnNicknameNotify;
  294.               property OnDCCChatIncoming      : TDCCChatIncoming read FOnDCCChatIncoming write FOnDCCChatIncoming;
  295.               property OnDCCChatOutgoing      : TDCCChatOutgoing read FOnDCCChatOutgoing write FOnDCCChatOutgoing;
  296.               property OnDCCChatMessage       : TDCCChatMessage read FOnDCCChatMessage write FOnDCCChatMessage;
  297.               property OnDCCFileIncoming      : TDCCFileIncoming read FOnDCCFileIncoming write FOnDCCFileIncoming;
  298.               property OnDCCFileOutgoing      : TDCCFileOutgoing read FOnDCCFileOutgoing write FOnDCCFileOutgoing;
  299.             end;
  300.  
  301. implementation
  302.  
  303. {$I IRCCodes.inc}
  304.  
  305. const
  306.   CRLF = #$A;
  307.  
  308.  
  309.  
  310. //
  311. // Create konstruktor
  312. //
  313. constructor TIRCChannels.Create;
  314. begin
  315.   Channels := TReiStringArray.Create;
  316.   Keywords := TReiStringArray.Create;
  317.   Channels.AllowDuplicateItems := FALSE;
  318.   Channels.CaseSensitive := FALSE;
  319.   Keywords.AllowDuplicateItems := TRUE;
  320.   Keywords.CaseSensitive := TRUE;
  321.   FCount := 0;
  322. end;
  323.  
  324. //
  325. // Free destruktor
  326. //
  327. destructor TIRCChannels.Free;
  328. begin
  329.   Channels.Free;
  330.   Keywords.Free;
  331. end;
  332.  
  333. //
  334. // Vraca info o kanalu
  335. //
  336. function TIRCChannels.GetChannel(const AIndex : DWORD; var AChannel, AKeyword : String) : Integer;
  337. begin
  338.   result := Channels.GetItem(AIndex, AChannel);
  339.   If result <> ERROR_SUCCESS Then
  340.     Exit;
  341.   Keywords.GetItem(AIndex, AKeyword);
  342. end;
  343.  
  344. //
  345. // Trazi zadati kanal u listi
  346. //
  347. function TIRCChannels.FindChannel(const AChannel : String; var AIndex : DWORD) : Integer;
  348. begin
  349.   result := Channels.FindItem(AChannel, AIndex);
  350. end;
  351.  
  352. //
  353. // Brise kanal iz liste
  354. //
  355. function TIRCChannels.DeleteChannel(const AIndex : DWORD) : Integer;
  356. begin
  357.   result := Channels.DeleteItem(AIndex);
  358.   If result = ERROR_SUCCESS Then
  359.   Begin
  360.     Keywords.DeleteItem(AIndex);
  361.     Dec(FCount);
  362.   End;
  363. end;
  364.  
  365. //
  366. // Dodaje kanal u listu
  367. //
  368. function TIRCChannels.AddChannel(const AChannel, AKeyword : String) : Integer;
  369. begin
  370.   result := Channels.AddItem(AChannel);
  371.   If result = ERROR_SUCCESS Then
  372.   Begin
  373.     Keywords.AddItem(AKeyword);
  374.     Inc(FCount);
  375.   End;
  376. end;
  377.  
  378. //
  379. // Menja mesta kanalima u listi
  380. //
  381. function TIRCChannels.SwapChannels(const AFirstIndex, ASecondIndex : DWORD) : Integer;
  382. begin
  383.   result := Channels.SwapItems(AFirstIndex, ASecondIndex);
  384.   If result = ERROR_SUCCESS Then
  385.     Keywords.SwapItems(AFirstIndex, ASecondIndex);
  386. end;
  387.  
  388. //
  389. // Brise sve kanale iz liste
  390. //
  391. procedure TIRCChannels.ClearChannels;
  392. begin
  393.   Channels.ClearItems;
  394.   Keywords.ClearItems;
  395. end;
  396.  
  397.  
  398.  
  399.  
  400.  
  401.  
  402. //
  403. // Create konstruktor
  404. //
  405. constructor TReiIRC.Create;
  406. begin
  407.   FPort := IRC_DEFAULT_PORT;
  408.   FSock := 0;
  409.   FConnected := FALSE;
  410.   FMOTDReceived := FALSE;
  411.  
  412.   FAutoRejoin := FALSE;
  413.   FMessageContainer := TReiStringArray.Create;
  414.  
  415.   FAntiFlood := FALSE;
  416.  
  417.   FUserModes.Away := FALSE;
  418.   FUserModes.Invisible := FALSE;
  419.   FUserModes.RecvWallops := TRUE;
  420.  
  421.   FChannels := TIRCChannels.Create;
  422.  
  423.   FNotifyList := TReiStringArray.Create;
  424.   FNotifyList.AllowDuplicateItems := FALSE;
  425.   FNotifyList.CaseSensitive := FALSE;
  426.   FNotifyList.ClearItems;
  427.  
  428.   FNotifyListOnline := TReiStringArray.Create;
  429.   FNotifyListOnline.AllowDuplicateItems := FALSE;
  430.   FNotifyListOnline.CaseSensitive := FALSE;
  431.   FNotifyListOnline.ClearItems;
  432.  
  433.   SetNotifyListEnabled(FALSE);
  434.  
  435.   DCC.Count := 0;
  436.   SetLength(DCC.Items, DCC.Count);
  437.  
  438.   FPingRespond := TRUE;
  439.   FVersionRespondString := 'VERSION ReiIRC v0.02 engine';
  440.  
  441.   AssignIRCClientCommands;
  442. end;
  443.  
  444. //
  445. // Free destruktor
  446. //
  447. destructor TReiIRC.Free;
  448. begin
  449.   Quit('');
  450. end;
  451.  
  452. //
  453. // Assignuje IRC komande
  454. //
  455. procedure TReiIRC.AssignIRCClientCommands;
  456. begin
  457.   If not Assigned(FCommands) Then
  458.     FCommands := TReiCommandDispatcher.Create;
  459.  
  460.   FCommands.ClearCommands;
  461.  
  462.   FCommands.AddCommand(IntToStr(RPL_ENDOFMOTD), CommandMOTD);
  463.   FCommands.AddCommand(IntToStr(ERR_NOMOTD), CommandMOTD);
  464.   FCommands.AddCommand('PING', CommandPing);
  465.   FCommands.AddCommand('JOIN', CommandJoin);
  466.   FCommands.AddCommand('PART', CommandPart);
  467.   FCommands.AddCommand('PRIVMSG', CommandPrivMsg);
  468.   FCommands.AddCommand('NOTICE', CommandNotice);
  469.   FCommands.AddCommand('MODE', CommandModeChange);
  470.   FCommands.AddCommand('KICK', CommandKick);
  471.   FCommands.AddCommand('INVITE', CommandInvite);
  472.   FCommands.AddCommand('QUIT', CommandQuit);
  473.   FCommands.AddCommand('NICK', CommandNicknameChange);
  474.   FCommands.AddCommand('TOPIC', CommandTopicChange);
  475.   FCommands.AddCommand('ERROR', CommandErrorReceive);
  476.   FCommands.AddCommand(IntToStr(RPL_NOTOPIC), CommandTopicReceive);
  477.   FCommands.AddCommand(IntToStr(RPL_TOPIC), CommandTopicReceive);
  478.   FCommands.AddCommand(IntToStr(RPL_NAMREPLY), CommandNicknamesListReceive);
  479.   FCommands.AddCommand(IntToStr(ERR_NICKNAMEINUSE), CommandNicknameInUse);
  480.   FCommands.AddCommand(IntToStr(RPL_ISON), CommandNicknameNotify);
  481. end;
  482.  
  483. //
  484. // Konektovanje na IRC server
  485. //
  486. function TReiIRC.Connect : Integer;
  487. var
  488.   WSAData  : TWSAData;
  489.   SockAddr : TSockAddrIn;
  490.   positive : DWORD;
  491. begin
  492.   If FConnected Then
  493.   Begin
  494.     result := ERROR_CONNECTED;
  495.     Exit;
  496.   End;
  497.  
  498.   result := WSAStartup($101, WSAData);
  499.   If result <> 0 Then
  500.   Begin
  501.     WSACleanup;
  502.     Exit;
  503.   End;
  504.  
  505.   FSock := Socket(AF_INET, SOCK_STREAM, 0);
  506.   If FSock = INVALID_SOCKET Then
  507.   Begin
  508.     Shutdown(FSock, SD_BOTH);
  509.     CloseSocket(FSock);
  510.     WSACleanup;
  511.     result := INVALID_SOCKET;
  512.     Exit;
  513.   End;
  514.  
  515.   SockAddr.sin_family := AF_INET;
  516.   SockAddr.sin_port := htons(FPort);
  517.   SockAddr.sin_addr.S_addr := inet_addr(PAnsiChar(HostNameToIP(FServer)));
  518.   result := WinSock2.Connect(FSock, @SockAddr, SizeOf(SockAddr));
  519.   If result <> 0 Then
  520.   Begin
  521.     Shutdown(FSock, SD_BOTH);
  522.     CloseSocket(FSock);
  523.     WSACleanup;
  524.     Exit;
  525.   End;
  526.  
  527.   positive := 1;
  528.   ioctlsocket(FSock, FIONBIO, positive);
  529.  
  530.   FConnected := TRUE;
  531.  
  532.   If not Assigned(DataRecvThread) Then
  533.     DataRecvThread := TReiThread.Create;
  534.   DataRecvThread.OnExecute := RecvThread;
  535.   DataRecvThread.Start;
  536.  
  537.   If not Assigned(MsgContainerThread) Then
  538.     MsgContainerThread := TReiThread.Create;
  539.   MCNextDelay := 100;
  540.   MCLastSend := GetTickCount;
  541.   MsgContainerThread.OnExecute := MessageContainerThread;
  542.   MsgContainerThread.Delay := CPUDelay;
  543.   MsgContainerThread.Start;
  544.  
  545.   If FPassword <> '' Then
  546.     Raw('PASS ' + FPassword);
  547.  
  548.   SetNickname(FNickname);
  549.   SetUsername(FUsername);
  550.  
  551.   result := ERROR_SUCCESS;
  552. end;
  553.  
  554. //
  555. // Diskonektuje se sa IRC servera
  556. //
  557. function TReiIRC.Quit(const AReason : String) : Integer;
  558. var
  559.   C1 : Integer;
  560. begin
  561.   If not FConnected Then
  562.   Begin
  563.     result := ERROR_NOT_CONNECTED;
  564.     Exit;
  565.   End
  566.   else
  567.     result := ERROR_SUCCESS;
  568.  
  569.   SetNotifyListEnabled(FALSE);
  570.   FConnected := FALSE;
  571.  
  572.   If DCC.Count > 0 Then
  573.   Begin
  574.     For C1 := 0 to DCC.Count - 1 Do
  575.       DCC.Items[C1].Free;
  576.     DCC.Count := 0;
  577.     SetLength(DCC.Items, DCC.Count);
  578.   End;
  579.  
  580.   DataRecvThread.Stop;
  581.   MsgContainerThread.Stop;
  582.  
  583.   Shutdown(FSock, SD_BOTH);
  584.   CloseSocket(FSock);
  585.   WSACleanup;
  586.  
  587.   FMOTDReceived := FALSE;
  588.   FSock := 0;
  589.   FUserModes.Away := FALSE;
  590.   FUserModes.Invisible := FALSE;
  591.   FUserModes.RecvWallops := TRUE;
  592.  
  593.   MCNextDelay := 100;
  594.   MCLastSend := GetTickCount;
  595.  
  596.   FMessageContainer.ClearItems;
  597.   FChannels.ClearChannels;
  598. end;
  599.  
  600.  
  601. //
  602. // Rasclanjuje raw poruku na njen prefix, komandu i parametre
  603. //
  604. procedure TReiIRC.ParseRawMessage(const ARaw : String; out ARawMessageInfo : TRawMessageInfo);
  605. var
  606.   value      : Int64;
  607.   LD         : Integer;
  608.   C1         : Integer;
  609.   rawPrefix  : String;
  610.   rawCommand : String;
  611.   rawParams  : String;
  612. begin
  613.   If ARaw = '' Then
  614.     Exit;
  615.   rawPrefix := Copy(ARaw, 1, Pos(' ', ARaw) - 1);
  616.   If (rawPrefix = '') or
  617.      (rawPrefix = ':') Then
  618.     Exit;
  619.   If rawPrefix[1] = ':' Then
  620.     Delete(rawPrefix, 1, 1);
  621.   If (Pos('!', rawPrefix) = 0) and
  622.      (Pos('@', rawPrefix) = 0) and
  623.      (Pos('.', rawPrefix) > 0) and
  624.      (PosEx('.', rawPrefix, Pos('.', rawPrefix) + 1) > 0) Then
  625.     ARawMessageInfo.Prefix.AType := PREFIX_SERVER
  626.   else
  627.     ARawMessageInfo.Prefix.AType := PREFIX_USER;
  628.  
  629.   Case ARawMessageInfo.Prefix.AType of
  630.     PREFIX_SERVER : ARawMessageInfo.Prefix.Server := rawPrefix;
  631.     PREFIX_USER   : Begin
  632.                       ARawMessageInfo.Prefix.Nickname := Copy(rawPrefix, 1, Pos('!', rawPrefix) - 1);
  633.                       ARawMessageInfo.Prefix.Username := Copy(rawPrefix, Pos('!', rawPrefix) + 1, Pos('@', rawPrefix) - Pos('!', rawPrefix) - 1);
  634.                       ARawMessageInfo.Prefix.Hostmask := Copy(rawPrefix, Pos('@', rawPrefix) + 1, Length(rawPrefix) - Pos('@', rawPrefix));
  635.                     End;
  636.   End;
  637.  
  638.   rawCommand := Copy(ARaw, Pos(' ', ARaw) + 1, PosEx(' ', ARaw, Pos(' ', ARaw) + 1) - Pos(' ', ARaw) - 1);
  639.   If rawCommand = '' Then
  640.   Begin
  641.     rawCommand := rawPrefix;
  642.     ARawMessageInfo.Prefix.AType := 0;
  643.   End;
  644.   If (Length(rawCommand) = 3) and
  645.      (TryStrToInt(rawCommand, value)) Then
  646.     ARawMessageInfo.Command.AType := COMMAND_NUMBER
  647.   else
  648.     ARawMessageInfo.Command.AType := COMMAND_STRING;
  649.   Case ARawMessageInfo.Command.AType of
  650.     COMMAND_NUMBER : ARawMessageInfo.Command.Number := value;
  651.     COMMAND_STRING : ARawMessageInfo.Command.Text := rawCommand;
  652.   End;
  653.  
  654.   If ARawMessageInfo.Prefix.AType = 0 Then
  655.     rawParams := Copy(ARaw, Pos(' ', ARaw) + 1, Length(ARaw) - Pos(' ', ARaw)) + ' '
  656.   else
  657.     rawParams := Copy(ARaw, PosEx(' ', ARaw, Pos(' ', ARaw) + 1) + 1, Length(ARaw) - PosEx(' ', ARaw, Pos(' ', ARaw) + 1)) + ' ';
  658.   ARawMessageInfo.Params.Count := 0;
  659.   SetLength(ARawMessageInfo.Params.Items, ARawMessageInfo.Params.Count);
  660.  
  661.   If (rawParams <> '') and
  662.      (rawParams <> ' ') Then
  663.   Begin
  664.     LD := 0;
  665.     For C1 := 1 to Length(rawParams) Do
  666.       If rawParams[C1] = ' ' Then
  667.       Begin
  668.         Inc(ARawMessageInfo.Params.Count);
  669.         SetLength(ARawMessageInfo.Params.Items, ARawMessageInfo.Params.Count);
  670.         ARawMessageInfo.Params.Items[ARawMessageInfo.Params.Count - 1] := Copy(rawParams, LD + 1, C1 - LD - 1);
  671.         LD := C1;
  672.       End
  673.       else
  674.         If rawParams[C1] = ':' Then
  675.         Begin
  676.           Inc(ARawMessageInfo.Params.Count);
  677.           SetLength(ARawMessageInfo.Params.Items, ARawMessageInfo.Params.Count);
  678.           ARawMessageInfo.Params.Items[ARawMessageInfo.Params.Count - 1] := Copy(rawParams, C1 + 1, Length(rawParams) - C1 - 1);
  679.           Break;
  680.         End;
  681.   End;      
  682. end;
  683.  
  684. //
  685. // Salje raw poruku na IRC server (u stvari, smesta poruku u listu poruka koje cekaju na slanje)
  686. //
  687. procedure TReiIRC.Raw(const AMsg : String; const Instant : Boolean = FALSE);
  688. begin
  689.   If (FConnected) and
  690.      (Assigned(FMessageContainer)) and
  691.      (FMessageContainer.ItemsCount < 200) Then
  692.     FMessageContainer.AddItem(AMsg, Instant);
  693. end;
  694.  
  695. //
  696. // Ulazi na zadate kanale
  697. //
  698. procedure TReiIRC.Join(const AChannel : String; const AKeyword : String = '');
  699. begin
  700.   Raw('JOIN ' + AChannel + ' ' + AKeyword);
  701. end;
  702.  
  703. //
  704. // Izlazi sa zadatog kanala
  705. //
  706. procedure TReiIRC.Part(const AChannel : String; const AReason : String = '');
  707. begin
  708.   Raw('PART ' + AChannel + ' :' + AReason);
  709. end;
  710.  
  711. //
  712. // Salje message na kanal/user
  713. //
  714. procedure TReiIRC.Say(const ATarget, AMessage : String);
  715. var
  716.   msg : String;
  717. begin
  718.   msg := AMessage;
  719.    
  720.   Raw('PRIVMSG ' + ATarget + ' :' + msg);
  721. end;
  722.  
  723. //
  724. // Salje PING targetu
  725. //
  726. procedure TReiIRC.Ping(const ATarget : String);
  727. begin
  728.   Raw('PING :' + ATarget);
  729. end;
  730.  
  731. //
  732. // Salje PONG targetu
  733. //
  734. procedure TReiIRC.Pong(const ATarget : String);
  735. begin
  736.   Raw('PONG :' + ATarget);
  737. end;
  738.  
  739. //
  740. // Salje notice na kanal/user
  741. //
  742. procedure TReiIRC.Notice(const ATarget, AMessage : String);
  743. var
  744.   msg : String;
  745. begin
  746.   msg := AMessage;
  747.  
  748.   Raw('NOTICE ' + ATarget + ' :' + msg);
  749. end;
  750.  
  751. //
  752. // Salje CTCP na kanal/user
  753. //
  754. procedure TReiIRC.SendCTCP(const ATarget, AMessage : String);
  755. begin
  756.   Say(ATarget, #1 + AMessage + #1);
  757. end;
  758.  
  759. //
  760. // Setuje zadati mod
  761. //
  762. procedure TReiIRC.SetMode(const ATarget, AMode : String);
  763. begin
  764.   Raw('MODE ' + ATarget + ' ' + AMode);
  765. end;
  766.  
  767. //
  768. // Kickuje zadatog usera sa kanala
  769. //
  770. procedure TReiIRC.Kick(const AChannel, ANickname, AReason : String);
  771. begin
  772.   Raw('KICK ' + AChannel + ' ' + ANickname + ' :' + AReason);
  773. end;
  774.  
  775. //
  776. // Banuje zadati hostmask
  777. //
  778. procedure TReiIRC.Ban(const AChannel, AHostmask : String);
  779. begin
  780.   SetMode(AChannel, '+b ' + AHostmask);
  781. end;
  782.  
  783. //
  784. // Unbanuje zadati hostmask
  785. //
  786. procedure TReiIRC.Unban(const AChannel, AHostmask : String);
  787. begin
  788.   SetMode(AChannel, '-b ' + AHostmask);
  789. end;
  790.  
  791. //
  792. // Daje operator status nekom useru
  793. //
  794. procedure TReiIRC.GiveOP(const AChannel, ANickname : String);
  795. begin
  796.   SetMode(AChannel, '+o ' + ANickname);
  797. end;
  798.  
  799. //
  800. // Daje half-operator status nekom useru
  801. //
  802. procedure TReiIRC.GiveHOP(const AChannel, ANickname : String);
  803. begin
  804.   SetMode(AChannel, '+h ' + ANickname);
  805. end;
  806.  
  807. //
  808. // Daje voice status nekom useru
  809. //
  810. procedure TReiIRC.GiveVoice(const AChannel, ANickname : String);
  811. begin
  812.   SetMode(AChannel, '+v ' + ANickname);
  813. end;
  814.  
  815. //
  816. // Skida operator status nekom useru
  817. //
  818. procedure TReiIRC.TakeOP(const AChannel, ANickname : String);
  819. begin
  820.   SetMode(AChannel, '-o ' + ANickname);
  821. end;
  822.  
  823. //
  824. // Skida half-operator status nekom useru
  825. //
  826. procedure TReiIRC.TakeHOP(const AChannel, ANickname : String);
  827. begin
  828.   SetMode(AChannel, '-h ' + ANickname);
  829. end;
  830.  
  831. //
  832. // Skida voice status nekom useru
  833. //
  834. procedure TReiIRC.TakeVoice(const AChannel, ANickname : String);
  835. begin
  836.   SetMode(AChannel, '-v ' + ANickname);
  837. end;
  838.  
  839. //
  840. // Invite nekog usera na kanal
  841. //
  842. procedure TReiIRC.Invite(const AChannel, ANickname : String);
  843. begin
  844.   Raw('INVITE ' + ANickname + ' ' + AChannel);
  845. end;
  846.  
  847. //
  848. // Salje fajl preko DCC-a
  849. //
  850. procedure TReiIRC.SendDCCFile(const ATarget, AFilename : String);
  851. var
  852.   port   : Integer;
  853.   sock   : TSocket;
  854.   readfd : TFDSet;
  855.   tmo    : TTimeVal;
  856.   csock  : TSocket;
  857.   SAddr  : TSockAddr;
  858.   size   : Integer;
  859. begin
  860.   Inc(DCC.Count);
  861.   SetLength(DCC.Items, DCC.Count);
  862.   DCC.Items[DCC.Count - 1] := TReiDCC.Create;
  863.  
  864.   port := Random(40000) + 7000;
  865.   If DCC.Items[DCC.Count - 1].OpenPort(port, sock) = ERROR_SUCCESS Then
  866.   Begin
  867.     SendCTCP(ATarget, 'DCC SEND ' + ExtractFileName(AFilename) + ' ' + LongIP(GetExternalIP) + ' ' + IntToStr(port) + ' ' + IntToStr(GetFileSize(AFilename)));
  868.  
  869.     readfd.fd_count := 1;
  870.     readfd.fd_array[0] := sock;
  871.     tmo.tv_sec := 10;
  872.     tmo.tv_usec := 0;
  873.     If select(0, @readfd, nil, nil, @tmo) = SOCKET_ERROR Then
  874.     Begin
  875.       Shutdown(sock, SD_BOTH);
  876.       CloseSocket(sock);
  877.     End
  878.     else
  879.     Begin
  880.       size := SizeOf(TSockAddr);
  881.       csock := accept(sock, @SAddr, @size);
  882.       CloseSocket(sock);
  883.       DCC.Items[DCC.Count - 1].SendFile(csock, AFilename);
  884.       Shutdown(csock, SD_BOTH);
  885.       CloseSocket(csock);
  886.     End;
  887.   End;
  888. end;
  889.  
  890. //
  891. // Prethodnik OnMOTDReceived eventa
  892. //
  893. function TReiIRC.CommandMOTD(ACommand : TReiCommandData) : Integer;
  894. begin
  895.   result := ERROR_SUCCESS;
  896.  
  897.   FMOTDReceived := TRUE;
  898.  
  899.   If Assigned(FOnMOTD) Then
  900.     FOnMOTD;
  901. end;
  902.  
  903. //
  904. // Prethodnik OnPing eventa
  905. //
  906. function TReiIRC.CommandPing(ACommand : TReiCommandData) : Integer;
  907. var
  908.   from       : String;
  909.   returnPong : Boolean;
  910. begin
  911.   result := ERROR_SUCCESS;
  912.  
  913.   from := ACommand.Params.Items[0];
  914.  
  915.   returnPong := TRUE;
  916.   If Assigned(FOnPing) Then
  917.     FOnPing(self, from, returnPong);
  918.  
  919.   If returnPong Then
  920.     Pong(from);
  921. end;
  922.  
  923. //
  924. // Prethodnik OnJoin eventa
  925. //
  926. function TReiIRC.CommandJoin(ACommand : TReiCommandData) : Integer;
  927. var
  928.   channel, keyword : String;
  929. begin
  930.   result := ERROR_SUCCESS;
  931.  
  932.   channel := ACommand.Params.Items[0];
  933.   keyword := '';
  934.   If ACommand.Params.Count > 1 Then
  935.     keyword := ACommand.Params.Items[1];
  936.  
  937.   Channels.AddChannel(channel, keyword);  
  938.  
  939.   If Assigned(FOnJoin) Then
  940.     FOnJoin(self, FSenderNick, FSenderUser, FSenderHost, channel, keyword);
  941. end;
  942.  
  943. //
  944. // Prethodnik OnPart eventa
  945. //
  946. function TReiIRC.CommandPart(ACommand : TReiCommandData) : Integer;
  947. var
  948.   channel, reason : String;
  949.   index           : DWORD;
  950. begin
  951.   result := ERROR_SUCCESS;
  952.  
  953.   reason := '';
  954.   channel := ACommand.Params.Items[0];
  955.   If ACommand.Params.Count > 1 Then
  956.     reason := ACommand.Params.Items[1];
  957.  
  958.   If Channels.FindChannel(channel, index) = ERROR_SUCCESS Then
  959.     Channels.DeleteChannel(index);
  960.  
  961.   If Assigned(FOnPart) Then
  962.     FOnPart(self, FSenderNick, FSenderUser, FSenderHost, channel, reason);
  963. end;
  964.  
  965. //
  966. // Prethodnik OnPrivMsg eventa
  967. //
  968. function TReiIRC.CommandPrivMsg(ACommand : TReiCommandData) : Integer;
  969. var
  970.   target, msg : String;
  971.   arr         : TStringArray;
  972.   port        : Int64;
  973.   filesize    : Int64;
  974.   accept      : Boolean;
  975.   loctime     : TSystemTime;
  976.   loctimes    : String;
  977. begin
  978.   result := ERROR_SUCCESS;
  979.  
  980.   target := ACommand.Params.Items[0];
  981.   msg := '';
  982.   If ACommand.Params.Count > 1 Then
  983.     msg := ACommand.Params.Items[1];
  984.  
  985.   If (msg[1] = #1) and
  986.      (msg[Length(msg)] = #1) Then
  987.   Begin
  988.     Delete(msg, 1, 1);
  989.     Delete(msg, Length(msg), 1);
  990.     ExtractParams(msg, arr, FALSE);
  991.  
  992.     If arr.Count > 0 Then
  993.     Begin
  994.       If (LowerCase(arr.Items[0]) = 'version') and
  995.          (FVersionRespondString <> '') Then
  996.         If target <> FNickname Then
  997.           Notice(target, FVersionRespondString)
  998.         else
  999.           Notice(FSenderNick, FVersionRespondString);
  1000.  
  1001.       If LowerCase(arr.Items[0]) = 'time' Then
  1002.       Begin
  1003.         GetLocalTime(loctime);
  1004.         loctimes := 'TIME ' + FormatStr(IntToStr(loctime.wHour), 2, '0', asRight) + ':' + FormatStr(IntToStr(loctime.wMinute), 2, '0', asRight) + ':' +
  1005.                     FormatStr(IntToStr(loctime.wSecond), 2, '0', asRight) + ' ' + FormatStr(IntToStr(loctime.wDay), 2, '0', asRight) + '/' +
  1006.                     FormatStr(IntToStr(loctime.wMonth), 2, '0', asRight) + '/' + IntToStr(loctime.wYear);
  1007.         If target <> FNickname Then
  1008.           Notice(target, loctimes)
  1009.         else
  1010.           Notice(FSenderNick, loctimes);
  1011.       End;
  1012.  
  1013.       If (LowerCase(arr.Items[0]) = 'dcc') and
  1014.          (arr.Count >= 5) Then
  1015.       Begin
  1016.         If (LowerCase(arr.Items[1]) = 'chat') and
  1017.            (LowerCase(arr.Items[2]) = 'chat') Then
  1018.         Begin
  1019.           If (Assigned(FOnDCCChatIncoming)) and
  1020.              (TryStrToInt(arr.Items[4], port)) Then
  1021.           Begin
  1022.             accept := FALSE;
  1023.             FOnDCCChatIncoming(self, arr.Items[3], port, accept);
  1024.  
  1025.             If accept Then
  1026.             Begin
  1027.               Inc(DCC.Count);
  1028.               SetLength(DCC.Items, DCC.Count);
  1029.  
  1030.               DCC.Items[DCC.Count - 1] := TReiDCC.Create;
  1031.               DCC.Items[DCC.Count - 1].Host := ShortIP(arr.Items[3]);
  1032.               DCC.Items[DCC.Count - 1].Port := port;
  1033.               DCC.Items[DCC.Count - 1].Tag := DCC.Count - 1;
  1034.               If DCC.Items[DCC.Count - 1].Connect = ERROR_SUCCESS Then
  1035.                 DCC.Items[DCC.Count - 1].OnPrivMsg := CommandDCCChatMessage;
  1036.             End;
  1037.           End;
  1038.         End;
  1039.  
  1040.         If LowerCase(arr.Items[1]) = 'send' Then
  1041.         Begin
  1042.           If (Assigned(FOnDCCFileIncoming)) and
  1043.              (TryStrToInt(arr.Items[4], port)) Then
  1044.           Begin
  1045.             filesize := -1;
  1046.             If arr.Count > 5 Then
  1047.               If not TryStrToInt(arr.Items[5], filesize) Then
  1048.                 filesize := -1;
  1049.             accept := FALSE;
  1050.             FOnDCCFileIncoming(self, arr.Items[2], arr.Items[3], port, filesize, accept);
  1051.  
  1052.             If accept Then
  1053.             Begin
  1054.             // *****
  1055.             End;
  1056.           End;
  1057.         End;
  1058.       End;
  1059.     End;
  1060.  
  1061.     If Assigned(FOnCTCP) Then
  1062.       FOnCTCP(self, FSenderNick, FSenderUser, FSenderHost, TrimRight(target), TrimRight(msg));
  1063.   End
  1064.   else
  1065.     If Assigned(FOnPrivMsg) Then
  1066.       FOnPrivMsg(self, FSenderNick, FSenderUser, FSenderHost, TrimRight(target), TrimRight(msg));
  1067. end;
  1068.  
  1069. //
  1070. // Prethodnik OnNotice eventa
  1071. //
  1072. function TReiIRC.CommandNotice(ACommand : TReiCommandData) : Integer;
  1073. var
  1074.   target, msg : String;
  1075. begin
  1076.   result := ERROR_SUCCESS;
  1077.  
  1078.   target := ACommand.Params.Items[0];
  1079.   msg := '';
  1080.   If ACommand.Params.Count > 1 Then
  1081.     msg := ACommand.Params.Items[1];
  1082.  
  1083.   If Assigned(FOnNotice) Then
  1084.     FOnNotice(self, FSenderNick, FSenderUser, FSenderHost, target, msg);
  1085. end;
  1086.  
  1087. //
  1088. // Prethodnik OnModeChange eventa
  1089. //
  1090. function TReiIRC.CommandModeChange(ACommand : TReiCommandData) : Integer;
  1091. var
  1092.   target, mode, params : String;
  1093.   plus                 : Boolean;
  1094.   C1                   : Integer;
  1095. begin
  1096.   result := ERROR_SUCCESS;
  1097.  
  1098.   target := ACommand.Params.Items[0];
  1099.   mode := ACommand.Params.Items[1];
  1100.   If ACommand.Params.Count > 2 Then
  1101.     params := ACommand.Params.Items[2];
  1102.  
  1103.   If Assigned(FOnModeChange) Then
  1104.     FOnModeChange(self, target, mode, params);
  1105.  
  1106.   plus := FALSE;  
  1107.   For C1 := 1 to Length(mode) Do
  1108.   Begin
  1109.     If mode[C1] = '-' Then
  1110.       plus := FALSE
  1111.     else
  1112.       If mode[C1] = '+' Then
  1113.         plus := TRUE
  1114.       else
  1115.         Case mode[C1] of
  1116.           'b' : If not plus Then
  1117.                 Begin
  1118.                   If Assigned(FOnUnban) Then
  1119.                     FOnUnban(self, FSenderNick, FSenderUser, FSenderHost, params);
  1120.                 End
  1121.                 else
  1122.                   If Assigned(FOnBan) Then
  1123.                     FOnBan(self, FSenderNick, FSenderUser, FSenderHost, params);
  1124.  
  1125.           'o' : If not plus Then
  1126.                 Begin
  1127.                   If Assigned(FOnDeOP) Then
  1128.                     FOnOP(self, FSenderNick, FSenderUser, FSenderHost, target, params);
  1129.                 End
  1130.                 else
  1131.                   If Assigned(FOnOP) Then
  1132.                     FOnOP(self, FSenderNick, FSenderUser, FSenderHost, target, params);
  1133.  
  1134.           'h' : If not plus Then
  1135.                 Begin
  1136.                   If Assigned(FOnDeHOP) Then
  1137.                     FOnHOP(self, FSenderNick, FSenderUser, FSenderHost, target, params);
  1138.                 End
  1139.                 else
  1140.                   If Assigned(FOnHOP) Then
  1141.                     FOnHOP(self, FSenderNick, FSenderUser, FSenderHost, target, params);
  1142.  
  1143.           'v' : If not plus Then
  1144.                 Begin
  1145.                   If Assigned(FOnDeVoice) Then
  1146.                     FOnVoice(self, FSenderNick, FSenderUser, FSenderHost, target, params);
  1147.                 End
  1148.                 else
  1149.                   If Assigned(FOnVoice) Then
  1150.                     FOnVoice(self, FSenderNick, FSenderUser, FSenderHost, target, params);
  1151.         End;
  1152.   End;
  1153. end;
  1154.  
  1155. //
  1156. // Prethodnik OnKick eventa
  1157. //
  1158. function TReiIRC.CommandKick(ACommand : TReiCommandData) : Integer;
  1159. var
  1160.   channel, target : String;
  1161.   index           : DWORD;
  1162.   keyword         : String;
  1163. begin
  1164.   result := ERROR_SUCCESS;
  1165.  
  1166.   channel := ACommand.Params.Items[0];
  1167.   target := ACommand.Params.Items[1];
  1168.  
  1169.   If Channels.FindChannel(channel, index) = ERROR_SUCCESS Then
  1170.     If FAutoRejoin Then
  1171.     Begin
  1172.       Channels.Keywords.GetItem(index, keyword);
  1173.       Join(channel, keyword);
  1174.     End
  1175.     else
  1176.       Channels.DeleteChannel(index);
  1177.  
  1178.   If Assigned(FOnKick) Then
  1179.     FOnKick(self, FSenderNick, FSenderUser, FSenderHost, channel, target);
  1180. end;
  1181.  
  1182. //
  1183. // Prethodnik OnInvite eventa
  1184. //
  1185. function TReiIRC.CommandInvite(ACommand : TReiCommandData) : Integer;
  1186. var
  1187.   channel, target : String;
  1188. begin
  1189.   result := ERROR_SUCCESS;
  1190.  
  1191.   channel := ACommand.Params.Items[0];
  1192.   target := ACommand.Params.Items[1];
  1193.  
  1194.   If Assigned(FOnInvite) Then
  1195.     FOnInvite(self, FSenderNick, FSenderUser, FSenderHost, channel, target);
  1196. end;
  1197.  
  1198. //
  1199. // Prethodnik OnQuit eventa
  1200. //
  1201. function TReiIRC.CommandQuit(ACommand : TReiCommandData) : Integer;
  1202. var
  1203.   reason : String;
  1204. begin
  1205.   result := ERROR_SUCCESS;
  1206.  
  1207.   reason := ACommand.Params.Items[0];
  1208.  
  1209.   If Assigned(FOnQuit) Then
  1210.     FOnQuit(self, FSenderNick, FSenderUser, FSenderHost, reason);
  1211. end;
  1212.  
  1213. //
  1214. // Prethodnik OnNicknameChange eventa
  1215. //
  1216. function TReiIRC.CommandNicknameChange(ACommand : TReiCommandData) : Integer;
  1217. var
  1218.   newnickname : String;
  1219. begin
  1220.   result := ERROR_SUCCESS;
  1221.  
  1222.   newnickname := ACommand.Params.Items[0];
  1223.  
  1224.   If Assigned(FOnNicknameChange) Then
  1225.     FOnNicknameChange(self, FSenderNick, FSenderUser, FSenderHost, newnickname);
  1226. end;
  1227.  
  1228. //
  1229. // Prethodnik OnTopicChange eventa
  1230. //
  1231. function TReiIRC.CommandTopicChange(ACommand : TReiCommandData) : Integer;
  1232. var
  1233.   channel, newtopic : String;
  1234. begin
  1235.   result := ERROR_SUCCESS;
  1236.  
  1237.   channel := ACommand.Params.Items[0];
  1238.   If ACommand.Params.Count > 1 Then
  1239.     newtopic := ACommand.Params.Items[1]
  1240.   else
  1241.     newtopic := '';
  1242.  
  1243.   If Assigned(FOnTopicChange) Then
  1244.     FOnTopicChange(self, FSenderNick, FSenderUser, FSenderHost, channel, newtopic);
  1245. end;
  1246.  
  1247. //
  1248. // Prethodnik OnTopicReceive eventa
  1249. //
  1250. function TReiIRC.CommandTopicReceive(ACommand : TReiCommandData) : Integer;
  1251. var
  1252.   channel, topic : String;
  1253. begin
  1254.   result := ERROR_SUCCESS;
  1255.  
  1256.   channel := ACommand.Params.Items[1];
  1257.  
  1258.   If ACommand.Command = IntToStr(RPL_NOTOPIC) Then
  1259.     topic := ''
  1260.   else
  1261.     topic := ACommand.Params.Items[2];
  1262.  
  1263.   If Assigned(FOnTopicReceive) Then
  1264.     FOnTopicReceive(self, channel, topic);
  1265. end;
  1266.  
  1267. //
  1268. // Prethodnik OnNicknamesReceive eventa
  1269. //
  1270. function TReiIRC.CommandNicknamesListReceive(ACommand : TReiCommandData) : Integer;
  1271. var
  1272.   channel   : String;
  1273.   nicknames : TStringArray;
  1274. begin
  1275.   result := ERROR_SUCCESS;
  1276.  
  1277.   channel := ACommand.Params.Items[2];
  1278.   If ACommand.Params.Count >= 4 Then
  1279.     ExtractParams(ACommand.Params.Items[3], nicknames, FALSE)
  1280.   else
  1281.   Begin
  1282.     nicknames.Count := 0;
  1283.     SetLength(nicknames.Items, nicknames.Count);
  1284.   End;
  1285.  
  1286.   If Assigned(FOnNicknamesListReceive) Then
  1287.     FOnNicknamesListReceive(self, channel, nicknames);
  1288. end;
  1289.  
  1290. //
  1291. // Prethodnik OnNicknameInUse eventa
  1292. //
  1293. function TReiIRC.CommandNicknameInUse(ACommand : TReiCommandData) : Integer;
  1294. var
  1295.   newnickname : String;
  1296. begin
  1297.   result := ERROR_SUCCESS;
  1298.  
  1299.   newnickname := FNickname + '^';
  1300.   If Assigned(FOnNicknameInUse) Then
  1301.     FOnNicknameInUse(self, FNickname, newnickname);
  1302.  
  1303.   SetNickname(newnickname);
  1304. end;
  1305.  
  1306. //
  1307. // Prethodnik OnNicknameNotify eventa
  1308. //
  1309. function TReiIRC.CommandNicknameNotify(ACommand : TReiCommandData) : Integer;
  1310. var
  1311.   C1, C2 : DWORD;
  1312.   item   : String;
  1313.   index  : DWORD;
  1314.   narr   : TStringArray;
  1315.   marked : Boolean;
  1316. begin
  1317.   result := ERROR_SUCCESS;
  1318.  
  1319.   narr.Count := 0;
  1320.   SetLength(narr.Items, narr.Count);
  1321.  
  1322.   If ACommand.Params.Count >=2 Then
  1323.   Begin
  1324.     ACommand.Params.Items[1] := Trim(ACommand.Params.Items[1]);
  1325.     ACommand.Params.Items[1] := ACommand.Params.Items[1] + ' ';
  1326.  
  1327.     While Pos(' ', ACommand.Params.Items[1]) > 0 Do
  1328.     Begin
  1329.       If Copy(ACommand.Params.Items[1], 1, Pos(' ', ACommand.Params.Items[1]) - 1) <> '' Then
  1330.       Begin
  1331.         Inc(narr.Count);
  1332.         SetLength(narr.Items, narr.Count);
  1333.         narr.Items[narr.Count - 1] := Copy(ACommand.Params.Items[1], 1, Pos(' ', ACommand.Params.Items[1]) - 1);
  1334.       End;  
  1335.       Delete(ACommand.Params.Items[1], 1, Pos(' ', ACommand.Params.Items[1]));
  1336.     End;
  1337.   End;
  1338.  
  1339.   C1 := 0;
  1340.   While C1 < FNotifyListOnline.ItemsCount Do
  1341.   Begin
  1342.     FNotifyListOnline.GetItem(C1, item);
  1343.  
  1344.     marked := FALSE;
  1345.     If narr.Count > 0 Then
  1346.     Begin
  1347.       For C2 := 0 to narr.Count - 1 Do
  1348.       Begin
  1349.         If LowerCase(item) = LowerCase(narr.Items[C2]) Then
  1350.         Begin
  1351.           Inc(C1);
  1352.           marked := TRUE;
  1353.           Break;
  1354.         End;
  1355.       End;
  1356.     End;
  1357.     If not marked Then
  1358.     Begin
  1359.       FNotifyListOnline.DeleteItem(C1);
  1360.       If Assigned(FOnNicknameNotify) Then
  1361.         FOnNicknameNotify(self, item, FALSE);
  1362.     End;    
  1363.   End;
  1364.  
  1365.   If narr.Count > 0 Then
  1366.     For C1 := 0 to narr.Count - 1 Do
  1367.       If FNotifyListOnline.FindItem(narr.Items[C1], index) <> ERROR_SUCCESS Then
  1368.       Begin
  1369.         FNotifyListOnline.AddItem(narr.Items[C1]);
  1370.         If Assigned(FOnNicknameNotify) Then
  1371.           FOnNicknameNotify(self, narr.Items[C1], TRUE);
  1372.       End;
  1373. end;
  1374.  
  1375. //
  1376. // Prethodnik OnErrorReceive eventa
  1377. //
  1378. function TReiIRC.CommandErrorReceive(ACommand : TReiCommandData) : Integer;
  1379. begin
  1380.   result := ERROR_SUCCESS;
  1381.  
  1382.   Quit('');
  1383.   If Assigned(FOnErrorReceive) Then
  1384.     FOnErrorReceive(self, ACommand.Params.Items[0]);
  1385. end;
  1386.  
  1387. //
  1388. // Prethodnik OnDCCChatMessage eventa
  1389. //
  1390. procedure TReiIRC.CommandDCCChatMessage(ASenderDCC : TReiDCC; const AMessage : String);
  1391. begin
  1392.   If Assigned(FOnDCCChatMessage) Then
  1393.     FOnDCCChatMessage(self, ASenderDCC, AMessage);
  1394. end;
  1395.  
  1396. //
  1397. // Lista poruka koje cekaju na slanje
  1398. //
  1399. procedure TReiIRC.MessageContainerThread;
  1400. var
  1401.   msg  : String;
  1402.   subs : DWORD;
  1403. begin
  1404.   If (Assigned(FMessageContainer)) and
  1405.      (FMessageContainer.ItemsCount > 0) Then
  1406.   Begin
  1407.     If FAntiFlood Then
  1408.     Begin
  1409.       subs := GetTickCount - MCLastSend;
  1410.       If subs < MCNextDelay Then
  1411.       Begin
  1412.         If subs div 5 > MCNextDelay Then
  1413.           MCNextDelay := 0
  1414.         else
  1415.           Dec(MCNextDelay, subs div 5);
  1416.         If MCNextDelay < 2500 Then
  1417.           Inc(MCNextDelay, 150);
  1418.         Sleep(MCNextDelay - subs);
  1419.       End;
  1420.     End;
  1421.  
  1422.     If (FMessageContainer.ItemsCount > 0) and
  1423.        (FMessageContainer.GetItem(0, msg) = ERROR_SUCCESS) and
  1424.        (FConnected) Then
  1425.     Begin
  1426.       If Copy(msg, Length(msg) - 1, Length(CRLF)) <> CRLF Then
  1427.         msg := msg + CRLF;
  1428.       send(FSock, msg[1], Length(msg), 0);
  1429.       MCLastSend := GetTickCount;
  1430.       FMessageContainer.DeleteItem(0);
  1431.  
  1432.       If Assigned(FOnRaw) Then
  1433.         FOnRaw(self, Copy(msg, 1, Length(msg) - 2), FALSE);
  1434.     End;
  1435.   End;
  1436. end;
  1437.  
  1438. //
  1439. // Thread koji prima podatke sa IRC servera
  1440. //
  1441. procedure TReiIRC.RecvThread;
  1442. const
  1443.   bufsize = 4096;
  1444. var
  1445.   buf    : Array[1..bufsize] of Char;
  1446.   len    : Integer;
  1447.   params : TStringArray;
  1448.   C1 : Integer;
  1449. begin
  1450.   len := recv(FSock, buf[1], bufsize, 0);
  1451.   If len > 0 Then
  1452.   Begin
  1453.     ExtractParams(Copy(buf, 1, len), params, FALSE, CRLF);
  1454.     ProcessRawParams(params);
  1455.     For C1 := 0 to params.Count - 1 Do
  1456.     WriteLn(params.Items[C1]);
  1457.   End
  1458.   else
  1459.     Case len of
  1460.       0            : Quit('');
  1461.       SOCKET_ERROR : If WSAGetLastError <> WSAEWOULDBLOCK Then
  1462.                        Quit('');
  1463.     End;
  1464. end;
  1465.  
  1466.  
  1467. //
  1468. // Setuje nickname
  1469. //
  1470. procedure TReiIRC.SetNickname(const AValue : String);
  1471. begin
  1472.   If not StringInString(AValue, AllowedChars) Then
  1473.     Exit;
  1474.  
  1475.   FNickname := AValue;
  1476.  
  1477.   Raw('NICK ' + FNickname);
  1478. end;
  1479.  
  1480. //
  1481. // Setuje username
  1482. //
  1483. procedure TReiIRC.SetUsername(const AValue : String);
  1484. var
  1485.   modes : String;
  1486. begin
  1487.   If not StringInString(AValue, AllowedChars) Then
  1488.     Exit;
  1489.  
  1490.   FUsername := AValue;
  1491.  
  1492.   modes := '+';
  1493.   If FUserModes.RecvWallops Then
  1494.     modes := modes + 'w';
  1495.   If FUserModes.Invisible Then
  1496.     modes := modes + 'i';
  1497.  
  1498.   Raw('USER ' + FUsername + ' ' + modes + ' * :' + FRealname);
  1499. end;
  1500.  
  1501. //
  1502. // Obradjuje raw podatke primljene sa servera
  1503. //
  1504. procedure TReiIRC.ProcessRawParams(const AParams : TStringArray);
  1505. var
  1506.   C1      : Integer;
  1507.   msginfo : TRawMessageInfo;
  1508.   command : String;
  1509. begin
  1510.   For C1 := 0 to AParams.Count - 1 Do
  1511.   Begin
  1512.     If Assigned(FOnRaw) Then
  1513.       FOnRaw(self, AParams.Items[C1], TRUE);
  1514.  
  1515.     FillChar(msginfo, SizeOf(TRawMessageInfo), 0);
  1516.     ParseRawMessage(AParams.Items[C1], msginfo);
  1517.  
  1518.     FSenderNick := '';
  1519.     FSenderUser := '';
  1520.     FSenderHost := '';
  1521.     Case msginfo.Prefix.AType of
  1522.       PREFIX_SERVER : FSenderNick := msginfo.Prefix.Server;
  1523.       PREFIX_USER   : Begin
  1524.                         FSenderNick := msginfo.Prefix.Nickname;
  1525.                         FSenderUser := msginfo.Prefix.Username;
  1526.                         FSenderHost := msginfo.Prefix.Hostmask;
  1527.                       End;
  1528.     End;
  1529.  
  1530.     Case msginfo.Command.AType of
  1531.       COMMAND_NUMBER : command := IntToStr(msginfo.Command.Number);
  1532.       COMMAND_STRING : command := msginfo.Command.Text;
  1533.     End;
  1534.  
  1535.     FCommands.DispatchCommand(command, msginfo.Params);
  1536.   End;
  1537. end;
  1538.  
  1539. //
  1540. // Setuje away status
  1541. //
  1542. procedure TReiIRC.SetAway(const AReason : String);
  1543. begin
  1544.   FUserModes.Away := TRUE;
  1545.   Raw('AWAY :' + AReason)
  1546. end;
  1547.  
  1548. //
  1549. // Unsetuje away status
  1550. //
  1551. procedure TReiIRC.UnsetAway;
  1552. begin
  1553.   FUserModes.Away := FALSE;
  1554.   Raw('AWAY');
  1555. end;
  1556.  
  1557. //
  1558. // Setuje +i mod
  1559. //
  1560. procedure TReiIRC.SetInvisible(const AValue : Boolean);
  1561. begin
  1562.   FUserModes.Invisible := AValue;
  1563.  
  1564.   If AValue Then
  1565.     SetMode(FNickname, '+i')
  1566.   else
  1567.     SetMode(FNickname, '-i');
  1568. end;
  1569.  
  1570. //
  1571. // Setuje +w mod
  1572. //
  1573. procedure TReiIRC.SetRecvWallops(const AValue : Boolean);
  1574. begin
  1575.   FUserModes.RecvWallops := AValue;
  1576.  
  1577.   If AValue Then
  1578.     SetMode(FNickname, '+w')
  1579.   else
  1580.     SetMode(FNickname, '-w');
  1581. end;
  1582.  
  1583. //
  1584. // Notify lista on/off
  1585. //
  1586. procedure TReiIRC.SetNotifyListEnabled(const AValue : Boolean);
  1587. begin
  1588.   If AValue = FNotifyListEnabled Then
  1589.     Exit;
  1590.  
  1591.   FNotifyListEnabled := AValue;
  1592.  
  1593.   If FNotifyListEnabled Then
  1594.   Begin
  1595.     If not Assigned(NotifyListThread) Then
  1596.       NotifyListThread := TReiThread.Create;
  1597.     NotifyListThread.Delay := 5000;
  1598.     NotifyListThread.OnExecute := SendISON;
  1599.     NotifyListThread.Start;
  1600.   End
  1601.   else
  1602.     If Assigned(NotifyListThread) Then
  1603.       NotifyListThread.Stop;
  1604. end;
  1605.  
  1606. //
  1607. // Salje ISON komandu serveru
  1608. //
  1609. procedure TReiIRC.SendISON;
  1610. var
  1611.   tmp  : String;
  1612.   C1   : DWORD;
  1613.   item : String;
  1614. begin
  1615.   tmp := '';
  1616.   If FNotifyList.ItemsCount > 0 Then
  1617.   Begin
  1618.     For C1 := 0 to FNotifyList.ItemsCount - 1 Do
  1619.     Begin
  1620.       FNotifyList.GetItem(C1, item);
  1621.       tmp := tmp + ' ' + item;
  1622.     End;
  1623.  
  1624.     Raw('ISON' + tmp);
  1625.   End;  
  1626. end;
  1627.  
  1628. end.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement