PageRenderTime 28ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 1ms

/vortex.pas

http://github.com/lookias/ProSnooper
Pascal | 2341 lines | 1709 code | 274 blank | 358 comment | 155 complexity | 95ae053df02f17d635563703f000f86f MD5 | raw file
  1. unit vortex;
  2. {
  3. Allabagitta Soft Presents.
  4. TVortex v2.8.5 by joepezT
  5. http://vortex.berzerk.net
  6. IRC: joepezT @ undernet : #Delphi
  7. ICQ: 340148, 3941292
  8. Email: Gothic(a)bluezone.no (Primary mail) - (a) = @
  9. vortex(a)berzerk.net (questions regarding this component)
  10. TVortex is an OpenSource IRC component by joepezt
  11. Feel free to use it on whatever you want, send me bug fixes & suggestions
  12. and or just help me develop it.
  13. note: I have changed alot of the event name to more logical names
  14. also I am in the work of adding "before" events.
  15. hope it wont make much problems for you ;)
  16. many options is now available under
  17. vortex.IrcOptions.ircnick
  18. vortex.ctcpoptions.versionreply... etc etc
  19. If you plan to use it in your own application,
  20. please write somewhere that you use vortex, and link to my pages..
  21. and i also want a copy and test it :)
  22. you might also put a "Powered by Vortex" on your project ;)
  23. I would also like to have your projects posted on my page, eighter the
  24. whole compiled project and or a link to it. or even a small description
  25. of it.
  26. If anyone of you find and fixes a bug, please send them back to me
  27. vortex@berzerk.net. just use "vortex" as subject
  28. IRC Related information
  29. RFC1459 : http://vortex.berzerk.net/rfc1459.html
  30. Last minute news:
  31. There might be a bug if you get kicked, which somehow stops you from parsing the strings,
  32. This might also reside in the topic area..
  33. other bug in the topic is the first time you join you seem to get the nick and timestamp.
  34. _____________________________________________________
  35. these peoples have contributed to the Vortex Project:
  36. (In no particular order)
  37. Guano,
  38. Cubud : I could not start on this if it werent for you ;)
  39. specially the component writings.
  40. Acryl : See annotations marked with "Acryl"
  41. WolfMan : some suggestions,
  42. + some other people i do not have the names from.
  43. }
  44. {$D+}
  45. interface
  46. uses
  47. {$IFDEF WIN32}
  48. Classes, Controls, Windows, wsocket, SysUtils, dialogs, VortexChannels;
  49. {$ELSE}
  50. { Linux Kylix }
  51. Classes, IcsSocket, SysUtils, VortexChannels;
  52. {$ENDIF}
  53. type
  54. TjpNetEvents = class(Tobject)
  55. { commands which will be triggered from the server }
  56. end;
  57. TStartEvent = procedure of object;
  58. TError = procedure (Sender : Tobject; Error : word) of object;
  59. TBGException = procedure (Sender : Tobject; E : Exception; Var CanClose : boolean) of Object;
  60. TServerError = procedure (ErrorString : string) of object;
  61. TServerMsg = procedure (Command : string) of object;
  62. type
  63. TjpAfterEvents = class(Tobject)
  64. { commands which will be triggered AFTER you send them OR from the server }
  65. end;
  66. TAfterServerPing = procedure of object;
  67. TAfterDisconnect = procedure of object;
  68. TAfterConnect = procedure of object;
  69. TAfterNickChanged = procedure (Oldnick, Newnick : string) of object; { me }
  70. TAfterNickChange = procedure (Oldnick, Newnick : string) of object; { not me }
  71. TAfterNotify = procedure (NotifyUsers : string) of object;
  72. TAfterTopic = procedure (ChannelName,Nickname,Topic : string) of object;
  73. TAfterKicked = procedure (Nickname, Channel, Reason : string) of object;
  74. TAfterJoin = procedure (Nickname, Hostname,Channel : string) of object;
  75. TAfterJoined = procedure (Channelname : string) of object;
  76. TAfterParted = procedure (Channelname : string) of object;
  77. TAfterPart = procedure (Nickname,Hostname,Channelname,Reason : string) of object;
  78. TAfterChannelMsg = procedure (Channelname,Content,Nickname, Ident, Mask : string) of object;
  79. TAfterPrivmsg = procedure (Nickname, Ident, Mask, Content : string) of object;
  80. TAfterCtcp = procedure (Nickname, Command, Destination : string) of object; // Acryl : Modified ( see DataReceive-Handler for explanation )
  81. TAfterMode = procedure (Nickname, Destination, Mode : string) of object;
  82. TAfterUserKick = procedure (KickedUser, Kicker, Channel, Reason : string) of object;
  83. TAfterIrcAction = procedure (NickName, Content, Destination : string) of Object; // Acryl : added
  84. TAfterNickInUse = procedure (Nickname : string) of object;
  85. TAfterNoSuchNick = procedure (Value : string) of object;
  86. TAfterNotice = procedure (Nick, Content : string) of object;
  87. TAfterInvited = procedure (NickName, Channel : string) of ObjecT; // Acryl : added
  88. TAfterUserQuit = procedure (Nickname,Reason : string) of object;
  89. TAfterWho = procedure (Channel, Nickname,Username,Hostname, Name, Servername,status,other : string; EndOfWho : boolean) of object;
  90. TAfterChannelList = procedure (ChannelName, Topic : string; Users : integer; EndOfList : boolean) of object;
  91. TAfterNames = procedure (Commanicks, Channel : string; endofnames : boolean) of object;
  92. TAfterWhois = procedure (Info : string; EndOfWhois : boolean) of object;
  93. TAfterMotd = procedure (Line : string; EndOfMotd : boolean) of object;
  94. type
  95. TjpBeforeSend = class(Tobject)
  96. { commands which will be triggered BEFORE you send them to the server }
  97. end;
  98. TBeforeDisconnect = procedure of object;
  99. TBeforeConnect = procedure (Ircserver,Ircport : string);
  100. TBeforeQuit = procedure (Reason : string) of object;
  101. TBeforeQuote = procedure (raw : string) of object;
  102. TBeforeJoin = procedure (Channelname : string) of object;
  103. TBeforePart = procedure (Channelname : string) of object;
  104. TBeforeMode = procedure (Nickname, Commands, parameters : string) of object;
  105. TBeforeTopic = procedure (Channelname, Topic : string) of object;
  106. TBeforePrivmsg = procedure (Destination, Content : string) of object;
  107. TBeforeNotice = procedure (Destination, Content : string) of object;
  108. TBeforeNickChange = procedure (Oldnick, Newnick : string) of object;
  109. type
  110. TjpDirectClientEvents = class(Tobject)
  111. { Used for DCC handling
  112. Sending is not complete yet }
  113. end;
  114. TDccChatIncoming = procedure (Nickname, Port,Address : string) of object;
  115. TDccChatOutgoing = procedure (Nickname, Port,Address : string) of object;
  116. TDccSendResume = procedure (Nickname, Filename, Port, Position : string) of object;
  117. TDccGetResume = procedure (Nickname, Filename, Port, Position : string) of object;
  118. TDccSend = procedure (Nickname, Port,Address, Filename, Filesize : string) of object;
  119. TDccGet = procedure (Nickname, Port,Address, Filename, Filesize : string) of object;
  120. { IdentD/Auth server }
  121. type
  122. TAuthOptions = class(TPersistent)
  123. private
  124. FSystem : string;
  125. FIdent : string;
  126. FAnswer : boolean;
  127. FEnabled : boolean;
  128. {$IFDEF WIN32}
  129. FAuthServer : TWSocket;
  130. {$ELSE}
  131. FAuthServer : TIcsSocket;
  132. {$ENDIF}
  133. protected
  134. procedure OnIdentDserverSessionAvailable(Sender: TObject; Error: Word);
  135. public
  136. procedure Assign(Source : TPersistent); override;
  137. procedure StartAuth;
  138. procedure StopAuth;
  139. published
  140. property System : string read FSystem write FSystem;
  141. property Ident : string read FIdent write FIdent;
  142. property UseAuth : Boolean read FEnabled write FEnabled; { to start the service }
  143. property Enabled : Boolean read FAnswer write FAnswer; { to answer on requests. }
  144. end;
  145. TAuthConnect = procedure (host : string) of object;
  146. { some component expanded options }
  147. type
  148. TIrcOptions = class(TPersistent)
  149. private
  150. FServerHost : string;
  151. FServerPort : string;
  152. FUserNick : string;
  153. FUserPass : string;
  154. FUserName : string;
  155. FUserIdent : string;
  156. FQuitMessage : string;
  157. public
  158. procedure Assign(Source : TPersistent); override;
  159. published
  160. property GetServerHost : string read FServerHost;
  161. property GetServerPort : string read FServerPort;
  162. property GetUserNick : string read FUserNick;
  163. property GetUserPass : string read FUserPass;
  164. property GetUserName : string read FUserName;
  165. property GetUserIdent : string read FUserIdent;
  166. property SetServerHost : string write FServerHost;
  167. property SetServerPort : string write FServerPort;
  168. property SetUserNick : string write FUserNick;
  169. property SetUserPass : string write FUserPass;
  170. property SetUserName : string write FUserName;
  171. property SetUserIdent : string write FUserIdent;
  172. property ServerHost : string read FServerHost write FServerHost;
  173. property ServerPort : string read FServerPort write FServerPort;
  174. property UserName : string read FUserName write FUserName;
  175. property UserIdent : string read FUserIdent write FUserIdent;
  176. property MyNick : string read FUserNick write FUserNick;
  177. property Password : string read FUserPass write FUserPass;
  178. property DefaultQuitMessage : string read FQuitMessage write FQuitMessage;
  179. end;
  180. type
  181. TCtcpOptions = class(TPersistent)
  182. private
  183. FVersionReply : string;
  184. FTimeReply : string;
  185. FFingerReply : string;
  186. FPingReply : string;
  187. FClientInfo : string;
  188. {FUnknownReply : string;}
  189. FReplyToPing : boolean;
  190. FReplyToCtcp : boolean; { if we decide not to reply at all }
  191. public
  192. procedure Assign(Source : TPersistent); override;
  193. published
  194. property GetVersionInfo : string read FVersionReply;
  195. property GetTimeReply : string read FTimeReply;
  196. property GetFingerReply : string read FFingerReply;
  197. property GetPingReply : string read FPingReply;
  198. property VersionReply : string read FVersionReply write FVersionReply;
  199. property TimeReply : string read FTimeReply write FTimeReply;
  200. property FingerReply : string read FFingerReply write FFingerReply;
  201. property PingReply : string read FPingReply write FPingReply;
  202. property ReplyOnPing : Boolean read FReplyToPing write FReplyToPing;
  203. property AnswerCtcps : Boolean read FReplyToCtcp write FReplyToCtcp;
  204. end;
  205. type
  206. TSocksOptions = class(TPersistent)
  207. private
  208. FSocksLevel : string;
  209. FSocksPort : string;
  210. FSocksServer : string;
  211. FSocksPassword : string;
  212. FSocksUserCode : string;
  213. FSocksAuthentication : TSocksAuthentication;
  214. public
  215. published
  216. property SocksPort : string read FSocksPort write FSocksPort;
  217. property SocksServer : string read FSocksServer write FSocksServer;
  218. property SocksPassword : string read FSocksPassword write FSocksPassword;
  219. property SocksLevel : string read FSocksLevel write FSocksLevel;
  220. property SocksUserCode : string read FSocksUserCode write FSocksUserCOde;
  221. property SocksAuthentication : TSocksAuthentication read FSocksAuthentication write FSocksAuthentication;
  222. end;
  223. { Main component }
  224. Type
  225. TVortex = class(TComponent)
  226. private
  227. { expanded properties }
  228. FIrcOptions : TIrcOptions;
  229. FCtcpOptions : TCtcpOptions;
  230. FSocksOptions : TSocksOptions;
  231. FAuthOptions : TAuthOptions;
  232. { some variuables }
  233. FCurrServer : string; // Which server are we connected to ?
  234. FConnected : boolean; // Am I connected (?)
  235. {$IFDEF WIN32}
  236. FClient : TwSocket;
  237. {$ELSE}
  238. FClient : TIcsSocket;
  239. {$ENDIF}
  240. { DCC Related events }
  241. FDccGet : TDCCGet;
  242. FDccGetResume : TDCCGetResume;
  243. FDccSend : TDCCGet;
  244. FDccSendResume : TDCCGetResume;
  245. FDccChatIncoming : TDccChatIncoming;
  246. FDccChatOutgoing : TDccChatIncoming;
  247. { All below is IRC Related and triggered before }
  248. FBeforeQuote : TBeforeQuote;
  249. FBeforeConnect : TBeforeConnect;
  250. FBeforeDisconnect : TBeforeDisconnect;
  251. FBeforeQuit : TBeforeQuit;
  252. FBeforeJoin : TBeforeJoin;
  253. FBeforeTopic : TBeforeTopic;
  254. FBeforePart : TBeforePart;
  255. FBeforePrivmsg : TBeforePrivmsg;
  256. FBeforeNickChange : TBeforeNickChange;
  257. FBeforeNotice : TBeforeNotice;
  258. FBeforeMode : TBeforeMode;
  259. { All below is IRC Related and triggered after something }
  260. FAfterNickChanged : TAfterNickChanged;
  261. FAfterDisconnect : TAfterDisconnect;
  262. FAfterTopic : TAfterTopic;
  263. FAfterMode : TAfterMode;
  264. FAfterKicked : TAfterKicked;
  265. FAfterJoin : TAfterjoin;
  266. FAfterParted : TAfterParted;
  267. FAfterConnect : TAfterConnect;
  268. FAfterChannelMsg : TAfterChannelMsg;
  269. FAfterChannelList : TAfterChannelList;
  270. FAfterNoSuchNick : TAfterNoSuchNick;
  271. FAfterCtcp : TAfterCtcp;
  272. FAfterNotify : TAfterNotify;
  273. FAfterUserKick : TAfterUserKick;
  274. FAfterjoined : TAfterJoined;
  275. FAfterServerPing : TAfterServerPing;
  276. FAfterNotice : TAfterNotice;
  277. FAfterWhois : TAfterWhois;
  278. FAfterWho : TAfterwho;
  279. FAfterPart : TAfterPart;
  280. FAfterNickChange : TAfterNickChange;
  281. FAfterUserQuit : TAfterUserQuit;
  282. FAfterNickInUse : TAfterNickInUse;
  283. FAfterNames : TAfterNames;
  284. FAfterPrivMsg : TAfterPrivMsg;
  285. FAfterMotd : TAfterMotd; { Message of the day }
  286. FAfterircAction : TAfterIrcAction;
  287. FAfterInvited : TAfterInvited;
  288. FError : TError;
  289. FServerMsg : TServerMsg;
  290. FServerError : TServerError;
  291. FStart : TStartEvent;
  292. FBgException : TBGException;
  293. { these are executed when you join part got kicked... }
  294. procedure SetIRCMode (destination, command, parameters: string);
  295. procedure Parted (Nickname, HostName, UserName, ChannelName, Reason : string);
  296. procedure Joined (Nickname, ChannelName,HostName : string);
  297. procedure Kicked (Victim, BOFH, Channel, Reason : string);
  298. procedure Quited (Nickname, user, host, reason : string);
  299. procedure NamesChan (ChannelName, CommaNicks : string; EndOfNames : boolean);
  300. procedure NickChange (OldNick, Newnick : string);
  301. procedure Messages (Line, nick, host, user, destination, Content : string);
  302. procedure CTCPMessage (Line, nick, host, user, destination, Content : string);
  303. procedure ChannelTopic (ChannelName, UserName, Topic : string);
  304. procedure ChannelTopicSetBy (ChannelName, Nickname : string);
  305. { Mask is always the param (format: Nickname!Ident@some.host.com) }
  306. function GetNickFromMask (S : string) : string; // e.g. Vortex2345
  307. function GetHostmaskFromMask (S : string) : string; // e.g. vortex@dialup23123.Dubplates.org
  308. function GetIdentFromMask (S : string) : string; // e.g. My Vortex name
  309. function GetHostFromMask (S : string) : string;
  310. procedure SetIrcOptions(const Value: TIrcOptions);
  311. procedure SetCtcpOptions(const Value: TCtcpOptions);
  312. procedure SetSocksOptions(const Value: TSocksOptions);
  313. procedure SetAuthOptions(const Value: TAuthOptions);
  314. procedure SetupSocket(ConnectToServer : boolean);
  315. protected
  316. procedure OnConnectDataAvailable(Sender: TObject; Error: Word);
  317. procedure OnSocketDataAvailable(Sender: TObject; Error: Word);
  318. procedure OnSocketClosed(Sender: TObject; Error: Word);
  319. procedure OnSocketConnected(Sender: TObject; Error: Word);
  320. procedure OnVortexIRCError (Sender: TObject);
  321. procedure OnVortexBgException(Sender: TObject; E: Exception; var CanClose: boolean);
  322. public
  323. FChannels : Tlist; { A List containing our channels.. }
  324. constructor Create(AOwner : TComponent); override;
  325. destructor Destroy; override;
  326. procedure Loaded; override;
  327. { first thing sent to IRC when you connect. should not be used by user..}
  328. procedure genericparser (socketmessage : string);
  329. function User(nick, user, ConnectMethod, realname : string) : string;
  330. function Between(S,Start,stop:string) : string;
  331. function LongIP(IP : string) : string; { Acryl : Modified }
  332. function ShortIP(const S: string) : string; { Acryl : Modified }
  333. { user commands goes here... }
  334. procedure InitDCCsendResume(nick, port, Position : string);
  335. procedure InitDCCchat (nick, port, address : string);
  336. procedure InitDCCsend (nick, port, address, filename, filesize : string);
  337. procedure InitDCCGet(nick, port,address, filename, filesize : string);
  338. procedure InitDCCGetResume(nick, port, Position : string);
  339. { Raw Commands (quote and raw is the same.. ) }
  340. procedure Quote (_Quote : string);
  341. procedure Raw (_raw : string);
  342. procedure NoticeChannelOps (DestinationChannel,Content : string);
  343. procedure Notice (destination, content : string);
  344. procedure Say (destination, content : string);
  345. procedure SendCTCP (nick, command : string);
  346. procedure CtcpReply (nick, command : string);
  347. procedure Join (channel,key : string);
  348. procedure Part (channel,reason : string);
  349. procedure Quit (reason : string);
  350. procedure Kick (Victim, channel, Reason : string);
  351. procedure Ban (nick, mask, channel : string);
  352. procedure Op (nick, channel : string);
  353. procedure Deop (nick, channel : string);
  354. procedure Voice (nick, channel : string);
  355. procedure DeVoice (nick, channel : string);
  356. procedure Topic (channel, Topic : string);
  357. { Request change nick on IRC }
  358. procedure Nick(newnick : string);
  359. { Info commands...}
  360. procedure ListChannels (max,min : integer);
  361. procedure who (mask : string);
  362. procedure whowas (nick : string);
  363. procedure whois (nick,server : string);
  364. { Connect is used by the Server procedure.. }
  365. procedure connect;
  366. procedure Server (server,ircport : string);
  367. procedure Disconnect (force : boolean; reason : string);
  368. { Misc commands }
  369. procedure SetCurrentServer (Value : string);
  370. procedure SetVersionInfo (Info : string);
  371. procedure SetMyUserName (Value : string);
  372. procedure SetIRCPort (Value : string);
  373. procedure SetIRCName (Value : string);
  374. procedure SetMyNick (Nickname : string); // This one does NOT change your nick on IRC
  375. function LocalIP (num : byte) : string;
  376. function IsNumeric (Value : string) :boolean;
  377. { Channel Related }
  378. procedure ClearUsersInChannel (value : string);
  379. function FindChannelID (AChannel : string) : integer;
  380. function CountUsersFromChannel (Value : string) : integer;
  381. function GetChannelTopic (value : string) : string;
  382. function GetTopicSetBy (value : string) : string;
  383. function GetUsersFromChannel (Value : string) : string;
  384. published
  385. property GetCurrentServer : string Read FCurrServer;
  386. property IsConnected : boolean Read FConnected;
  387. { sub items }
  388. property IrcOptions : TIrcOptions read FIrcOptions write SetIrcOptions;
  389. property CtcpOptions : TCtcpOptions read FCtcpOptions write SetCtcpOptions;
  390. property SocksOptions : TSocksOptions read FSocksOptions write SetSocksOptions;
  391. property AuthOptions : TAuthOptions read FAuthOptions write SetAuthOptions;
  392. { User-defined event handlers }
  393. property BeforeQuote : TBeforeQuote read FBeforeQuote write FBeforeQuote;
  394. property BeforeDisconnect : TBeforeDisconnect read FBeforeDisconnect write FBeforeDisconnect;
  395. property BeforeQuit : TBeforeQuit read FBeforeQuit write FBeforeQuit;
  396. property BeforeJoin : TBeforeJoin read FBeforeJoin write FBeforeJoin;
  397. property BeforeTopic : TBeforeTopic read FBeforeTopic write FBeforeTopic;
  398. property BeforePart : TBeforePart read FBeforePart write FBeforePart;
  399. property BeforePrivateMessage: TBeforePrivmsg read FBeforePrivmsg write FBeforePrivmsg;
  400. property BeforeNickChange : TBeforeNickChange read FBeforeNickChange write FBeforeNickChange;
  401. property BeforeNotice : TBeforeNotice read FBeforeNotice write FBeforeNotice;
  402. property BeforeMode : TBeforeMode read FBeforeMode write FBeforeMode;
  403. property AfterPrivateMessage : TAfterprivMsg read FAfterPrivmsg write FAfterPrivmsg;
  404. property AfterUserJoin : TAfterJoin read FAfterJoin write FAfterJoin;
  405. property AfterJoined : TAfterjoined read FAfterJoined write FAfterJoined;
  406. property AfterUserPart : TAfterPart read FAfterPart write FAfterPart;
  407. property AfterParted : TAfterParted read FAfterParted write FAfterParted;
  408. property AfterTopic : TAfterTopic read FAfterTopic write FAfterTopic;
  409. property AfterUserQuit : TAfterUserQuit read FAfterUserQuit write FAfterUserQuit;
  410. property AfterUserKick : TAfterUserKick read FAfterUserKick write FAfterUserKick;
  411. property AfterKicked : TAfterKicked read FAfterKicked write FAfterKicked;
  412. property AfterCtcp : TAfterCtcp read FAfterCtcp write FAfterCtcp;
  413. property AfterUserNickChange : TAfterNickChange read FAfterNickChange write FAfterNickChange;
  414. property AfterNickChanged : TAfterNickChanged read FAfterNickChanged write FAfterNickChanged;
  415. property AfterStarted : TStartEvent read FStart write FStart;
  416. property AfterAction : TAfterIrcAction read FAfterIrcAction write FAfterIrcAction; {Acryl : added}
  417. property AfterInvited : TAfterInvited read FAfterInvited write FAfterInvited; {Acryl : added}
  418. property AfterServerPing : TAfterServerPing read FAfterServerPing write FAfterServerPing;
  419. property OnNoSuchNickChannel : TAfterNoSuchNick read FAfterNoSuchNick write FAfterNoSuchNick;
  420. property OnChannelMessage : TAfterChannelmsg read FAfterChannelMsg write FAfterChannelMsg;
  421. property OnQuoteServer : TServerMsg read FServerMsg write FServerMsg;
  422. property OnServerError : TServerError read FServerError write FServerError;
  423. property OnNickInUse : TAfterNickInUse read FAfterNickInUse write FAfterNickInUse;
  424. property OnNotice : TAfterNotice read FAfterNotice write FAfterNotice;
  425. property OnNotify : TAfterNotify read FAfterNotify write FAfterNotify;
  426. property OnNames : TAfterNames read FAfterNames write FAfterNames;
  427. property OnWhois : TAfterWhois read FAfterWhois write FAfterWhois;
  428. property OnMOTD : TAfterMotd read FAfterMotd write FAfterMotd;
  429. property OnList : TAfterChannelList read FAfterChannelList write FAfterChannelList;
  430. property OnMode : TAfterMode read FAfterMode write FAfterMode;
  431. property OnWho : TAfterWho read FAfterWho write FAfterWho;
  432. { DCC related events, you can use them with my other components }
  433. property OnDCCFileReceive : TDCCGet read FDCCGet write FDCCGet;
  434. property OnDCCFileResume : TDCCGetResume read FDCCGetResume write FDCCGetResume;
  435. property OnDCCChat : TDccChatIncoming read FDccChatIncoming write FDccChatIncoming;
  436. { Socket related stuff }
  437. property OnDisconnect : TAfterDisconnect Read FAfterDisconnect write FAfterDisconnect;
  438. property OnConnect : TAfterConnect Read FAfterConnect write FAfterConnect;
  439. Property OnError : Terror Read FError write FError;
  440. Property OnBgException : TBgException Read FBGException write FBGException;
  441. end;
  442. procedure Register;
  443. implementation
  444. ////////////////////////////////////////////////////////////////////////////////
  445. ////////////////////////// Misc constants //////////////////////////////////////
  446. ////////////////////////////////////////////////////////////////////////////////
  447. Const
  448. MWG_VERSION_MAJOR = '2';
  449. MWG_VERSION_MINOR = '8';
  450. MWG_VERSION_TAG = 'Vortex IRC component for Delphi';
  451. CrLf = #13#10;
  452. ChannelPrefix = '#!&+'; { <- # = Normal channels ! = Secure channels (?)
  453. & = Local channels + = Mode less channels }
  454. Commands: Array [0..33] of integer =
  455. (324,329, // get MODE
  456. 301,311,312,313,317,318,319, // Whois return codes
  457. 401,433,303, // Nickname in use, IsON
  458. 315,352, // who...
  459. 332,333, // topic set
  460. 353,366, // names / end of.
  461. 321,322,323,324, // Channel Listing
  462. 250,251,252,253,254,255, // Motd stuff
  463. 265,266,373,372,375,376 // ----"----
  464. );
  465. {
  466. // uncomment this if you are using Delphi 4 or older)
  467. procedure FreeAndNil(var Value: TObject);
  468. begin
  469. Value.Free;
  470. Value := nil;
  471. end;
  472. }
  473. { Match the different IRC Numeric commands }
  474. function match (cmd: string) : integer;
  475. var
  476. i : integer;
  477. begin
  478. i := 0;
  479. while i <= High(Commands) do
  480. begin
  481. if Cmd = inttostr(Commands[i]) then
  482. begin
  483. Result := commands[i];
  484. exit;
  485. end;
  486. Inc(I);
  487. end;
  488. result := -1;
  489. end;
  490. procedure Register;
  491. begin
  492. RegisterComponents('joepezT', [Tvortex]);
  493. end;
  494. {
  495. ------------------------------------------------------------------
  496. Constructor / Destructor
  497. ------------------------------------------------------------------
  498. }
  499. { TVortex }
  500. function TVortex.IsNumeric( Value:String ):boolean;
  501. var
  502. Code : integer;
  503. Tmp : integer;
  504. begin
  505. { check if a value really is a value }
  506. Val ( Value, tmp, Code );
  507. Result := Code = 0;
  508. end;
  509. procedure Tvortex.SetupSocket(ConnectToServer : boolean);
  510. begin
  511. if assigned(FClient) then
  512. Fclient.Free;
  513. {$IFDEF WIN32} FClient := TWSocket.Create(Self);
  514. {$ELSE} FClient := TIcsSocket.Create(Self);{$ENDIF}
  515. with FIrcOptions do
  516. With FSocksOptions do
  517. With FClient do
  518. Begin
  519. if assigned(FBeforeConnect) then
  520. FBeforeConnect(GetServerHost, GetServerPort);
  521. if GetServerPort = '' then SetServerPort := '6667';
  522. if trim(GetServerHost) = '' then exit; { exit if there is no address specified }
  523. OnDataAvailable := OnConnectDataAvailable;
  524. OnSessionClosed := OnSocketClosed;
  525. OnError := OnvortexIRCError;
  526. OnBgException := OnVortexBgException;
  527. OnSessionConnected := OnSocketConnected;
  528. LineEdit := False;
  529. LineEcho := False;
  530. LineMode := True;
  531. LineEnd := #13#10;
  532. Proto := 'tcp';
  533. Port := FIrcOptions.GetServerPort;
  534. Addr := FIrcOptions.GetServerHost;
  535. SocksPort := FsocksPort;
  536. SocksServer := FSocksServer;
  537. Sockspassword := FSocksPassword;
  538. SocksLevel := FSocksLevel;
  539. SocksUserCode := FSocksUserCode;
  540. {SocksAuthentication := TSocksAuthentication;}
  541. if ConnectToServer then
  542. Connect;
  543. end;
  544. end;
  545. Constructor Tvortex.Create(AOwner: TComponent);
  546. Begin
  547. Inherited Create(Aowner);
  548. FIrcOptions := TIrcOptions.Create;
  549. FCtcpOptions := TCtcpOptions.Create;
  550. FSocksOptions := TSocksOptions.Create;
  551. FAuthOptions := TAuthOptions.Create;
  552. with FIrcOptions do
  553. with FAuthOptions do
  554. with FCtcpOptions do
  555. begin
  556. if GetServerHost = '' then SetServerHost := 'stockholm.se.eu.undernet.org';
  557. if GetServerPort = '' then SetServerPort := '6667';
  558. if GetUserName = '' then SetUserName := 'IRC Component';
  559. if GetUserIdent = '' then SetUserIdent := 'Vortex';
  560. if GetUserNick = '' then SetUserNick := 'Vortex' + inttostr(random(999));
  561. if GetUserPass = '' then SetUserPass := '';
  562. if FSystem = '' then FSystem := 'UNIX';
  563. if FIdent = '' then FSystem := 'Vortex';
  564. if FFingerReply = '' then FFingerReply := 'FooBar';
  565. if FClientInfo = '' then FClientInfo := format('CLIENTINFO Vortex engine, version: %s %s %s',[MWG_VERSION_MAJOR,MWG_VERSION_MINOR,MWG_VERSION_TAG]);
  566. end;
  567. SetVersionInfo(format('Vortex - v%s.%s.',[MWG_VERSION_MAJOR,MWG_VERSION_MINOR]));
  568. If not (csDesigning in ComponentState) Then
  569. Begin
  570. Fchannels := TList.create;
  571. {SetupSocket(false);}
  572. end;
  573. End;
  574. Destructor Tvortex.Destroy;
  575. Begin
  576. If not (csDesigning in ComponentState) Then
  577. Begin
  578. FreeAndNil(FClient);
  579. FreeAndNil(Fchannels);
  580. with FAuthOptions do
  581. begin
  582. FreeAndNil(FAuthServer);
  583. end;
  584. End;
  585. inherited Destroy();
  586. End;
  587. procedure Tvortex.Loaded();
  588. Begin
  589. Inherited Loaded();
  590. If not (csDesigning in ComponentState) Then
  591. begin
  592. { if we decide to use identd server }
  593. With FAuthOptions do
  594. begin
  595. if FEnabled = true then
  596. StartAuth;
  597. end;
  598. If Assigned(FStart) Then FStart();
  599. end;
  600. End;
  601. ////////////////////////////////////////////////////////////////////////////////
  602. // String manipulation functions
  603. // Great string manipulation which i got from Wolfman :)
  604. ////////////////////////////////////////////////////////////////////////////////
  605. function Tvortex.Between(S,Start,stop:string):string;
  606. Var P1,P2:integer;
  607. Begin
  608. P1:=Pos(start,s);
  609. P2:=pos(stop,s);
  610. Result:=copy(s,p1+1,p2-p1-1);
  611. End;
  612. function Tvortex.shortIP(const S: string): string;
  613. Var
  614. IP : int64;
  615. A, B, C, D : Byte;
  616. Begin
  617. {
  618. ShortIP
  619. Example: 3232235777 -> 192.168.1.1
  620. }
  621. IP := StrToInt64(S);
  622. A := (IP and $FF000000) shr 24;
  623. B := (IP and $00FF0000) shr 16;
  624. C := (IP and $0000FF00) shr 8;
  625. D := (IP and $000000FF);
  626. Result := Format('%d.%d.%d.%d', [A, B, C, D]);
  627. End;
  628. { Long IP converted by joepezt }
  629. function Tvortex.LongIP(IP : string) : string;
  630. var
  631. IPaddr : array[1..4] of integer;
  632. temp : string;
  633. res : Longword;
  634. i : integer;
  635. begin
  636. temp := ip;
  637. temp := temp + '.';
  638. for i := 1 to 4 do
  639. begin
  640. try
  641. ipaddr[i] := strtoint(copy(temp,1,pos('.',temp) - 1));
  642. delete(temp,1,pos('.',temp));
  643. if ipaddr[i] > 255 then raise exception.Create('');
  644. except
  645. result := 'Invalid IP address.';
  646. exit;
  647. end;
  648. end;
  649. res := (ipaddr[1] * $FFFFFF) + ipaddr[1] + (ipaddr[2] * $FFFF) + ipaddr[2] + (ipaddr[3] * $FF) + ipaddr[3] + (ipaddr[4]);
  650. result := format('%u',[res]);
  651. end;
  652. ////////////////////////////////////////////////////////////////////////////////
  653. // Command parsers by Acryl
  654. ////////////////////////////////////////////////////////////////////////////////
  655. function Tvortex.GetNickFromMask(S : string) : string;
  656. Var
  657. C : integer;
  658. TmpString : string;
  659. Begin
  660. S := Trim(S);
  661. If (Length(S) = 0) Then Exit;
  662. TmpString := '';
  663. For C:=1 To Length(S) Do
  664. Begin
  665. If (S[C] = '!') Then break;
  666. TmpString := TmpString + S[C];
  667. End;
  668. Result := TmpString;
  669. end;
  670. function Tvortex.GetIdentFromMask(S : string) : string;
  671. Var
  672. C : integer;
  673. Copying : boolean;
  674. TmpString : string;
  675. Begin
  676. S := Trim(S);
  677. If (Length(S) = 0) Then Exit;
  678. TmpString := '';
  679. Copying := False;
  680. For C:=1 To Length(S) Do
  681. Begin
  682. If (S[C] = '@') Then break;
  683. If (S[C] = '!') Then Copying := True
  684. else If (Copying) Then TmpString := TmpString + S[C];
  685. End;
  686. Result := TmpString;
  687. end;
  688. function Tvortex.GetHostFromMask(S : string) : string;
  689. Var
  690. C : integer;
  691. Copying : boolean;
  692. TmpString : string;
  693. Begin
  694. S := Trim(S);
  695. If (Length(S) = 0) Then exit;
  696. TmpString := '';
  697. Copying := False;
  698. For C:=1 To Length(S) Do
  699. Begin
  700. If (S[C] = '@') Then Copying := True
  701. else If (Copying) Then TmpString := TmpString + S[C];
  702. End;
  703. Result := TmpString;
  704. end;
  705. function Tvortex.GetHostmaskFromMask(S : string) : string;
  706. Var
  707. C : integer;
  708. Copying : boolean;
  709. TmpString : string;
  710. Begin
  711. S := Trim(S);
  712. If (Length(S) = 0) Then Exit;
  713. TmpString := '';
  714. Copying := False;
  715. For C:=1 To Length(S) Do
  716. Begin
  717. If (S[C] = '!') Then Copying := True
  718. else If (Copying) Then TmpString := TmpString + S[C];
  719. End;
  720. Result := TmpString;
  721. end;
  722. {
  723. -------------------------------------------------------------------
  724. User commands
  725. -------------------------------------------------------------------
  726. }
  727. procedure Tvortex.Quote(_quote : string);
  728. Begin
  729. if assigned(Fclient) then
  730. FClient.sendstr(_quote + crlf);
  731. End;
  732. procedure Tvortex.Raw(_raw : string);
  733. Begin
  734. if assigned(FBeforeQuote) then
  735. Quote(_raw + crlf);
  736. End;
  737. procedure Tvortex.Say(destination, content : string);
  738. Begin
  739. if Assigned(FBeforePrivmsg) then
  740. FBeforePrivmsg(destination, content);
  741. Quote(format('PRIVMSG %s :%s',[destination,content]));
  742. End;
  743. procedure Tvortex.Notice(destination, content : string);
  744. begin
  745. if assigned(FBeforeNotice) then
  746. FBeforeNotice(destination,content);
  747. Quote(format('NOTICE %s :%s',[destination,content]));
  748. end;
  749. procedure Tvortex.NoticeChannelOps(DestinationChannel,
  750. Content: string);
  751. begin
  752. if assigned(FBeforeNotice) then
  753. FBeforeNotice(destinationChannel,content);
  754. { sends this notice to channel ops }
  755. Quote(format('WALLCHOPS %s :%s',[destinationChannel,content]));
  756. end;
  757. procedure Tvortex.whois(nick, server : string);
  758. begin
  759. if server <> '' then
  760. Quote(format('WHOIS %s %s',[nick,server]))
  761. else Quote(format('WHOIS %s',[nick]))
  762. end;
  763. procedure TVortex.listChannels (max,min : integer);
  764. begin
  765. { LIST <3,>1,C<10,T>0 ; 2 users, younger than 10 min., topic set.
  766. probably a better way to do this }
  767. if min <0 then
  768. if max >0 then
  769. begin
  770. Quote(format('List <%d,>%d',[max,min]));
  771. exit
  772. end;
  773. if min >0 then
  774. begin
  775. Quote(format('List >%d',[min]));
  776. exit
  777. end;
  778. if max >0 then
  779. begin
  780. Quote(format('List <%d',[max]));
  781. exit;
  782. end;
  783. end;
  784. procedure Tvortex.who(mask : string);
  785. begin
  786. Quote(format('WHO %s',[Mask]))
  787. end;
  788. procedure Tvortex.whowas(nick : string);
  789. begin
  790. quote(format('WHOWAS %s',[nick]))
  791. end;
  792. procedure Tvortex.Op(nick, channel : string);
  793. begin
  794. if assigned(FBeforeMode) then
  795. FBeforeMode(nick,'op',channel);
  796. Quote(format('MODE %s +oooo %s',[channel,nick]));
  797. end;
  798. procedure Tvortex.Deop(nick, channel : string);
  799. begin
  800. if assigned(FBeforeMode) then
  801. FBeforeMode(nick,'deop',channel);
  802. Quote(format('MODE %s -oooo %s',[channel,nick]));
  803. end;
  804. procedure Tvortex.Voice(nick, channel : string);
  805. begin
  806. if assigned(FBeforeMode) then
  807. FBeforeMode(nick,'voice',channel);
  808. Quote(format('MODE %s +vvvv %s',[channel,nick]));
  809. end;
  810. procedure Tvortex.DeVoice(nick, channel : string);
  811. begin
  812. if assigned(FBeforeMode) then
  813. FBeforeMode(nick,'devoice',channel);
  814. Quote(format('MODE %s -vvvv %s',[channel,nick]));
  815. end;
  816. procedure Tvortex.SetIRCMode(destination, command, parameters : string);
  817. begin
  818. if assigned(FBeforeMode) then
  819. FBeforeMode(Destination,Command,Parameters);
  820. Quote(format('MODE %s %s %s',[destination,command,parameters]));
  821. end;
  822. procedure Tvortex.Ban(nick, mask, channel : string);
  823. begin
  824. { if assigned(FBeforeMode) then
  825. FBeforeMode(Destination,Command,Parameters);}
  826. Quote(format('MODE %s +b %s',[channel,mask]));
  827. end;
  828. procedure Tvortex.Topic(channel, Topic : string);
  829. begin
  830. if assigned(FBeforeTopic) then
  831. FBeforeTopic(channel,topic);
  832. Quote(format('TOPIC %s :%s',[channel,Topic]));
  833. end;
  834. procedure Tvortex.Kick(Victim, channel, Reason : string);
  835. begin
  836. Quote(format('KICK %s %s :%s',[channel,victim,reason]));
  837. end;
  838. procedure Tvortex.join(channel,key : string);
  839. begin
  840. if assigned(FBeforeJoin) then
  841. FBeforeJoin(Channel);
  842. if key <> '' then
  843. Quote(format('Join %s :%s',[channel,key]))
  844. else
  845. Quote(format('Join %s',[channel]))
  846. end;
  847. procedure Tvortex.connect;
  848. begin
  849. SetupSocket(true);
  850. end;
  851. procedure Tvortex.InitDCCchat(nick,port,address : string);
  852. var
  853. CustomLongIP : string;
  854. begin
  855. if port = '' then port := '59';
  856. if address = '' then customlongip := longip(localip(0))
  857. else CustomLongIP := longip(address);
  858. Quote(format('PRIVMSG %s :' + #1 + 'DCC CHAT chat %s %s' + #1,[nick, CustomLongIP,port]));
  859. end;
  860. procedure Tvortex.InitDCCsend(nick, port,Address, filename, filesize : string);
  861. var
  862. CustomLongIP : string;
  863. begin
  864. if port = '' then port := '59';
  865. if address = '' then customlongip := longip(localip(0))
  866. else CustomLongIP := longip(address);
  867. Quote(format('PRIVMSG %s :' + #1 + 'DCC SEND "%s" %s %s %s' + #1,[nick,filename, CustomLongIP, port, filesize]));
  868. end;
  869. procedure TVortex.InitDCCsendResume(nick, port, Position : string);
  870. begin
  871. Quote(format('PRIVMSG %s :' + #1 + 'DCC RESUME file.ext %s %s',[nick, port, position]));
  872. end;
  873. procedure Tvortex.Part(channel,reason : string);
  874. begin
  875. if assigned(FBeforePart) then
  876. FBeforePart(channel);
  877. if reason <> '' then
  878. Quote(format('part %s :%s',[channel,reason]))
  879. else Quote(format('part %s',[channel]))
  880. end;
  881. procedure Tvortex.Quit(reason : string);
  882. Begin
  883. { change it to whatever you want }
  884. if assigned(FBeforeQuit) then
  885. FBeforeQuit(reason);
  886. If (trim(Reason) = '') Then
  887. Reason := FIrcOptions.DefaultQuitMessage;
  888. Quote(format('QUIT :%s',[reason]));
  889. End;
  890. procedure Tvortex.SendCTCP(nick, command : string);
  891. Begin
  892. Quote(format('PRIVMSG %s :%s%s',[nick,#1,command]));
  893. End;
  894. procedure Tvortex.CtcpReply(nick, command : string);
  895. Begin
  896. Quote(format('NOTICE %s :%s%s%s',[nick,#1,command,#1]));
  897. End;
  898. procedure Tvortex.Disconnect(force : boolean; reason : string);
  899. var
  900. i : integer;
  901. Begin
  902. if assigned(FBeforeDisconnect) then
  903. FBeforeDisconnect;
  904. If (not force) Then Quit(reason)
  905. Else FClient.close;
  906. FConnected := False;
  907. With Fchannels do
  908. begin
  909. if assigned(Fchannels) then
  910. begin
  911. for i := 0 to count -1 do
  912. with Tobject(FChannels[i]) as TChannels do
  913. begin
  914. DeleteUsers;
  915. Fchannels[i] := nil;
  916. end;
  917. FChannels.Clear;
  918. end;
  919. FChannels := TList.create;
  920. end;
  921. End;
  922. procedure Tvortex.Nick(newnick : string);
  923. Begin
  924. Quote(format('NICK %s',[newnick]))
  925. End;
  926. procedure Tvortex.Server(server,ircport : string);
  927. Begin
  928. { connect to IRC, or reconnect... }
  929. if assigned(Fclient) then
  930. begin
  931. If (FConnected) Then Quit('Vortex - Changing server.');
  932. Fconnected := false;
  933. end;
  934. with FIrcOptions do
  935. begin
  936. SetServerHost := server;
  937. SetServerPort := ircport;
  938. SetupSocket(true);
  939. end;
  940. end;
  941. function Tvortex.User(nick, user, ConnectMethod, realname : string) : string;
  942. begin
  943. { 4.1.3 User message | Only used during Authentications
  944. Command: USER
  945. Parameters: <username> <hostname> <servername> <realname>
  946. Quote(format('USER %s %s %s :%s',[nick,user,ConnectMethod,realname]));
  947. Use this procedure if you want to use other clients than ICS
  948. you have to handle socket operations self tho...
  949. procedure Tdata.ClientSocket1Connect(Sender: TObject; Socket: TCustomWinSocket);
  950. begin
  951. socket.SendText(vortex.User('someone','something','-1','hehe:P') + #13#10);
  952. end;
  953. }
  954. With FIrcOptions do
  955. begin
  956. SetUserName := RealName;
  957. SetUserIdent := User;
  958. SetUserNick := nick;
  959. if connectmethod = '-1' then
  960. begin
  961. result := format(
  962. 'PASS %s' + CrLf +
  963. 'NICK %s' + CrLf +
  964. 'USER %s %s %s :%s' + CrLf,[GetUserPass,GetUserNick,GetUserNick,GetUserIdent,localiplist[0],GetUserName]);
  965. exit;
  966. end;
  967. if assigned(Fclient) then begin
  968. Quote(format('PASS %s',[GetUserPass]));
  969. Quote(format('USER %s %s %s :%s',[GetUserIdent,localiplist[0],Fclient.addr,GetUserName]));
  970. end;
  971. end;
  972. end;
  973. procedure Tvortex.OnConnectDataAvailable(Sender: TObject; Error: Word);
  974. var
  975. received : string;
  976. temp : string;
  977. Command : integer;
  978. i : integer;
  979. { On Connect Events
  980. This one is used during connection! }
  981. begin
  982. if not assigned(fclient) then exit;
  983. received := trim(Twsocket(sender).ReceiveStr);
  984. temp := received;
  985. { Trigger server (dataavailable / any data) }
  986. If Assigned(FServerMsg) then
  987. FServerMsg(Received);
  988. { Reply to Server Pings, to avoid disconnection }
  989. If copy(received,1,4) = 'PING' Then
  990. Begin
  991. Quote('PONG ' + copy(received,6,length(received)));
  992. if assigned(FAfterServerPing) then FAfterServerPing;
  993. Exit;
  994. end;
  995. If copy(received,1,5) = 'ERROR' Then
  996. Begin
  997. if assigned(FServerError) then
  998. FServerError(Received);
  999. exit;
  1000. end;
  1001. If copy(received,1,11) = 'NOTICE AUTH' Then
  1002. Begin
  1003. If assigned(FAfterNotice) then
  1004. FAfterNotice('server',copy(received,14,length(received)));
  1005. Exit;
  1006. end;
  1007. { Remove garbage. }
  1008. delete(temp,1,pos(' ',temp));
  1009. delete(temp,pos(' ',temp),length(temp));
  1010. { Ensure temp is a number }
  1011. if isnumeric(temp) then command := strtoint(temp);
  1012. temp := received;
  1013. case command of
  1014. 001..003:
  1015. begin
  1016. if command = 001 then
  1017. begin
  1018. { Grab my nick & Local server name from the start }
  1019. FCurrserver := trim(copy(temp,2,pos(' ',temp)-1));
  1020. for i := 0 to 1 do
  1021. delete(received,1,pos(' ',received));
  1022. SetMyNick(trim(copy(received,1,pos(' ',received))));
  1023. end;
  1024. for i := 0 to 1 do
  1025. delete(temp,1,pos(':',temp));
  1026. if assigned(FAfterMotd) then
  1027. FAfterMotd(temp,false);
  1028. exit;
  1029. end;
  1030. 004,005:
  1031. begin
  1032. { We can extract lots of good information on these lines
  1033. Oslo.NO.EU.undernet.org u2.10.10.pl18.(release) dioswkg biklmnopstv
  1034. SILENCE=15 WHOX WALLCHOPS USERIP CPRIVMSG CNOTICE MODES=6 MAXCHANNELS=10 MAXBANS=30 NICKLEN=9 TOPICLEN=160 KICKLEN=160 CHANTYPES=+#& :are supported by this server
  1035. PREFIX=(ov)@+ CHANMODES=b,k,l,imnpst CHARSET=rfc1459 NETWORK=Undernet :are supported by this server
  1036. }
  1037. { Get Server name }
  1038. SetCurrentServer(copy(temp,2,pos(' ',temp)));
  1039. for i := 1 to 3 do
  1040. delete(temp,1,pos(' ',temp));
  1041. temp := stringreplace(temp,' :',' ', [rfReplaceAll]);
  1042. if assigned(FAfterMotd) then FAfterMotd(trim(temp),false);
  1043. exit;
  1044. end;
  1045. 251..255:
  1046. begin
  1047. if (command = 251) or (command = 255) then
  1048. begin
  1049. for i := 1 to 2 do
  1050. delete(temp,1,pos(':',temp));
  1051. temp := stringreplace(temp,' :',' ', [rfReplaceAll]);
  1052. if assigned(FAfterMotd) then FAfterMotd(temp,false);
  1053. exit;
  1054. end;
  1055. for i := 1 to 3 do
  1056. delete(temp,1,pos(' ',temp));
  1057. temp := stringreplace(temp,' :',' ', [rfReplaceAll]);
  1058. if assigned(FAfterMotd) then FAfterMotd(temp,false);
  1059. exit;
  1060. end;
  1061. 376,422:
  1062. begin
  1063. { Assign all incoming data to alternate events }
  1064. for i := 0 to 1 do
  1065. delete(temp,1,pos(':',temp));
  1066. if assigned(FAfterMotd) then
  1067. FAfterMotd(temp,true);
  1068. with Fclient do
  1069. begin
  1070. LineEnd := crlf;
  1071. OnDataAvailable := OnSocketDataAvailable;
  1072. end;
  1073. exit;
  1074. end;
  1075. { Might be buggy =/ }
  1076. 433: If Assigned(FAfterNickInUse) Then
  1077. with FIrcOptions do
  1078. FAfterNickInUse(GetUserNick);
  1079. end;
  1080. end;
  1081. procedure Tvortex.genericparser (socketmessage : string);
  1082. var
  1083. i,j : integer;
  1084. Received : string;
  1085. Backup : string;
  1086. Channel : string;
  1087. Temp : string;
  1088. CmdFrom : string; // Who sent us this command ?
  1089. CmdName : string; // What command is it ?
  1090. CmdTo : string; // To whom does this go - irgnored most of the time
  1091. CmdMiddle : string; // Possible Middle string;
  1092. CmdAllParams : string; // Everything past :
  1093. Params : Array[0..10] Of String; // just extra parameters, used for temporary strings
  1094. {
  1095. Format of Standart Messages:
  1096. :From MessageType To :Parameters
  1097. From can either be:
  1098. Server.host.address
  1099. Or:
  1100. Nickname!ident@host.mask.com
  1101. Some special messages:
  1102. NOTICE Constant/To :Message
  1103. Constant is e.g. AUTH
  1104. PING :From
  1105. From is server.address.com
  1106. CTCPS are sent as privmsgs delimited by #1 at beginning & end
  1107. Sometimes Messages got the following format:
  1108. :From MessageType To SomethingElseHere :Parameters
  1109. If this is the case "S1omethingElseHere" will be stroed in cmdMiddle
  1110. }
  1111. begin
  1112. received := trim(socketmessage);
  1113. Backup := Received;
  1114. { Quick exit - unlikely but possible still }
  1115. If (Length(Received) = 0) Then exit;
  1116. { Command parsing. }
  1117. { If From is specified ... }
  1118. If (Received[1] = ':') Then
  1119. Begin
  1120. I := Pos(' ', Received);
  1121. If (I > 2) Then CmdFrom := Copy(Received,2,I-2);
  1122. Delete(Received,1,I);
  1123. End;
  1124. { Now get the command name }
  1125. Begin
  1126. I := Pos(' ', Received);
  1127. If (I > 1) Then CmdName := Copy(Received,1,I-1);
  1128. Delete(Received,1,I);
  1129. ENd;
  1130. { Now check if there is an additional constant or "to" }
  1131. If (Received[1] <> ':') Then
  1132. Begin
  1133. I := Pos(' ', Received);
  1134. If (I > 1) Then CmdTo := Copy(Received,1,I-1);
  1135. Delete(Received,1,I);
  1136. End;
  1137. { Now check if there is an additional middle-string }
  1138. If (Received[1] <> ':') Then
  1139. Begin
  1140. I := Pos(' ', Received);
  1141. If (I > 1) Then CmdMiddle := Copy(Received,1,I-1);
  1142. Delete(Received,1,I);
  1143. End;
  1144. { Now the get the rest with out the ":" }
  1145. If (Length(Received) > 1) Then
  1146. If (Received[1] = ':') Then CmdAllParams := Copy(Received,2,Length(Received)-1)
  1147. Else CmdAllParams := Received;
  1148. //////////////////////////////////////////////////////////////////
  1149. ///////////////////////// END OF PARSING /////////////////////////
  1150. //////////////////////////////////////////////////////////////////
  1151. { Restore the original received string. }
  1152. Received := Backup;
  1153. { Trigger server (dataavailable / any data) }
  1154. If Assigned(FServerMsg) then FServerMsg(Received);
  1155. { Reply to Server Pings, to avoid disconnection }
  1156. If (uppercase(cmdName) = 'PING') Then
  1157. Begin
  1158. Quote('PONG ' + cmdAllParams);
  1159. if assigned(FAfterServerPing) then FAfterServerPing;
  1160. Exit;
  1161. end;
  1162. {
  1163. User Joining, (this includes me as well)
  1164. (nickname host channel)
  1165. }
  1166. If (uppercase(cmdName) = 'JOIN') Then
  1167. Begin
  1168. Joined(GetNickFromMask(cmdFrom),cmdAllParams,GetHostmaskFromMask(cmdFrom));
  1169. exit;
  1170. end;
  1171. { User quitting }
  1172. If (uppercase(cmdName) = 'QUIT') Then
  1173. Begin
  1174. {
  1175. (nickname reason)
  1176. :nick!user@host QUIT :reason
  1177. }
  1178. Quited(GetNickFromMask(cmdFrom), GetHostMaskFromMask(CmdFrom), GetIdentFromMask(CmdFrom), cmdAllParams);
  1179. exit;
  1180. end;
  1181. { User parting (this includes me as well)
  1182. (nickname host channel reason) }
  1183. If (uppercase(cmdName) = 'PART') Then
  1184. Begin
  1185. for i := 0 to 1 do { get channelname }
  1186. params[i] := received;
  1187. delete(params[0],1,lastdelimiter('#',received)-1);
  1188. delete(params[0],pos(':',params[0])-1,length(params[1])-1);
  1189. { get part reason }
  1190. for i := 0 to 1 do
  1191. delete(params[1],1,pos(':',params[1]));
  1192. Parted(GetNickFromMask(cmdFrom),GetHostMaskFromMask(CmdFrom),GetIdentFromMask(CmdFrom),params[0],params[1]);
  1193. exit;
  1194. End;
  1195. { This one is very incomplete.. }
  1196. If (uppercase(cmdName) = 'MODE') Then
  1197. Begin
  1198. If Assigned(FAfterMode) Then
  1199. Begin
  1200. If (cmdFrom <> '') Then
  1201. if assigned(FAfterMode) then
  1202. FAfterMode(GetNickFromMask(cmdFrom),CmdTo, cmdAllParams)
  1203. end;
  1204. Exit;
  1205. End;
  1206. {
  1207. There are 2 types of NOTICEs:
  1208. 1. NOTICE Constant :SomeTextHere (coming from server)
  1209. 2. :Nick!ident@host.com NOTICE To :SomeTextHere (coming from user 'nick')
  1210. }
  1211. If (uppercase(cmdName) = 'NOTICE') Then
  1212. Begin
  1213. If Assigned(FAfterNotice) Then
  1214. Begin
  1215. If (cmdFrom <> '') Then
  1216. if assigned(FAfterNotice) then
  1217. FAfterNotice(GetNickFromMask(cmdFrom),cmdAllParams)
  1218. Else if assigned(FAfterNotice) then
  1219. FAfterNotice('',cmdAllParams);
  1220. end;
  1221. Exit;
  1222. End;
  1223. If (uppercase(cmdName) = 'INVITE') Then
  1224. Begin
  1225. { :Nick!Ident@host.com INVITE MyNick :Channel }
  1226. If Assigned(FAfterInvited) Then
  1227. FAfterInvited(GetNickFromMask(cmdFrom),cmdAllParams);
  1228. Exit;
  1229. End;
  1230. { User was kicked }
  1231. If (uppercase(cmdName) = 'KICK') Then
  1232. begin
  1233. { there might be a bug here if I am kicked, beware }
  1234. Kicked(CmdMiddle,GetNickFromMask(CmdFrom), CmdTo,CmdAllParams);
  1235. exit;
  1236. end;
  1237. If (uppercase(cmdName) = 'TOPIC') Then
  1238. Begin
  1239. {
  1240. SOmeone changed the topic
  1241. :Nick!ident@host.com TOPIC Channel :NewTopic
  1242. }
  1243. ChannelTopic(cmdTo,GetNickFromMask(cmdFrom),CmdAllParams);
  1244. Exit;
  1245. End;
  1246. If (uppercase(cmdName) = 'NICK') Then
  1247. Begin
  1248. { :Nick!Ident@host.com NICK <newnick> }
  1249. NickChange(GetNickFromMask(GetNickFromMask(cmdFrom)),CmdAllParams);
  1250. exit;
  1251. End;
  1252. If (UpperCase(cmdName) = 'PRIVMSG') Then
  1253. Begin
  1254. { this might be removed later... }
  1255. If (Length(cmdAllParams) = 0) Then Exit;
  1256. Messages(received,GetNickFromMask(cmdFrom),GetHostFromMask(CmdFrom),GetIdentFromMask(CmdFrom),CmdTo,CmdAllParams);
  1257. exit;
  1258. end;
  1259. If (UpperCase(cmdName) = 'ERROR:') Then
  1260. Begin
  1261. { these error codes appears often right after you connect }
  1262. if assigned(FServerError) then FServerError(Received);
  1263. exit;
  1264. end;
  1265. { Number to command translator as shown in RFC1459
  1266. putting the most unused stuff at the bottom.
  1267. Sorted after how often they likely would appear }
  1268. i := match(CmdName);
  1269. case i of
  1270. 324,329:
  1271. begin
  1272. { Message of the day stuff }
  1273. if assigned(FAfterMode) then FAfterMode(GetNickFromMask(cmdFrom),CmdTo, cmdAllParams);
  1274. exit;
  1275. end;
  1276. 353:
  1277. Begin
  1278. {
  1279. Names
  1280. :irc.server.com 353 To = Channel :SpaceSperatedNickList
  1281. (@ and + prefixes are included)
  1282. ChannelName, CommaNicks, end of names = false
  1283. }
  1284. temp := received;
  1285. channel := received;
  1286. delete(channel,1,pos('#',channel)-1);
  1287. delete(channel,pos(' ',channel),length(channel));
  1288. delete(temp,1,pos(' :',temp)+1);
  1289. NamesChan(channel,temp,false);
  1290. Exit;
  1291. End;
  1292. 366:
  1293. begin
  1294. { end of /names }
  1295. channel := received;
  1296. delete(channel,1,pos('#',channel)-1);
  1297. delete(channel,pos(' ',channel),length(channel));
  1298. NamesChan(channel,cmdAllParams,true);
  1299. Exit;
  1300. end;
  1301. 301,311..314,
  1302. 316..319:
  1303. begin
  1304. { Whois thingie... }
  1305. If Assigned(FAfterWhois) Then
  1306. begin
  1307. if i <> 318 then FAfterWhois(CmdAllParams, false)
  1308. else FAfterWhois(CmdAllParams, true); // End of /whois
  1309. exit
  1310. end;
  1311. end;
  1312. 303: begin { Ison }
  1313. If assigned(FAfterNotify) then
  1314. FAfterNotify(CmdAllParams);
  1315. exit;
  1316. end;
  1317. 461:
  1318. begin
  1319. { :irc.homelien.no 461 joepezt ISON :Not enough parameters }
  1320. exit;
  1321. end;
  1322. 352,315:
  1323. Begin { who stuff }
  1324. If Assigned(FAfterWho) Then
  1325. if i <> 315 then
  1326. begin
  1327. temp := received;
  1328. for i := 0 to 3 do
  1329. delete(temp,1,pos(' ',temp));
  1330. { user host server nick away/here ??? :navn channelname }
  1331. params[7] := Cmdmiddle;
  1332. params[6] := trim(copy(temp,pos(':',temp)+2,length(temp)));
  1333. for i := 0 to 5 do
  1334. begin
  1335. params[i] := trim(copy(temp,1,pos(' ',temp)));
  1336. delete(temp,1,pos(' ',temp));
  1337. end;
  1338. if assigned(FAfterWho) then
  1339. FAfterWho(params[7], params[3], params[0], params[1], params[6], params[2], params[4], params[5], false)
  1340. end
  1341. else FAfterWho('End of /Who','','','','','','','', true); // End of /whois
  1342. exit;
  1343. End;
  1344. 332,333: { Topic when joining a channel }
  1345. Begin
  1346. { :Diemen.NL.EU.Undernet.org 332 joepezT #somechannel :some topic }
  1347. if i = 333 then
  1348. begin
  1349. { :Diemen.NL.EU.Undernet.org 333 joepezT #skien blygblome 1033906982 }
  1350. if channel = '' then
  1351. begin
  1352. channel := CmdFrom;
  1353. channel := Cmdto;
  1354. end;
  1355. ChannelTopicSetBy(channel,CmdAllParams);
  1356. Exit;
  1357. end;
  1358. if channel = '' then
  1359. channel := CmdMiddle;
  1360. ChannelTopic(channel,'',CmdAllParams);
  1361. Exit;
  1362. end;
  1363. 401:
  1364. begin
  1365. {
  1366. No such nich / channel
  1367. fix ;)
  1368. }
  1369. If Assigned(FAfterNoSuchNick) Then
  1370. FAfterNoSuchNick(CmdFrom);
  1371. exit;
  1372. end;
  1373. 433:
  1374. begin
  1375. {
  1376. Nickname is allready in use
  1377. :irc.server.com 433 * OldNickName :Description
  1378. }
  1379. If Assigned(FAfterNickInUse) Then
  1380. FAfterNickInUse(cmdMiddle);
  1381. exit;
  1382. end;
  1383. 321..323:
  1384. begin
  1385. {
  1386. Channel listing. Example: LIST <3,>1,C<10,T>0 ;
  1387. 2 users, younger than 10 min., topic set.
  1388. }
  1389. if i <> 323 then
  1390. begin
  1391. channel := cmdmiddle;
  1392. params[0] := copy(CmdAllParams,pos(':',CmdAllParams)+1,length(CmdAllParams));
  1393. params[1] := trim(copy(CmdAllParams,1,pos(':',CmdAllParams) -1));
  1394. if isnumeric(params[1]) = false then params[1] := '0';
  1395. if assigned(FAfterChannelList) then FAfterChannelList(channel,params[0],strtoint(params[1]), false);
  1396. exit;
  1397. end;
  1398. if assigned(FAfterChannelList) then
  1399. FAfterChannelList('','',0,true);
  1400. exit;
  1401. end;
  1402. 250..255,
  1403. 260..266,
  1404. 370..376:
  1405. begin { motd stuff again }
  1406. if i = 004 then
  1407. begin
  1408. FCurrServer := received;
  1409. for j := 0 to 2 do
  1410. delete(FCurrServer,1,pos(' ',FCurrServer));
  1411. delete(FCurrServer,pos(' ',FCurrServer),length(FCurrServer));
  1412. FCurrServer := trim(FCurrServer);
  1413. end;
  1414. If Assigned(FAfterMotd) Then
  1415. begin
  1416. if i <> 376 then FAfterMotd(cmdAllParams, false)
  1417. else FAfterMotd(cmdAllParams, true); // End of /motd
  1418. Exit;
  1419. end;
  1420. end;
  1421. -1: begin
  1422. { This command is unimplemented }
  1423. exit;
  1424. end;
  1425. end;
  1426. { end case }
  1427. end;
  1428. procedure Tvortex.OnSocketDataAvailable(Sender: TObject; Error: Word);
  1429. Var
  1430. received : string;
  1431. begin
  1432. received := trim(Twsocket(sender).ReceiveStr);
  1433. genericparser(received);
  1434. End;
  1435. procedure Tvortex.OnvortexIRCError (Sender: TObject);
  1436. Var Error : word;
  1437. Begin
  1438. Error := FClient.LastError;
  1439. { winsock error 10057 }
  1440. if error = 10057 then Fclient.OnDataAvailable := OnConnectDataAvailable;
  1441. If Assigned(OnError) Then OnError(sender,error);
  1442. End;
  1443. procedure Tvortex.OnVortexBgException(Sender: TObject; E: Exception; var CanClose: boolean);
  1444. Begin
  1445. If Assigned(FBgException) Then
  1446. FBgException(sender,E,Canclose);
  1447. End;
  1448. procedure Tvortex.OnSocketClosed (Sender: TObject; Error: Word);
  1449. Begin
  1450. FConnected := False;
  1451. If Assigned(FAfterDisconnect) Then
  1452. FAfterDisconnect();
  1453. End;
  1454. procedure Tvortex.OnSocketConnected (Sender: TObject; Error: Word);
  1455. Begin
  1456. FConnected := True;
  1457. with FIrcOptions do
  1458. begin
  1459. User(GetUserNick, GetUserIdent, '8', FUserName);
  1460. Nick(GetUserNick);
  1461. end;
  1462. If Assigned(FAfterConnect) Then FAfterConnect();
  1463. End;
  1464. function Tvortex.LocalIP(num : byte) : string;
  1465. Begin
  1466. Try
  1467. Result := LocalIpList[num];
  1468. Except
  1469. Try
  1470. Result := LocalIpList[0];
  1471. Except
  1472. MessageBox(0,'No IP!','error.',mb_ok);
  1473. End;
  1474. End;
  1475. End;
  1476. procedure Tvortex.Joined(Nickname, ChannelName, HostName : string);
  1477. var
  1478. me : boolean;
  1479. channel : TChannels;
  1480. i : integer;
  1481. begin
  1482. { Check wether this is me or others }
  1483. With FIrcOptions do
  1484. if ansisametext(Nickname,GetUserNick) then Me := true
  1485. else me := false;
  1486. case me of
  1487. false:
  1488. begin
  1489. { fikse ? }
  1490. If Assigned(FAfterJoin) Then
  1491. FAfterJoin(Nickname,HostName,ChannelName);
  1492. for i := 0 to FChannels.Count -1 do
  1493. with Tobject(Fchannels[i]) as TChannels do
  1494. if Tobject(Fchannels[i]) <> nil then
  1495. if GetChannelName = ChannelName then
  1496. begin
  1497. AddUserToChannel(Nickname);
  1498. Fchannels[i] := nil;
  1499. break;
  1500. end;
  1501. end;
  1502. true:
  1503. begin
  1504. { Add this channel to later be used :) }
  1505. If Assigned(FAfterJoined) Then
  1506. FAfterJoined(ChannelName);
  1507. Channel := Tchannels.Create;
  1508. FChannels.add(Channel);
  1509. with Channel do
  1510. begin
  1511. SetChannelName(ChannelName);
  1512. SetChannelID(FChannels.Count);
  1513. end;
  1514. end;
  1515. end;
  1516. end;
  1517. procedure Tvortex.Parted(Nickname, HostName, UserName, ChannelName, Reason: string);
  1518. var
  1519. me : boolean;
  1520. i : integer;
  1521. begin
  1522. { Check wether this is me or someone else }
  1523. With FIrcOptions do
  1524. if ansisametext(Nickname,GetUserNick) then Me := true
  1525. else me := false;
  1526. Case Me of
  1527. true:
  1528. begin
  1529. if Assigned(FAfterParted) Then
  1530. FAfterParted(ChannelName);
  1531. { Delete channel; }
  1532. for i := 0 to FChannels.Count -1 do
  1533. with Tobject(Fchannels[i]) as TChannels do
  1534. if Tobject(Fchannels[i]) <> nil then
  1535. if GetChannelName = ChannelName then
  1536. begin
  1537. Fchannels[i] := nil;
  1538. break;
  1539. end;
  1540. exit;
  1541. end;
  1542. false:
  1543. begin
  1544. If Assigned(FAfterPart) then
  1545. FAfterPart(Nickname,HostName,ChannelName,reason);
  1546. { Delete user from channel; }
  1547. for i := 0 to FChannels.Count -1 do
  1548. with Tobject(Fchannels[i]) as TChannels do
  1549. if Tobject(Fchannels[i]) <> nil then
  1550. if GetChannelName = ChannelName then
  1551. begin
  1552. RemoveUserFromChannel(NickName);
  1553. exit;
  1554. end;
  1555. end;
  1556. end;
  1557. end;
  1558. procedure Tvortex.Quited(Nickname, user, host, reason: string);
  1559. begin
  1560. If Assigned(FAfterUserQuit) Then
  1561. FAfterUserQuit(NickName, Reason);
  1562. {
  1563. TODO: Add user ident and hostname..
  1564. delete user from channellist
  1565. }
  1566. end;
  1567. procedure Tvortex.Kicked(Victim, BOFH, Channel, Reason: string);
  1568. var
  1569. me : boolean;
  1570. begin
  1571. { Check wether this is me or others }
  1572. With FIrcOptions do
  1573. if ansisametext(Victim,GetUserNick) then Me := true
  1574. else me := false;
  1575. Case Me of
  1576. false:
  1577. begin
  1578. If Assigned(FAfterUserKick) Then
  1579. FAfterUserKick(Victim,BOFH,Channel,Reason);
  1580. exit;
  1581. end;
  1582. true:
  1583. begin
  1584. if FindChannelID(Channel) = -1 then exit;
  1585. with Tobject(Fchannels[FindChannelID(Channel)]) as TChannels do
  1586. begin
  1587. with Tobject(Fchannels[FindChannelID(Channel)]) as TChannels do
  1588. Fchannels[FindChannelID(channel)] := nil;
  1589. end;
  1590. If Assigned(FAfterKicked) then
  1591. FAfterKicked(BOFH,Channel,Reason);
  1592. end;
  1593. end;
  1594. end;
  1595. procedure Tvortex.NamesChan(ChannelName, CommaNicks: string;
  1596. EndOfNames: boolean);
  1597. var
  1598. temp : string;
  1599. i : integer;
  1600. begin
  1601. if EndOfNames then
  1602. begin
  1603. If Assigned(FAfterNames) Then
  1604. FAfterNames('End of /Names',channelName, True);
  1605. end;
  1606. temp := CommaNicks;;
  1607. Delete(Temp,1, Pos(':',temp));
  1608. { Replace spaces with commatas }
  1609. If (Length(Temp) > 0) Then
  1610. For I:=0 To Length(Temp) Do
  1611. If (Temp[I] = ' ') Then Temp[I] := ',';
  1612. If Assigned(FAfterNames) Then
  1613. FAfterNames(temp,ChannelName, false);
  1614. i := FindChannelID(Channelname);
  1615. if i = -1 then exit;
  1616. with Tobject(Fchannels[i]) as TChannels do
  1617. AddUsersFromCommaText(commanicks);
  1618. end;
  1619. procedure TVortex.ChannelTopic (ChannelName, UserName, Topic : string);
  1620. begin
  1621. If Assigned(FAfterTopic) Then
  1622. FAfterTopic(ChannelName,UserName,Topic);
  1623. { Clean up ... }
  1624. try
  1625. case FindChannelID(Channelname) of
  1626. -1: exit;
  1627. else
  1628. with Tobject(Fchannels[FindChannelID(Channelname)]) as TChannels do
  1629. begin
  1630. { bug in VortexChannels. :( }
  1631. SetTopic(Topic);
  1632. SetTopicSetBy(UserName);
  1633. end;
  1634. end;
  1635. except
  1636. end;
  1637. end;
  1638. procedure TVortex.ChannelTopicSetBy (ChannelName, Nickname : string);
  1639. begin
  1640. try
  1641. case FindChannelID(Channelname) of
  1642. -1: exit;
  1643. else
  1644. with Tobject(Fchannels[FindChannelID(Channelname)]) as TChannels do
  1645. SetTopicSetBy(NickName);
  1646. end;
  1647. except
  1648. end;
  1649. end;
  1650. procedure Tvortex.NickChange(OldNick, Newnick: string);
  1651. var
  1652. me : boolean;
  1653. begin
  1654. if assigned(FBeforeNickChange) then
  1655. FBeforeNickChange(oldnick,Newnick);
  1656. { Check wether this is me or someone else }
  1657. With FIrcOptions do
  1658. if AnsiSameText(OldNick,GetUserNick) then Me := true;
  1659. Case Me of
  1660. false:
  1661. begin
  1662. If Assigned(FAfterNickChange) Then
  1663. FAfterNickChange(OldNick,NewNick);
  1664. { ToDo: Update channels with the new nickname... }
  1665. end;
  1666. true:
  1667. begin
  1668. SetMyNick(NewNick);;
  1669. If Assigned(FAfterNickChanged) Then
  1670. FAfterNickChanged(NewNick,OldNick);
  1671. exit;
  1672. end;
  1673. end;
  1674. end;
  1675. procedure Tvortex.SetMyNick(Nickname: string);
  1676. begin
  1677. { This one does NOT change your nick on IRC }
  1678. With FIrcOptions do
  1679. SetUserNick := NickName;
  1680. end;
  1681. procedure Tvortex.SetCurrentServer(Value: string);
  1682. begin
  1683. { Which server we are currently connected to }
  1684. FCurrServer := Value;
  1685. end;
  1686. procedure Tvortex.SetIRCName(Value: string);
  1687. begin
  1688. With FIrcOptions do
  1689. FUserName := Value;
  1690. end;
  1691. procedure Tvortex.SetIRCPort(Value: string);
  1692. begin
  1693. With FIrcOptions do
  1694. FServerPort := Value;
  1695. end;
  1696. procedure Tvortex.SetMyUserName(Value: string);
  1697. begin
  1698. With FIrcOptions do
  1699. SetUserNick := Value;
  1700. end;
  1701. procedure Tvortex.SetVersionInfo(Info: string);
  1702. begin
  1703. with FCtcpOptions do
  1704. FVersionReply := info;
  1705. end;
  1706. //////////////////////////////////////////////////////////////////////////////
  1707. //////////////////////////////////////////////////////////////////////////////
  1708. //////////////////////////////////////////////////////////////////////////////
  1709. // //
  1710. // !!! Channel & Private messages !!! //
  1711. // probably the biggest part of vortex is the message handling. //
  1712. // //
  1713. //////////////////////////////////////////////////////////////////////////////
  1714. //////////////////////////////////////////////////////////////////////////////
  1715. //////////////////////////////////////////////////////////////////////////////
  1716. {
  1717. There are different types of PRIVMSGs:
  1718. :Nick!ident@host.com PRIVMSG To :SomeTextHere
  1719. Now "To" can either be your current Nick, then it's aprivate message
  1720. or a channel name then it's a channel message.
  1721. If The PRIVMSG was a CTCP then "SomeTextHere" begins and ends with char #1.
  1722. Again CTCPs can be sent to individuals or to channels
  1723. Some CTCPs have a really stupid formatting sicne they append the Nick of
  1724. after the trailing #1
  1725. In this case we can safely ignore "NicknameItComesFrom" sicne it's alos passed
  1726. as :Nick!ident@...
  1727. }
  1728. procedure TVortex.Messages (Line, nick, host, user, destination, Content : string);
  1729. begin
  1730. {
  1731. Is it a CTCP-Message ?
  1732. A third parameter "Dest" was added so that the user-assigned event-handler
  1733. can destinguish between CTCPs sent directly to the user and
  1734. CTCPs sent to a whole channel.
  1735. }
  1736. If (Content[1] = #1) Then
  1737. Begin
  1738. CTCPMessage(Line,Nick,Host,User,Destination,Content);
  1739. exit;
  1740. end;
  1741. { Is this a channel message ? }
  1742. if Destination[1] = '#' Then
  1743. Begin
  1744. If Assigned(FAfterChannelMsg) Then
  1745. FAfterChannelMsg(Destination, Content, nick, User, host);
  1746. Exit;
  1747. End;
  1748. { Ok this must be a private Message :-) }
  1749. if Assigned(FAfterPrivMsg) then
  1750. FAfterPrivMsg(Nick,User,Host,Content);
  1751. end;
  1752. procedure Tvortex.CTCPMessage(Line, nick, host, user, destination,
  1753. Content: string);
  1754. var
  1755. i : integer;
  1756. streng : string;
  1757. temp : string;
  1758. params : array[0..5] of string;
  1759. begin
  1760. streng := Content;
  1761. {
  1762. Strip of the leading #10 char and the trailing
  1763. #10 char including everything that comes behind it
  1764. }
  1765. Delete(Streng,1,1);
  1766. If (Length(Streng) > 0) Then
  1767. Begin
  1768. I:=Pos(#1,Streng);
  1769. If (I = 0) Then I := Length(Streng) + 1;
  1770. Streng := Copy(Streng,1,I-1);
  1771. End;
  1772. {
  1773. Check if it's an action
  1774. If ((Length(cmdAllParams) > 6) and (UpperCase(Copy(cmdAllParams,1,6)) = 'ACTION')) Then
  1775. }
  1776. If ansisametext(copy(streng,1,6),'ACTION') Then
  1777. Begin
  1778. delete(content,1,pos(' ',content));
  1779. If Assigned(FAfterIrcAction) Then
  1780. FAfterIrcAction(nick,Content,Destination);
  1781. Exit;
  1782. End;
  1783. {
  1784. Handle DCCs Here
  1785. If ((Length(Streng) > 3) and (UpperCase(Copy(cmdAllParams,1,3)) = 'DCC')) Then
  1786. }
  1787. If UpperCase(Copy(streng,1,3)) = 'DCC' Then
  1788. Begin
  1789. temp := streng;
  1790. { if the client send a file with spaces.. }
  1791. if pos('"',temp) <> 0 then
  1792. begin
  1793. Line := between(temp,'"','" ') ;
  1794. delete(temp,pos('"',temp), length(line) +3);
  1795. end else
  1796. begin
  1797. Line := temp;
  1798. for i := 0 to 1 do
  1799. delete(line,1,pos(' ',line));
  1800. delete(line,pos(' ',line),length(line));
  1801. delete(temp,9,length(line)+1);
  1802. end;
  1803. for i := 0 to 5 do
  1804. begin { Find out what type of DCC we received... }
  1805. params[i] := trim(copy(temp,1,pos(' ',temp)));
  1806. delete(temp,1,pos(' ',temp));
  1807. end;
  1808. params[5] := temp; { port }
  1809. //////////////////////////////////////////////////////////////////////////////
  1810. //////////////// when receiving a DCC chat request ///////////////////////////
  1811. //////////////////////////////////////////////////////////////////////////////
  1812. if ansisametext(params[1],'chat') then
  1813. begin
  1814. delete(temp,1,pos(#32,temp));
  1815. params[0] := trim(copy(temp,1,pos(#32,temp)));
  1816. delete(temp,1,pos(#32,temp));
  1817. if params[3] = '0' then { might be a bad idea }
  1818. params[3] := host;
  1819. { DCC CHAT chat ip [temp = port] }
  1820. if assigned(FdccChatIncoming) then
  1821. FdccChatIncoming(nick, temp, shortip(params[2]));
  1822. exit;
  1823. end;
  1824. //////////////////////////////////////////////////////////////////////////////
  1825. //////////////// when receiving a DCC RESUME request /////////////////////////
  1826. //////////////////////////////////////////////////////////////////////////////
  1827. if trim(lowercase(params[1])) = 'resume' then
  1828. begin
  1829. exit;
  1830. end;
  1831. //////////////////////////////////////////////////////////////////////////////
  1832. //////////////// User accepted your resume request ///////////////////////////
  1833. //////////////////////////////////////////////////////////////////////////////
  1834. if lowercase(params[1]) = 'accept' then
  1835. begin
  1836. { Getting the last information we need to make a connection }
  1837. for i := 1 to 2 do
  1838. begin
  1839. params[i] := trim(copy(temp,1,pos(#32,temp)));
  1840. delete(temp,1,pos(#32,temp));
  1841. end;
  1842. {
  1843. params[3] := trim(CmdAllParams);
  1844. params[4] := trim(copy(cmdAllParams,1,pos('"',cmdAllParams)-1));
  1845. }
  1846. if params[4] = '' then
  1847. params[4] := 'file.ext';
  1848. If assigned(FDCCGetResume) then
  1849. FDCCGetResume(nick, Params[4],temp,params[3]);
  1850. exit;
  1851. end;
  1852. //////////////////////////////////////////////////////////////////////////////
  1853. //////////////// when receiving a DCC Send request ///////////////////////////
  1854. //////////////////////////////////////////////////////////////////////////////
  1855. if ansisametext(params[1],'send') then
  1856. begin
  1857. {
  1858. Might need a try loop here
  1859. nick port address filename FileSize
  1860. Some clients sends the entire path. damn!
  1861. }
  1862. if pos ('/',Line) <> 0 then delete(Line,1,Lastdelimiter('/',Line));
  1863. if pos ('\',Line) <> 0 then delete(Line,1,Lastdelimiter('\',Line));
  1864. if assigned(FDCCGet) then
  1865. FDCCGet(nick,params[3],shortip(params[2]),Line,Params[5]);
  1866. exit;
  1867. end;
  1868. End; { End of DCC stuff.. }
  1869. {
  1870. Ok it's *no* DCC request and *no* Action -> fire a CTCP event
  1871. The only *standart* CTCP we handle here is PING - this is required by the standart
  1872. Everything else should be handled by the user-assigned eventhandler imho
  1873. The CTCP event will still be fired though - since clients wnat to rect on this event
  1874. }
  1875. with FCtcpOptions do
  1876. if FReplyToCtcp = true then
  1877. begin
  1878. If ((Length(streng) > 4) and (UpperCase(Copy(streng,1,4)) = 'PING')) Then
  1879. begin
  1880. CtcpReply(nick,streng);
  1881. exit;
  1882. end;
  1883. If ((Length(streng) >= 7) and (UpperCase(Copy(streng,1,7)) = 'VERSION')) Then
  1884. begin
  1885. CtcpReply(nick,'VERSION ' + GetVersionInfo);
  1886. exit;
  1887. end;
  1888. If ((Length(streng) >= 6) and (UpperCase(Copy(streng,1,6)) = 'FINGER')) Then
  1889. begin
  1890. with FCtcpOptions do
  1891. CtcpReply(nick,'FINGER ' + FingerReply);
  1892. exit;
  1893. end;
  1894. If ((Length(streng) >= 4) and (UpperCase(Copy(streng,1,4)) = 'TIME')) Then
  1895. begin
  1896. with FCtcpOptions do
  1897. begin
  1898. if FTimeReply = '' then
  1899. CtcpReply(nick,'TIME ' + timetostr(now))
  1900. else
  1901. CtcpReply(nick,'TIME ' + FTimeReply);
  1902. end;
  1903. exit;
  1904. end;
  1905. { Please leave this line intact... :-) }
  1906. If ((Length(streng) >= 10) and (UpperCase(Copy(streng,1,10)) = 'CLIENTINFO')) Then
  1907. begin
  1908. with FCtcpOptions do
  1909. CtcpReply(nick,FClientInfo);
  1910. exit;
  1911. end;
  1912. { Now fire the CTCP-event handler }
  1913. If Assigned(FAfterCtcp) Then
  1914. FAfterCtcp(nick, streng, Destination);
  1915. end;
  1916. end;
  1917. function Tvortex.FindChannelID(AChannel: string): integer;
  1918. var
  1919. i : integer;
  1920. begin
  1921. for i := 0 to Fchannels.Count -1 do
  1922. if Fchannels[i] <> nil then
  1923. with Tobject(Fchannels[i]) as TChannels do
  1924. if AnsiSameText(GetChannelname,Achannel) then
  1925. begin
  1926. result := i;
  1927. exit;
  1928. end;
  1929. result := -1;
  1930. end;
  1931. function Tvortex.GetChannelTopic(value: string): string;
  1932. begin
  1933. if (value <> '') and
  1934. (value[1] = '#') then { mulig bug fiks }
  1935. if findchannelid(value) <> -1 then
  1936. begin
  1937. with Tobject(Fchannels[findchannelID(value)]) as Tchannels do
  1938. result := GetTopic;
  1939. exit;
  1940. end;
  1941. Result := 'unknown channel';
  1942. end;
  1943. procedure Tvortex.ClearUsersInChannel(value: string);
  1944. begin
  1945. if value = '' then exit;
  1946. if FindChannelID(value) <> -1 then
  1947. begin
  1948. with Tobject(Fchannels[findchannelid(value)]) as Tchannels do
  1949. ClearUsers;
  1950. Quote(format('names %s',[value]));
  1951. end;
  1952. end;
  1953. function Tvortex.GetTopicSetBy(value: string): string;
  1954. begin
  1955. if findchannelid(value) = -1 then
  1956. begin
  1957. Result := 'unknown channel';
  1958. exit;
  1959. end;
  1960. with Tobject(Fchannels[findchannelid(value)]) as Tchannels do
  1961. result := GetTopicSetBy;
  1962. end;
  1963. function Tvortex.GetUsersFromChannel(Value: string): string;
  1964. var
  1965. i : integer;
  1966. begin
  1967. i := findchannelid(value);
  1968. if i = -1 then
  1969. begin
  1970. Result := 'unknown channel';
  1971. exit;
  1972. end;
  1973. with Tobject(Fchannels[i]) as Tchannels do
  1974. result := GetAllNicksFromChannel;
  1975. end;
  1976. function Tvortex.CountUsersFromChannel(Value: string): integer;
  1977. var
  1978. i : integer;
  1979. begin
  1980. i := findchannelid(value);
  1981. if i = -1 then
  1982. begin
  1983. Result := 0;
  1984. exit;
  1985. end;
  1986. with Tobject(Fchannels[i]) as Tchannels do
  1987. result := CountUsers;
  1988. end;
  1989. { I put these on one line since they wont be modified anyway }
  1990. procedure TVortex.SetIrcOptions(const Value: TIrcOptions);begin FIrcOptions.Assign(Value);end;
  1991. procedure TVortex.SetCtcpOptions(const Value: TCtcpOptions);begin FCtcpOptions.Assign(Value);end;
  1992. procedure TVortex.SetSocksOptions(const Value: TSocksOptions);begin FSocksOptions.Assign(Value);end;
  1993. procedure TVortex.SetAuthOptions(const Value: TAuthOptions);begin FAuthOptions.Assign(Value);end;
  1994. procedure TCtcpOptions.Assign(Source: TPersistent);begin inherited;end;
  1995. procedure TAuthOptions.Assign(Source: TPersistent);begin inherited;end;
  1996. procedure TircOptions.Assign(Source: TPersistent);begin inherited;end;
  1997. procedure TVortex.InitDCCGet(nick, port, address, filename,
  1998. filesize: string);
  1999. begin
  2000. end;
  2001. procedure TVortex.InitDCCGetResume(nick, port, Position: string);
  2002. begin
  2003. end;
  2004. { TAuthOptions }
  2005. procedure TAuthOptions.OnIdentDserverSessionAvailable(Sender: TObject;
  2006. Error: Word);
  2007. var
  2008. AuthClient : TWSocket;
  2009. UserIdent : string;
  2010. begin
  2011. { uferdig }
  2012. AuthClient := TWSocket.Create(nil);
  2013. With AuthClient do
  2014. begin
  2015. LineMode := TRUE;
  2016. HSocket := TWSocket(sender).Accept;
  2017. { We are answering on Identd requests}
  2018. if FAnswer = true then
  2019. SendStr(format('%s, 113 : USERID : %s : %s' + crlf,['6667', FSystem, FIdent]))
  2020. else SendStr(format('%s, 113 : ERROR : NO-USER' + crlf,['6667']));
  2021. Close;
  2022. end;
  2023. FreeAndNil(AuthClient);
  2024. end;
  2025. procedure TAuthOptions.StartAuth;
  2026. { experimental IdentD daemon }
  2027. begin
  2028. if FAuthServer <> nil then FAuthServer.free;
  2029. FAuthServer := TWSocket.create(nil);
  2030. with FAuthServer do
  2031. begin
  2032. OnSessionAvailable := OnIdentDserverSessionAvailable;
  2033. Addr := '0.0.0.0';
  2034. port := '113';
  2035. proto := 'tcp';
  2036. try
  2037. listen;
  2038. except
  2039. free
  2040. end;
  2041. end;
  2042. exit;
  2043. end;
  2044. procedure TAuthOptions.StopAuth;
  2045. begin
  2046. if FAuthServer <> nil then
  2047. FAuthServer.free;
  2048. end;
  2049. End.