IdIRC.pas 112 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958
  1. {
  2. $Project$
  3. $Workfile$
  4. $Revision$
  5. $DateUTC$
  6. $Id$
  7. This file is part of the Indy (Internet Direct) project, and is offered
  8. under the dual-licensing agreement described on the Indy website.
  9. (http://www.indyproject.org/)
  10. Copyright:
  11. (c) 1993-2005, Chad Z. Hower and the Indy Pit Crew. All rights reserved.
  12. }
  13. {
  14. $Log$
  15. }
  16. {
  17. 2003-11-Jul:
  18. Original author: Sergio Perry
  19. Matthew Elzer - bug fixes & modifications
  20. }
  21. unit IdIRC;
  22. {
  23. Based on TIRCClient component by Steve Williams ([email protected])
  24. ported to Indy by Daaron Dwyer ([email protected])
  25. }
  26. { Based on RFC 2812 }
  27. interface
  28. {$i IdCompilerDefines.inc}
  29. uses
  30. Classes,
  31. IdAssignedNumbers, IdContext, IdCmdTCPClient, IdCommandHandlers,
  32. IdIOHandler, IdGlobal, IdException;
  33. type
  34. TIdIRC = class;
  35. TIdIRCUserMode = (amAway, amInvisible, amWallops, amRestricted, amOperator, amLocalOperator, amReceiveServerNotices);
  36. TIdIRCUserModes = set of TIdIRCUserMode;
  37. TIdIRCStat = (stServerConnectionsList, stCommandUsageCount, stOperatorList, stUpTime);
  38. { -WELCOME- }
  39. TIdIRCServerMsgEvent = procedure(ASender: TIdContext; const AMsg: String) of object;
  40. TIdIRCMyInfoEvent = procedure(ASender: TIdContext; const AServer, AVersion, AUserModes, AChanModes, AExtra: String) of object;
  41. TIdIRCBounceEvent = procedure(ASender: TIdContext; const AHost: String; APort: Integer; const AInfo: String) of object;
  42. TIdIRCISupportEvent = procedure(ASender: TIdContext; AParameters: TStrings) of object;
  43. { -PING- }
  44. TIdIRCPingPongEvent = procedure(ASender: TIdContext) of object;
  45. { -MESSAGE- }
  46. TIdIRCPrivMessageEvent = procedure(ASender: TIdContext; const ANickname, AHost, ATarget, AMessage: String) of object;
  47. { -NOTICE- }
  48. TIdIRCNoticeEvent = procedure(ASender: TIdContext; const ANickname, AHost, ATarget, ANotice: String) of object;
  49. { -REHASH- }
  50. TIdIRCRehashEvent = procedure(ASender: TIdContext; const ANickname, AHost: String) of object;
  51. { -SUMMON- }
  52. TIdIRCSummonEvent = procedure(ASender: TIdContext; const ANickname, AHost: String) of object;
  53. { -WALLOPS- }
  54. TIdIRCWallopsEvent = procedure(ASender: TIdContext; const ANickname, AHost, AMessage: String) of object;
  55. { -ISON- }
  56. TIdIRCIsOnIRCEvent = procedure(ASender: TIdContext; const ANickname, AHost: String) of object;
  57. { -AWAY- }
  58. TIdIRCAwayEvent = procedure(ASender: TIdContext; const ANickname, AHost, AAwayMessage: String; UserAway: Boolean) of object;
  59. { -JOIN- }
  60. TIdIRCJoinEvent = procedure(ASender: TIdContext; const ANickname, AHost, AChannel: String) of object;
  61. { -PART- }
  62. TIdIRCPartEvent = procedure(ASender: TIdContext; const ANickname, AHost, AChannel, APartMessage: String) of object;
  63. { -TOPIC- }
  64. TIdIRCTopicEvent = procedure(ASender: TIdContext; const ANickname, AHost, AChannel, ATopic: String) of object;
  65. { -KICK- }
  66. TIdIRCKickEvent = procedure(ASender: TIdContext; const ANickname, AHost, AChannel, ATarget, AReason: String) of object;
  67. { -MOTD- }
  68. TIdIRCMOTDEvent = procedure(ASender: TIdContext; AMOTD: TStrings) of object;
  69. { -TRACE- }
  70. TIdIRCServerTraceEvent = procedure(ASender: TIdContext; ATraceInfo: TStrings) of object;
  71. { -OPER- }
  72. TIdIRCOpEvent = procedure(ASender: TIdContext; const ANickname, AChannel, AHost: String) of object;
  73. { -INV- }
  74. TIdIRCInvitingEvent = procedure(ASender: TIdContext; const ANickname, AHost: String) of object;
  75. TIdIRCInviteEvent = procedure(ASender: TIdContext; const ANickname, AHost, ATarget, AChannel: String) of object;
  76. { -LIST- }
  77. TIdIRCChanBANListEvent = procedure(ASender: TIdContext; const AChannel: String; ABanList: TStrings) of object;
  78. TIdIRCChanEXCListEvent = procedure(ASender: TIdContext; const AChannel: String; AExceptList: TStrings) of object;
  79. TIdIRCChanINVListEvent = procedure(ASender: TIdContext; const AChannel: String; AInviteList: TStrings) of object;
  80. TIdIRCServerListEvent = procedure(ASender: TIdContext; AServerList: TStrings) of object;
  81. TIdIRCNickListEvent = procedure(ASender: TIdContext; const AChannel: String; ANicknameList: TStrings) of object;
  82. { -STATS- }
  83. TIdIRCServerUsersEvent = procedure(ASender: TIdContext; AUsers: TStrings) of object;
  84. TIdIRCServerStatsEvent = procedure(ASender: TIdContext; AStatus: TStrings) of object;
  85. TIdIRCKnownServerNamesEvent = procedure(ASender: TIdContext; AKnownServers: TStrings) of object;
  86. { -INFO- }
  87. TIdIRCAdminInfoRecvEvent = procedure(ASender: TIdContext; AAdminInfo: TStrings) of object;
  88. TIdIRCUserInfoRecvEvent = procedure(ASender: TIdContext; const AUserInfo: String) of object;
  89. { -WHO- }
  90. TIdIRCWhoEvent = procedure(ASender: TIdContext; AWhoResults: TStrings) of object;
  91. TIdIRCWhoIsEvent = procedure(ASender: TIdContext; AWhoIsResults: TStrings) of object;
  92. TIdIRCWhoWasEvent = procedure(ASender: TIdContext; AWhoWasResults: TStrings) of object;
  93. { Mode }
  94. TIdIRCChanModeEvent = procedure(ASender: TIdContext; const ANickname, AHost, AChannel, AMode, AParams: String) of object;
  95. TIdIRCUserModeEvent = procedure(ASender: TIdContext; const ANickname, AHost, AMode: String) of object;
  96. { -CTCP- }
  97. TIdIRCCTCPQueryEvent = procedure(ASender: TIdContext; const ANickname, AHost, ATarget, ACommand, AParams: String) of object;
  98. TIdIRCCTCPReplyEvent = procedure(ASender: TIdContext; const ANickname, AHost, ATarget, ACommand, AParams: String) of object;
  99. { -DCC- }
  100. TIdIRCDCCChatEvent = procedure(ASender: TIdContext; const ANickname, AHost: String; APort: Integer) of object;
  101. TIdIRCDCCSendEvent = procedure(ASender: TIdContext; const ANickname, AHost, AFilename: String; APort: TIdPort; AFileSize: Int64) of object;
  102. TIdIRCDCCResumeEvent = procedure(ASender: TIdContext; const ANickname, AHost, AFilename: String; APort: TIdPort; AFilePos: Int64) of object;
  103. TIdIRCDCCAcceptEvent = procedure(ASender: TIdContext; const ANickname, AHost, AFilename: String; APort: TIdPort; AFilePos: Int64) of object;
  104. { -Errors- }
  105. TIdIRCServerErrorEvent = procedure(ASender: TIdContext; AErrorCode: Integer; const AErrorMessage: String) of object;
  106. TIdIRCNickErrorEvent = procedure(ASender: TIdContext; AError: Integer) of object;
  107. TIdIRCKillErrorEvent = procedure(ASender: TIdContext) of object;
  108. { Other }
  109. TIdIRCNicknameChangedEvent = procedure(ASender: TIdContext; const AOldNickname, AHost, ANewNickname: String) of object;
  110. TIdIRCKillEvent = procedure(ASender: TIdContext; const ANickname, AHost, ATargetNickname, AReason: String) of object;
  111. TIdIRCQuitEvent = procedure(ASender: TIdContext; const ANickname, AHost, AReason: String) of object;
  112. TIdIRCSvrQuitEvent = procedure(ASender: TIdContext; const ANickname, AHost, AServer, AReason: String) of object;
  113. TIdIRCSvrTimeEvent = procedure(ASender: TIdContext; const AHost, ATime: String) of object;
  114. TIdIRCServiceEvent = procedure(ASender: TIdContext) of object;
  115. TIdIRCSvrVersionEvent = procedure(ASender: TIdContext; const AVersion, AHost, AComments: String) of object;
  116. TIdIRCRawEvent = procedure(ASender: TIdContext; AIn: Boolean; const AMessage: String) of object;
  117. EIdIRCError = class(EIdException);
  118. TIdIRCReplies = class(TPersistent)
  119. protected
  120. FFinger: String;
  121. FVersion: String;
  122. FUserInfo: String;
  123. FClientInfo: String;
  124. public
  125. constructor Create;
  126. procedure Assign(Source: TPersistent); override;
  127. published
  128. property Finger: String read FFinger write FFinger;
  129. property Version: String read FVersion write FVersion;
  130. property UserInfo: String read FUserInfo write FUserInfo;
  131. property ClientInfo: String read FClientInfo write FClientInfo;
  132. end;
  133. TIdIRC = class(TIdCmdTCPClient)
  134. protected
  135. FNickname: String;
  136. FAltNickname: String;
  137. FAltNickUsed: Boolean;
  138. //
  139. FUsername: String;
  140. FRealName: String;
  141. FPassword: String;
  142. FUserMode: TIdIRCUserModes;
  143. FUserAway: Boolean;
  144. FReplies: TIdIRCReplies;
  145. //
  146. FSenderNick: String;
  147. FSenderHost: String;
  148. //
  149. FBans: TStrings;
  150. FExcepts: TStrings;
  151. FInvites: TStrings;
  152. FLinks: TStrings;
  153. FMotd: TStrings;
  154. FNames: TStrings;
  155. FWho: TStrings;
  156. FWhoIs: TStrings;
  157. FWhoWas: TStrings;
  158. FSvrList: TStrings;
  159. FUsers: TStrings;
  160. //
  161. FOnSWelcome: TIdIRCServerMsgEvent;
  162. FOnYourHost: TIdIRCServerMsgEvent;
  163. FOnSCreated: TIdIRCServerMsgEvent;
  164. FOnMyInfo: TIdIRCMyInfoEvent;
  165. FOnBounce: TIdIRCBounceEvent;
  166. FOnISupport: TIdIRCISupportEvent;
  167. FOnSError: TIdIRCServerMsgEvent;
  168. FOnPingPong: TIdIRCPingPongEvent;
  169. FOnPrivMessage: TIdIRCPrivMessageEvent;
  170. FOnNotice: TIdIRCNoticeEvent;
  171. FOnRehash: TIdIRCRehashEvent;
  172. FOnSummon: TIdIRCSummonEvent;
  173. FOnWallops: TIdIRCWallopsEvent;
  174. FOnIsOnIRC: TIdIRCIsOnIRCEvent;
  175. FOnAway: TIdIRCAwayEvent;
  176. FOnJoin: TIdIRCJoinEvent;
  177. FOnPart: TIdIRCPartEvent;
  178. FOnTopic: TIdIRCTopicEvent;
  179. FOnKick: TIdIRCKickEvent;
  180. FOnMOTD: TIdIRCMOTDEvent;
  181. FOnTrace: TIdIRCServerTraceEvent;
  182. FOnOp: TIdIRCOpEvent;
  183. FOnInviting: TIdIRCInvitingEvent;
  184. FOnInvite: TIdIRCInviteEvent;
  185. FOnBANList: TIdIRCChanBANListEvent;
  186. FOnEXCList: TIdIRCChanEXCListEvent;
  187. FOnINVList: TIdIRCChanINVListEvent;
  188. FOnSvrList: TIdIRCServerListEvent;
  189. FOnNickList: TIdIRCNickListEvent;
  190. FOnSvrUsers: TIdIRCServerUsersEvent;
  191. FOnSvrStats: TIdIRCServerStatsEvent;
  192. FOnKnownSvrs: TIdIRCKnownServerNamesEvent;
  193. FOnAdminInfo: TIdIRCAdminInfoRecvEvent;
  194. FOnUserInfo: TIdIRCUserInfoRecvEvent;
  195. FOnWho: TIdIRCWhoEvent;
  196. FOnWhoIs: TIdIRCWhoIsEvent;
  197. FOnWhoWas: TIdIRCWhoWasEvent;
  198. FOnChanMode: TIdIRCChanModeEvent;
  199. FOnUserMode: TIdIRCUserModeEvent;
  200. FOnCTCPQry: TIdIRCCTCPQueryEvent;
  201. FOnCTCPRep: TIdIRCCTCPReplyEvent;
  202. FOnDCCChat: TIdIRCDCCChatEvent;
  203. FOnDCCSend: TIdIRCDCCSendEvent;
  204. FOnDCCResume: TIdIRCDCCResumeEvent;
  205. FOnDCCAccept: TIdIRCDCCAcceptEvent;
  206. FOnServerError: TIdIRCServerErrorEvent;
  207. FOnNickError: TIdIRCNickErrorEvent;
  208. FOnKillError: TIdIRCKillErrorEvent;
  209. FOnNickChange: TIdIRCNicknameChangedEvent;
  210. FOnKill: TIdIRCKillEvent;
  211. FOnQuit: TIdIRCQuitEvent;
  212. FOnSvrQuit: TIdIRCSvrQuitEvent;
  213. FOnSvrTime: TIdIRCSvrTimeEvent;
  214. FOnService: TIdIRCServiceEvent;
  215. FOnSvrVersion: TIdIRCSvrVersionEvent;
  216. FOnRaw: TIdIRCRawEvent;
  217. //
  218. function GetUsedNickname: String;
  219. procedure SetNickname(const AValue: String);
  220. procedure SetUsername(const AValue: String);
  221. procedure SetIdIRCUserMode(AValue: TIdIRCUserModes);
  222. procedure SetIdIRCReplies(AValue: TIdIRCReplies);
  223. function GetUserMode: String;
  224. procedure ParseDCC(AContext: TIdContext; const ADCC: String);
  225. //Command handlers
  226. procedure DoBeforeCmd(ASender: TIdCommandHandlers; var AData: string; AContext: TIdContext);
  227. procedure DoReplyUnknownCommand(AContext: TIdContext; ALine: string); override;
  228. procedure DoBounce(ASender: TIdCommand; ALegacy: Boolean);
  229. procedure CommandPRIVMSG(ASender: TIdCommand);
  230. procedure CommandNOTICE(ASender: TIdCommand);
  231. procedure CommandJOIN(ASender: TIdCommand);
  232. procedure CommandPART(ASender: TIdCommand);
  233. procedure CommandKICK(ASender: TIdCommand);
  234. procedure CommandMODE(ASender: TIdCommand);
  235. procedure CommandNICK(ASender: TIdCommand);
  236. procedure CommandQUIT(ASender: TIdCommand);
  237. procedure CommandSQUIT(ASender: TIdCommand);
  238. procedure CommandINVITE(ASender: TIdCommand);
  239. procedure CommandKILL(ASender: TIdCommand);
  240. procedure CommandPING(ASender: TIdCommand);
  241. procedure CommandERROR(ASender: TIdCommand);
  242. procedure CommandWALLOPS(ASender: TIdCommand);
  243. procedure CommandTOPIC(ASender: TIdCommand);
  244. procedure CommandWELCOME(ASender: TIdCommand);
  245. procedure CommandYOURHOST(ASender: TIdCommand);
  246. procedure CommandCREATED(ASender: TIdCommand);
  247. procedure CommandMYINFO(ASender: TIdCommand);
  248. procedure CommandISUPPORT(ASender: TIdCommand);
  249. procedure CommandBOUNCE(ASender: TIdCommand);
  250. procedure CommandUSERHOST(ASender: TIdCommand);
  251. procedure CommandISON(ASender: TIdCommand);
  252. procedure CommandWHOIS(ASender: TIdCommand);
  253. procedure CommandENDOFWHOIS(ASender: TIdCommand);
  254. procedure CommandWHOWAS(ASender: TIdCommand);
  255. procedure CommandENDOFWHOWAS(ASender: TIdCommand);
  256. procedure CommandLISTSTART(ASender: TIdCommand);
  257. procedure CommandLIST(ASender: TIdCommand);
  258. procedure CommandLISTEND(ASender: TIdCommand);
  259. procedure CommandAWAY(ASender: TIdCommand);
  260. procedure CommandINVITING(ASender: TIdCommand);
  261. procedure CommandSUMMONING(ASender: TIdCommand);
  262. procedure CommandINVITELIST(ASender: TIdCommand);
  263. procedure CommandENDOFINVITELIST(ASender: TIdCommand);
  264. procedure CommandEXCEPTLIST(ASender: TIdCommand);
  265. procedure CommandENDOFEXCEPTLIST(ASender: TIdCommand);
  266. procedure CommandWHOREPLY(ASender: TIdCommand);
  267. procedure CommandENDOFWHO(ASender: TIdCommand);
  268. procedure CommandNAMEREPLY(ASender: TIdCommand);
  269. procedure CommandENDOFNAMES(ASender: TIdCommand);
  270. procedure CommandLINKS(ASender: TIdCommand);
  271. procedure CommandENDOFLINKS(ASender: TIdCommand);
  272. procedure CommandBANLIST(ASender: TIdCommand);
  273. procedure CommandENDOFBANLIST(ASender: TIdCommand);
  274. procedure CommandINFO(ASender: TIdCommand);
  275. procedure CommandENDOFINFO(ASender: TIdCommand);
  276. procedure CommandMOTD(ASender: TIdCommand);
  277. procedure CommandENDOFMOTD(ASender: TIdCommand);
  278. procedure CommandREHASHING(ASender: TIdCommand);
  279. procedure CommandUSERSSTART(ASender: TIdCommand);
  280. procedure CommandUSERS(ASender: TIdCommand);
  281. procedure CommandENDOFUSERS(ASender: TIdCommand);
  282. procedure CommandENDOFSTATS(ASender: TIdCommand);
  283. procedure CommandSERVLIST(ASender: TIdCommand);
  284. procedure CommandSERVLISTEND(ASender: TIdCommand);
  285. procedure CommandTIME(ASender: TIdCommand);
  286. procedure CommandSERVICE(ASender: TIdCommand);
  287. procedure CommandVERSION(ASender: TIdCommand);
  288. procedure CommandCHANMODE(ASender: TIdCommand);
  289. procedure CommandOPER(ASender: TIdCommand);
  290. procedure CommandNICKINUSE(ASender: TIdCommand);
  291. //
  292. procedure AssignIRCClientCommands;
  293. function GetCmdHandlerClass: TIdCommandHandlerClass; override;
  294. procedure SetIOHandler(AValue: TIdIOHandler); override;
  295. procedure InitComponent; override;
  296. public
  297. destructor Destroy; override;
  298. //
  299. procedure Connect; override;
  300. procedure Disconnect(const AReason: String = ''); reintroduce;
  301. //
  302. function IsChannel(const AChannel: String): Boolean;
  303. function IsOp(const ANickname: String): Boolean;
  304. function IsVoice(const ANickname: String): Boolean;
  305. procedure Raw(const ALine: String);
  306. procedure Say(const ATarget, AMsg: String);
  307. procedure Notice(const ATarget, AMsg: String);
  308. procedure Action(const ATarget, AMsg: String);
  309. procedure CTCPQuery(const ATarget, ACommand, AParameters: String);
  310. procedure CTCPReply(const ATarget, ACTCP, AReply: String);
  311. procedure Join(const AChannel: String; const AKey: String ='');
  312. procedure Part(const AChannel: String; const AReason: String = '');
  313. procedure Kick(const AChannel, ANickname: String; const AReason: String = '');
  314. procedure SetChannelMode(const AChannel, AMode: String; const AParams: String = '');
  315. procedure SetUserMode(const ANickname, AMode: String);
  316. procedure GetChannelTopic(const AChannel: String);
  317. procedure SetChannelTopic(const AChannel, ATopic: String);
  318. procedure SetAway(const AMsg: String);
  319. procedure Op(const AChannel, ANickname: String);
  320. procedure Deop(const AChannel, ANickname: String);
  321. procedure Voice(const AChannel, ANickname: String);
  322. procedure Devoice(const AChannel, ANickname: String);
  323. procedure Ban(const AChannel, AHostmask: String);
  324. procedure Unban(const AChannel, AHostmask: String);
  325. procedure RegisterService(const ANickname, ADistribution, AInfo: String; AType: Integer);
  326. procedure ListChannelNicknames(const AChannel: String; const ATarget: String = '');
  327. procedure ListChannel(const AChannel: String; const ATarget: String = '');
  328. procedure Invite(const ANickname, AChannel: String);
  329. procedure GetMessageOfTheDay(const ATarget: String = '');
  330. procedure GetNetworkStatus(const AHostMask: String = ''; const ATarget: String = '');
  331. procedure GetServerVersion(const ATarget: String = '');
  332. procedure GetServerStatus(AQuery: TIdIRCStat; const ATarget: String = '');
  333. procedure ListKnownServerNames(const ARemoteHost: String = ''; const AHostMask: String = '');
  334. procedure QueryServerTime(const ATarget: String = '');
  335. procedure RequestServerConnect(const ATargetHost: String; APort: Integer; const ARemoteHost: String = '');
  336. procedure TraceServer(const ATarget: String = '');
  337. procedure GetAdminInfo(const ATarget: String = '');
  338. procedure GetServerInfo(const ATarget: String = '');
  339. procedure ListNetworkServices(const AHostMask: String = ''; const AType: String = '');
  340. procedure QueryService(const AServiceName, AMessage: String);
  341. procedure Who(const AMask: String; AOnlyAdmins: Boolean);
  342. procedure WhoIs(const AMask: String; const ATarget: String = '');
  343. procedure WhoWas(const ANickname: String; ACount: Integer = -1; const ATarget: String = '');
  344. procedure Kill(const ANickname, AComment: String);
  345. procedure Ping(const AServer1: String; const AServer2: String = '');
  346. procedure Pong(const AServer1: String; const AServer2: String = '');
  347. procedure Error(const AMessage: String);
  348. procedure ReHash;
  349. procedure Die;
  350. procedure Restart;
  351. procedure Summon(const ANickname: String; const ATarget: String = ''; const AChannel: String = '');
  352. procedure ListServerUsers(const ATarget: String = '');
  353. procedure SayWALLOPS(const AMessage: String);
  354. procedure GetUserInfo(const ANickname: String);
  355. procedure GetUsersInfo(const ANicknames: array of String);
  356. procedure IsOnIRC(const ANickname: String); overload;
  357. procedure IsOnIRC(const ANicknames: array of String); overload;
  358. procedure BecomeOp(const ANickname, APassword: String);
  359. procedure SQuit(const AHost, AComment: String);
  360. procedure SetChannelLimit(const AChannel: String; ALimit: Integer);
  361. procedure SetChannelKey(const AChannel, AKey: String);
  362. //
  363. property Away: Boolean read FUserAway;
  364. property SenderNick: String read FSenderNick;
  365. property SenderHost: String read FSenderHost;
  366. published
  367. property Nickname: String read FNickname write SetNickname;
  368. property AltNickname: String read FAltNickname write FAltNickname;
  369. property UsedNickname: String read GetUsedNickname; // returns Nickname or AltNickname
  370. property Username: String read FUsername write SetUsername;
  371. property RealName: String read FRealName write FRealName;
  372. property Password: String read FPassword write FPassword;
  373. property Port default IdPORT_IRC;
  374. property Replies: TIdIRCReplies read FReplies write SetIdIRCReplies;
  375. property UserMode: TIdIRCUserModes read FUserMode write SetIdIRCUserMode;
  376. { Events }
  377. property OnServerWelcome: TIdIRCServerMsgEvent read FOnSWelcome write FOnSWelcome;
  378. property OnYourHost: TIdIRCServerMsgEvent read FOnYourHost write FOnYourHost;
  379. property OnServerCreated: TIdIRCServerMsgEvent read FOnSCreated write FOnSCreated;
  380. property OnMyInfo: TIdIRCMyInfoEvent read FOnMyInfo write FOnMyInfo;
  381. property OnBounce: TIdIRCBounceEvent read FOnBounce write FOnBounce;
  382. property OnISupport: TIdIRCISupportEvent read FOnISupport write FOnISupport;
  383. property OnPingPong: TIdIRCPingPongEvent read FOnPingPong write FOnPingPong;
  384. property OnPrivateMessage: TIdIRCPrivMessageEvent read FOnPrivMessage write FOnPrivMessage;
  385. property OnNotice: TIdIRCNoticeEvent read FOnNotice write FOnNotice;
  386. property OnRehash: TIdIRCRehashEvent read FOnRehash write FOnRehash;
  387. property OnSummon: TIdIRCSummonEvent read FOnSummon write FOnSummon;
  388. property OnWallops: TIdIRCWallopsEvent read FOnWallops write FOnWallops;
  389. property OnIsOnIRC: TIdIRCIsOnIRCEvent read FOnIsOnIRC write FOnIsOnIRC;
  390. property OnAway: TIdIRCAwayEvent read FOnAway write FOnAway;
  391. property OnJoin: TIdIRCJoinEvent read FOnJoin write FOnJoin;
  392. property OnPart: TIdIRCPartEvent read FOnPart write FOnPart;
  393. property OnTopic: TIdIRCTopicEvent read FOnTopic write FOnTopic;
  394. property OnKick: TIdIRCKickEvent read FOnKick write FOnKick;
  395. property OnMOTD: TIdIRCMOTDEvent read FOnMOTD write FOnMOTD;
  396. property OnTrace: TIdIRCServerTraceEvent read FOnTrace write FOnTrace;
  397. property OnOp: TIdIRCOpEvent read FOnOp write FOnOp;
  398. property OnInviting: TIdIRCInvitingEvent read FOnInviting write FOnInviting;
  399. property OnInvite: TIdIRCInviteEvent read FOnInvite write FOnInvite;
  400. property OnBanListReceived: TIdIRCChanBANListEvent read FOnBANList write FOnBANList;
  401. property OnExceptionListReceived: TIdIRCChanEXCListEvent read FOnEXCList write FOnEXCList;
  402. property OnInvitationListReceived: TIdIRCChanINVListEvent read FOnINVList write FOnINVList;
  403. property OnServerListReceived: TIdIRCServerListEvent read FOnSvrList write FOnSvrList;
  404. property OnNicknamesListReceived: TIdIRCNickListEvent read FOnNickList write FOnNickList;
  405. property OnServerUsersListReceived: TIdIRCServerUsersEvent read FOnSvrUsers write FOnSvrUsers;
  406. property OnServerStatsReceived: TIdIRCServerStatsEvent read FOnSvrStats write FOnSvrStats;
  407. property OnKnownServersListReceived: TIdIRCKnownServerNamesEvent read FOnKnownSvrs write FOnKnownSvrs;
  408. property OnAdminInfoReceived: TIdIRCAdminInfoRecvEvent read FOnAdminInfo write FOnAdminInfo;
  409. property OnUserInfoReceived: TIdIRCUserInfoRecvEvent read FOnUserInfo write FOnUserInfo;
  410. property OnWho: TIdIRCWhoEvent read FOnWho write FOnWho;
  411. property OnWhoIs: TIdIRCWhoIsEvent read FOnWhoIs write FOnWhoIs;
  412. property OnWhoWas: TIdIRCWhoWasEvent read FOnWhoWas write FOnWhoWas;
  413. property OnChannelMode: TIdIRCChanModeEvent read FOnChanMode write FOnChanMode;
  414. property OnUserMode: TIdIRCUserModeEvent read FOnUserMode write FOnUserMode;
  415. property OnCTCPQuery: TIdIRCCTCPQueryEvent read FOnCTCPQry write FOnCTCPQry;
  416. property OnCTCPReply: TIdIRCCTCPReplyEvent read FOnCTCPRep write FOnCTCPRep;
  417. property OnDCCChat: TIdIRCDCCChatEvent read FOnDCCChat write FOnDCCChat;
  418. property OnDCCSend: TIdIRCDCCSendEvent read FOnDCCSend write FOnDCCSend;
  419. property OnDCCResume: TIdIRCDCCResumeEvent read FOnDCCResume write FOnDCCResume;
  420. property OnDCCAccept: TIdIRCDCCAcceptEvent read FOnDCCAccept write FOnDCCAccept;
  421. property OnServerError: TIdIRCServerErrorEvent read FOnServerError write FOnServerError;
  422. property OnNicknameError: TIdIRCNickErrorEvent read FOnNickError write FOnNickError;
  423. property OnKillError: TIdIRCKillErrorEvent read FOnKillError write FOnKillError;
  424. property OnNicknameChange: TIdIRCNicknameChangedEvent read FOnNickChange write FOnNickChange;
  425. property OnKill: TIdIRCKillEvent read FOnKill write FOnKill;
  426. property OnQuit: TIdIRCQuitEvent read FOnQuit write FOnQuit;
  427. property OnServerQuit: TIdIRCSvrQuitEvent read FOnSvrQuit write FOnSvrQuit;
  428. property OnServerTime: TIdIRCSvrTimeEvent read FOnSvrTime write FOnSvrTime;
  429. property OnService: TIdIRCServiceEvent read FOnService write FOnService;
  430. property OnServerVersion: TIdIRCSvrVersionEvent read FOnSvrVersion write FOnSvrVersion;
  431. property OnRaw: TIdIRCRawEvent read FOnRaw write FOnRaw;
  432. end;
  433. implementation
  434. uses
  435. IdGlobalProtocols, IdResourceStringsProtocols, IdSSL,
  436. IdStack, IdBaseComponent, SysUtils;
  437. const
  438. IdIRCCTCP: array[0..11] of String = ('ACTION', 'SOUND', 'PING', 'FINGER', {do not localize}
  439. 'USERINFO', 'VERSION', 'CLIENTINFO', 'TIME', 'ERROR', 'DCC', 'SED', 'ERRMSG'); {do not localize}
  440. MQuote = #16;
  441. XDelim = #1;
  442. XQuote = #92;
  443. { TIdIRCReplies }
  444. constructor TIdIRCReplies.Create;
  445. begin
  446. inherited Create;
  447. //
  448. end;
  449. procedure TIdIRCReplies.Assign(Source: TPersistent);
  450. var
  451. LSource: TIdIRCReplies;
  452. begin
  453. if Source is TIdIRCReplies then
  454. begin
  455. LSource := TIdIRCReplies(Source);
  456. FFinger := LSource.Finger;
  457. FFinger := LSource.Finger;
  458. FVersion := LSource.Version;
  459. FUserInfo := LSource.UserInfo;
  460. FClientInfo := LSource.ClientInfo;
  461. end else begin
  462. inherited Assign(Source);
  463. end;
  464. end;
  465. { TIdIRC }
  466. // RLebeau 1/7/2010: SysUtils.TrimLeft() removes all characters < #32, but
  467. // CTC requires character #1, so don't remove that character when parsing
  468. // IRC parameters in FetchIRCParam()...
  469. //
  470. function IRCTrimLeft(const S: string): string;
  471. var
  472. I, L: Integer;
  473. begin
  474. L := Length(S);
  475. I := 1;
  476. while (I <= L) and (S[I] <= ' ') and (S[I] <> XDelim) do begin
  477. Inc(I);
  478. end;
  479. Result := Copy(S, I, Maxint);
  480. end;
  481. function FetchIRCParam(var S: String): String;
  482. var
  483. LTmp: String;
  484. begin
  485. LTmp := IRCTrimLeft(S);
  486. if TextStartsWith(LTmp, ':') then
  487. begin
  488. Result := Copy(LTmp, 2, MaxInt);
  489. S := '';
  490. end else
  491. begin
  492. Result := Fetch(LTmp, ' ');
  493. S := IRCTrimLeft(LTmp);
  494. end;
  495. end;
  496. function IRCQuote(const S: String): String;
  497. begin
  498. // IMPORTANT! MQuote needs to be the first character in the replacement
  499. // list, otherwise it will end up being double-escaped if the other
  500. // character get replaced, which will produce the wrong output!!
  501. Result := StringsReplace(S, [MQuote, #0, LF, CR], [MQuote+MQuote, MQuote+'0', MQuote+'n', MQuote+'r']);
  502. end;
  503. {$IFDEF STRING_IS_IMMUTABLE}
  504. function FindCharInSB(const ASB: TIdStringBuilder; AChar: Char; AStart: Integer): Integer;
  505. begin
  506. for Result := AStart to ASB.Length-1 do begin
  507. if ASB[Result] = AChar then begin
  508. Exit;
  509. end;
  510. end;
  511. Result := -1;
  512. end;
  513. {$ENDIF}
  514. function IRCUnquote(const S: String): String;
  515. var
  516. I, L: Integer;
  517. {$IFDEF STRING_IS_IMMUTABLE}
  518. LSB: TIdStringBuilder;
  519. {$ENDIF}
  520. begin
  521. {$IFDEF STRING_IS_IMMUTABLE}
  522. LSB := TIdStringBuilder.Create(S);
  523. L := LSB.Length;
  524. I := 0;
  525. while I < L do begin
  526. I := FindCharInSB(LSB, MQuote, I);
  527. if I = -1 then begin
  528. Break;
  529. end;
  530. LSB.Remove(I, 1);
  531. Dec(L);
  532. if I >= L then begin
  533. Break;
  534. end;
  535. case LSB[I] of
  536. '0': LSB[I] := #0;
  537. 'n': LSB[I] := LF;
  538. 'r': LSB[I] := CR;
  539. end;
  540. Inc(I);
  541. end;
  542. Result := LSB.ToString;
  543. {$ELSE}
  544. Result := S;
  545. L := Length(Result);
  546. I := 1;
  547. while I <= L do begin
  548. I := PosIdx(MQuote, Result, I);
  549. if I = 0 then begin
  550. Break;
  551. end;
  552. IdDelete(Result, I, 1);
  553. Dec(L);
  554. if I > L then begin
  555. Break;
  556. end;
  557. case Result[I] of
  558. '0': Result[I] := #0;
  559. 'n': Result[I] := LF;
  560. 'r': Result[I] := CR;
  561. end;
  562. Inc(I);
  563. end;
  564. {$ENDIF}
  565. end;
  566. function CTCPQuote(const S: String): String;
  567. begin
  568. Result := StringsReplace(S, [XDelim, XQuote], [XQuote+'a', XQuote+XQuote]);
  569. end;
  570. function CTCPUnquote(const S: String): String;
  571. var
  572. I, L: Integer;
  573. {$IFDEF STRING_IS_IMMUTABLE}
  574. LSB: TIdStringBuilder;
  575. {$ENDIF}
  576. begin
  577. {$IFDEF STRING_IS_IMMUTABLE}
  578. LSB := TIdStringBuilder.Create(S);
  579. L := LSB.Length;
  580. I := 0;
  581. while I < L do begin
  582. I := FindCharInSB(LSB, XQuote, I);
  583. if I = -1 then begin
  584. Break;
  585. end;
  586. LSB.Remove(I, 1);
  587. Dec(L);
  588. if I >= L then begin
  589. Break;
  590. end;
  591. if LSB[I] = 'a' then begin
  592. LSB[I] := XDelim;
  593. end;
  594. Inc(I);
  595. end;
  596. Result := LSB.ToString;
  597. {$ELSE}
  598. Result := S;
  599. L := Length(Result);
  600. I := 1;
  601. while I <= L do begin
  602. I := PosIdx(XQuote, Result, I);
  603. if I = 0 then begin
  604. Break;
  605. end;
  606. IdDelete(Result, I, 1);
  607. Dec(L);
  608. if I > L then begin
  609. Break;
  610. end;
  611. if Result[I] = 'a' then begin
  612. Result[I] := XDelim;
  613. end;
  614. Inc(I);
  615. end;
  616. {$ENDIF}
  617. end;
  618. procedure ExtractCTCPs(var AText: String; CTCPs: TStrings);
  619. var
  620. LTmp: String;
  621. I, J, K: Integer;
  622. begin
  623. I := 1;
  624. repeat
  625. J := PosIdx(XDelim, AText, I);
  626. if J = 0 then begin
  627. Break;
  628. end;
  629. K := PosIdx(XDelim, AText, J+1);
  630. if K = 0 then begin
  631. Break;
  632. end;
  633. LTmp := Copy(AText, J+1, K-J-1);
  634. LTmp := CTCPUnquote(LTmp);
  635. CTCPs.Add(LTmp);
  636. IdDelete(AText, J, (K-J)+1);
  637. I := J;
  638. until False;
  639. end;
  640. type
  641. TIdIRCCommandHandler = class(TIdCommandHandler)
  642. public
  643. procedure DoParseParams(AUnparsedParams: string; AParams: TStrings); override;
  644. end;
  645. procedure TIdIRCCommandHandler.DoParseParams(AUnparsedParams: string; AParams: TStrings);
  646. begin
  647. AParams.BeginUpdate;
  648. try
  649. AParams.Clear;
  650. while AUnparsedParams <> '' do begin
  651. AParams.Add(FetchIRCParam(AUnparsedParams));
  652. end;
  653. finally
  654. AParams.EndUpdate;
  655. end;
  656. end;
  657. function TIdIRC.GetCmdHandlerClass: TIdCommandHandlerClass;
  658. begin
  659. Result := TIdIRCCommandHandler;
  660. end;
  661. procedure TIdIRC.InitComponent;
  662. begin
  663. inherited InitComponent;
  664. //
  665. FReplies := TIdIRCReplies.Create;
  666. Port := IdPORT_IRC;
  667. FUserMode := [];
  668. // RLebeau 2/21/08: for the IRC protocol, RFC 2812 section 2.4 says that
  669. // clients are not allowed to issue numeric replies for server-issued
  670. // commands. Added the PerformReplies property so TIdIRC can specify
  671. // that behavior.
  672. CommandHandlers.PerformReplies := False;
  673. // RLebeau 3/11/08: most of the command handlers should parse parameters by default
  674. CommandHandlers.ParseParamsDefault := True;
  675. if not IsDesignTime then begin
  676. AssignIRCClientCommands;
  677. end;
  678. end;
  679. destructor TIdIRC.Destroy;
  680. begin
  681. FreeAndNil(FReplies);
  682. FreeAndNil(FBans);
  683. FreeAndNil(FExcepts);
  684. FreeAndNil(FInvites);
  685. FreeAndNil(FLinks);
  686. FreeAndNil(FMotd);
  687. FreeAndNil(FNames);
  688. FreeAndNil(FWho);
  689. FreeAndNil(FWhoIs);
  690. FreeAndNil(FWhoWas);
  691. FreeAndNil(FSvrList);
  692. FreeAndNil(FUsers);
  693. inherited Destroy;
  694. end;
  695. function TIdIRC.GetUserMode: String;
  696. const
  697. IdIRCUserModeChars: array[TIdIRCUserMode] of Char = ('a', 'i', 'w', 'r', 'o', 'O', 's'); {do not localize}
  698. var
  699. i: TIdIRCUserMode;
  700. begin
  701. if FUserMode <> [] then
  702. begin
  703. Result := '+';
  704. for i := amAway to amReceiveServerNotices do begin
  705. if i in FUserMode then begin
  706. Result := Result + IdIRCUserModeChars[i];
  707. end;
  708. end;
  709. end else begin
  710. Result := '0';
  711. end;
  712. end;
  713. procedure TIdIRC.Connect;
  714. begin
  715. // I doubt that there is explicit SSL support in the IRC protocol
  716. if (IOHandler is TIdSSLIOHandlerSocketBase) then begin
  717. (IOHandler as TIdSSLIOHandlerSocketBase).PassThrough := False;
  718. end;
  719. inherited Connect;
  720. //
  721. try
  722. FAltNickUsed := False;
  723. if FPassword <> '' then begin
  724. Raw(IndyFormat('PASS %s', [FPassword])); {do not localize}
  725. end;
  726. SetNickname(FNickname);
  727. SetUsername(FUsername);
  728. except
  729. on E: EIdSocketError do begin
  730. inherited Disconnect;
  731. IndyRaiseOuterException(EIdIRCError.Create(RSIRCCannotConnect));
  732. end;
  733. end;
  734. end;
  735. procedure TIdIRC.Disconnect(const AReason: String = '');
  736. begin
  737. try
  738. Raw(IndyFormat('QUIT :%s', [AReason])); {do not localize}
  739. finally
  740. inherited Disconnect;
  741. end;
  742. end;
  743. procedure TIdIRC.Raw(const ALine: String);
  744. begin
  745. if Connected then begin
  746. if Assigned(FOnRaw) then begin
  747. // TODO: use FListeningThread.FContext instead of nil...
  748. FOnRaw(nil, False, ALine);
  749. end;
  750. IOHandler.WriteLn(IRCQuote(ALine));
  751. end;
  752. end;
  753. procedure TIdIRC.AssignIRCClientCommands;
  754. var
  755. LCommandHandler: TIdCommandHandler;
  756. begin
  757. { Text commands }
  758. //PRIVMSG Nickname/#channel :message
  759. LCommandHandler := CommandHandlers.Add;
  760. LCommandHandler.Command := 'PRIVMSG'; {do not localize}
  761. LCommandHandler.OnCommand := CommandPRIVMSG;
  762. LCommandHandler.ParseParams := False;
  763. //NOTICE Nickname/#channel :message
  764. LCommandHandler := CommandHandlers.Add;
  765. LCommandHandler.Command := 'NOTICE'; {do not localize}
  766. LCommandHandler.OnCommand := CommandNOTICE;
  767. LCommandHandler.ParseParams := False;
  768. //JOIN #channel
  769. LCommandHandler := CommandHandlers.Add;
  770. LCommandHandler.Command := 'JOIN'; {do not localize}
  771. LCommandHandler.OnCommand := CommandJOIN;
  772. //PART #channel
  773. LCommandHandler := CommandHandlers.Add;
  774. LCommandHandler.Command := 'PART'; {do not localize}
  775. LCommandHandler.OnCommand := CommandPART;
  776. //KICK #channel target :reason
  777. LCommandHandler := CommandHandlers.Add;
  778. LCommandHandler.Command := 'KICK'; {do not localize}
  779. LCommandHandler.OnCommand := CommandKICK;
  780. //MODE Nickname/#channel +/-modes parameters...
  781. LCommandHandler := CommandHandlers.Add;
  782. LCommandHandler.Command := 'MODE'; {do not localize}
  783. LCommandHandler.OnCommand := CommandMODE;
  784. LCommandHandler.ParseParams := False;
  785. //NICK newNickname
  786. LCommandHandler := CommandHandlers.Add;
  787. LCommandHandler.Command := 'NICK'; {do not localize}
  788. LCommandHandler.OnCommand := CommandNICK;
  789. //QUIT :reason
  790. LCommandHandler := CommandHandlers.Add;
  791. LCommandHandler.Command := 'QUIT'; {do not localize}
  792. LCommandHandler.OnCommand := CommandQUIT;
  793. //SQUIT server :reason
  794. LCommandHandler := CommandHandlers.Add;
  795. LCommandHandler.Command := 'SQUIT'; {do not localize}
  796. LCommandHandler.OnCommand := CommandSQUIT;
  797. //INVITE Nickname :#channel
  798. LCommandHandler := CommandHandlers.Add;
  799. LCommandHandler.Command := 'INVITE'; {do not localize}
  800. LCommandHandler.OnCommand := CommandINVITE;
  801. //KILL Nickname :reason
  802. LCommandHandler := CommandHandlers.Add;
  803. LCommandHandler.Command := 'KILL'; {do not localize}
  804. LCommandHandler.OnCommand := CommandKILL;
  805. //PING server
  806. LCommandHandler := CommandHandlers.Add;
  807. LCommandHandler.Command := 'PING'; {do not localize}
  808. LCommandHandler.OnCommand := CommandPING;
  809. //WALLOPS :message
  810. LCommandHandler := CommandHandlers.Add;
  811. LCommandHandler.Command := 'WALLOPS'; {do not localize}
  812. LCommandHandler.OnCommand := CommandWALLOPS;
  813. LCommandHandler.ParseParams := False;
  814. //TOPIC
  815. LCommandHandler := CommandHandlers.Add;
  816. LCommandHandler.Command := 'TOPIC'; {do not localize}
  817. LCommandHandler.OnCommand := CommandTOPIC;
  818. //ERROR message
  819. LCommandHandler := CommandHandlers.Add;
  820. LCommandHandler.Command := 'ERROR'; {do not localize}
  821. LCommandHandler.OnCommand := CommandERROR;
  822. LCommandHandler.ParseParams := False;
  823. { Numeric commands, refer to http://www.alien.net.au/irc/irc2numerics.html }
  824. //RPL_WELCOME
  825. LCommandHandler := CommandHandlers.Add;
  826. LCommandHandler.Command := '001'; {do not localize}
  827. LCommandHandler.OnCommand := CommandWELCOME;
  828. LCommandHandler.ParseParams := False;
  829. //RPL_YOURHOST
  830. LCommandHandler := CommandHandlers.Add;
  831. LCommandHandler.Command := '002'; {do not localize}
  832. LCommandHandler.OnCommand := CommandYOURHOST;
  833. //RPL_CREATED
  834. LCommandHandler := CommandHandlers.Add;
  835. LCommandHandler.Command := '003'; {do not localize}
  836. LCommandHandler.OnCommand := CommandCREATED;
  837. //RPL_MYINFO
  838. LCommandHandler := CommandHandlers.Add;
  839. LCommandHandler.Command := '004'; {do not localize}
  840. LCommandHandler.OnCommand := CommandMYINFO;
  841. LCommandHandler.ParseParams := False;
  842. //RPL_BOUNCE (deprecated), RPL_ISUPPORT (new)
  843. LCommandHandler := CommandHandlers.Add;
  844. LCommandHandler.Command := '005'; {do not localize}
  845. //LCommandHandler.OnCommand := CommandBOUNCE; // deprecated
  846. LCommandHandler.OnCommand := CommandISUPPORT;
  847. { TODO:
  848. 008 RPL_SNOMASK ircu Server notice mask (hex)
  849. 009 RPL_STATMEMTOT ircu
  850. 014 RPL_YOURCOOKIE Hybrid?
  851. 042 RPL_YOURID IRCnet
  852. 043 RPL_SAVENICK IRCnet :<info> Sent to the client when their nickname was forced to change due to a collision
  853. 050 RPL_ATTEMPTINGJUNC aircd
  854. 051 RPL_ATTEMPTINGREROUTE aircd
  855. 200 RPL_TRACELINK RFC1459 Link <version>[.<debug_level>] <destination> <next_server> [V<protocol_version> <link_uptime_in_seconds> <backstream_sendq> <upstream_sendq>] See RFC
  856. 201 RPL_TRACECONNECTING RFC1459 Try. <class> <server> See RFC
  857. 202 RPL_TRACEHANDSHAKE RFC1459 H.S. <class> <server> See RFC
  858. 203 RPL_TRACEUNKNOWN RFC1459 ???? <class> [<connection_address>] See RFC
  859. 204 RPL_TRACEOPERATOR RFC1459 Oper <class> <nick> See RFC
  860. 205 RPL_TRACEUSER RFC1459 User <class> <nick> See RFC
  861. 206 RPL_TRACESERVER RFC1459 Serv <class> <int>S <int>C <server> <nick!user|*!*>@<host|server> [V<protocol_version>] See RFC
  862. 207 RPL_TRACESERVICE RFC2812 Service <class> <name> <type> <active_type> See RFC
  863. 208 RPL_TRACENEWTYPE RFC1459 <newtype> 0 <client_name> See RFC
  864. 209 RPL_TRACECLASS RFC2812 Class <class> <count> See RFC
  865. 210 RPL_TRACERECONNECT RFC2812
  866. 210 RPL_STATS aircd Used instead of having multiple stats numerics
  867. 211 RPL_STATSLINKINFO RFC1459 <linkname> <sendq> <sent_msgs> <sent_bytes> <recvd_msgs> <rcvd_bytes> <time_open> Reply to STATS (See RFC)
  868. 212 RPL_STATSCOMMANDS RFC1459 <command> <count> [<byte_count> <remote_count>] Reply to STATS (See RFC)
  869. 213 RPL_STATSCLINE RFC1459 C <host> * <name> <port> <class> Reply to STATS (See RFC)
  870. 214 RPL_STATSNLINE RFC1459 N <host> * <name> <port> <class> Reply to STATS (See RFC), Also known as RPL_STATSOLDNLINE (ircu, Unreal)
  871. 215 RPL_STATSILINE RFC1459 I <host> * <host> <port> <class> Reply to STATS (See RFC)
  872. 216 RPL_STATSKLINE RFC1459 K <host> * <username> <port> <class> Reply to STATS (See RFC)
  873. 217 RPL_STATSQLINE RFC1459
  874. 217 RPL_STATSPLINE ircu
  875. 218 RPL_STATSYLINE
  876. }
  877. // RPL_BOUNCE (new)
  878. LCommandHandler := CommandHandlers.Add;
  879. LCommandHandler.Command := '010'; {do not localize}
  880. LCommandHandler.OnCommand := CommandBOUNCE;
  881. //RPL_ENDOFSTATS
  882. LCommandHandler := CommandHandlers.Add;
  883. LCommandHandler.Command := '219'; {do not localize}
  884. LCommandHandler.OnCommand := CommandENDOFSTATS;
  885. {TODO:
  886. 221 RPL_UMODEIS RFC1459 <user_modes> [<user_mode_params>] Information about a user's own modes. Some daemons have extended the mode command and certain modes take parameters (like channel modes).
  887. }
  888. //RPL_SERVLIST
  889. LCommandHandler := CommandHandlers.Add;
  890. LCommandHandler.Command := '234'; {do not localize}
  891. LCommandHandler.OnCommand := CommandSERVLIST;
  892. //RPL_SERVLISTEND
  893. LCommandHandler := CommandHandlers.Add;
  894. LCommandHandler.Command := '235'; {do not localize}
  895. LCommandHandler.OnCommand := CommandSERVLISTEND;
  896. {TODO:
  897. 236 RPL_STATSVERBOSE ircu Verbose server list?
  898. 237 RPL_STATSENGINE ircu Engine name?
  899. 239 RPL_STATSIAUTH IRCnet
  900. 241 RPL_STATSLLINE RFC1459 L <hostmask> * <servername> <maxdepth> Reply to STATS (See RFC)
  901. 242 RPL_STATSUPTIME RFC1459 :Server Up <days> days <hours>:<minutes>:<seconds> Reply to STATS (See RFC)
  902. 243 RPL_STATSOLINE RFC1459 O <hostmask> * <nick> [:<info>] Reply to STATS (See RFC); The info field is an extension found in some IRC daemons, which returns info such as an e-mail address or the name/job of an operator
  903. 244 RPL_STATSHLINE RFC1459 H <hostmask> * <servername> Reply to STATS (See RFC)
  904. 245 RPL_STATSSLINE Bahamut, IRCnet, Hybrid
  905. 250 RPL_STATSCONN ircu, Unreal
  906. 251 RPL_LUSERCLIENT RFC1459 :There are <int> users and <int> invisible on <int> servers Reply to LUSERS command, other versions exist (eg. RFC2812); Text may vary.
  907. 252 RPL_LUSEROP RFC1459 <int> :<info> Reply to LUSERS command - Number of IRC operators online
  908. 253 RPL_LUSERUNKNOWN RFC1459 <int> :<info> Reply to LUSERS command - Number of unknown/unregistered connections
  909. 254 RPL_LUSERCHANNELS RFC1459 <int> :<info> Reply to LUSERS command - Number of channels formed
  910. 255 RPL_LUSERME RFC1459 :I have <int> clients and <int> servers Reply to LUSERS command - Information about local connections; Text may vary.
  911. 256 RPL_ADMINME RFC1459 <server> :<info> Start of an RPL_ADMIN* reply. In practise, the server parameter is often never given, and instead the info field contains the text 'Administrative info about <server>'. Newer daemons seem to follow the RFC and output the server's hostname in the 'server' parameter, but also output the server name in the text as per traditional daemons.
  912. 257 RPL_ADMINLOC1 RFC1459 :<admin_location> Reply to ADMIN command (Location, first line)
  913. 258 RPL_ADMINLOC2 RFC1459 :<admin_location> Reply to ADMIN command (Location, second line)
  914. 259 RPL_ADMINEMAIL RFC1459 :<email_address> Reply to ADMIN command (E-mail address of administrator)
  915. 261 RPL_TRACELOG RFC1459 File <logfile> <debug_level> See RFC
  916. 263 RPL_TRYAGAIN RFC2812 <command> :<info> When a server drops a command without processing it, it MUST use this reply. Also known as RPL_LOAD_THROTTLED and RPL_LOAD2HI, I'm presuming they do the same thing.
  917. 265 RPL_LOCALUSERS aircd, Hybrid, Hybrid, Bahamut Also known as RPL_CURRENT_LOCAL
  918. 266 RPL_GLOBALUSERS aircd, Hybrid, Hybrid, Bahamut Also known as RPL_CURRENT_GLOBAL
  919. 267 RPL_START_NETSTAT aircd
  920. 268 RPL_NETSTAT aircd
  921. 269 RPL_END_NETSTAT aircd
  922. 270 RPL_PRIVS ircu
  923. 271 RPL_SILELIST ircu
  924. 272 RPL_ENDOFSILELIST ircu
  925. 273 RPL_NOTIFY aircd
  926. 276 RPL_VCHANEXIST
  927. 277 RPL_VCHANLIST
  928. 278 RPL_VCHANHELP
  929. 280 RPL_GLIST ircu
  930. 296 RPL_CHANINFO_KICKS aircd
  931. 299 RPL_END_CHANINFO aircd
  932. 300 RPL_NONE RFC1459 Dummy reply, supposedly only used for debugging/testing new features, however has appeared in production daemons.
  933. }
  934. //RPL_AWAY
  935. LCommandHandler := CommandHandlers.Add;
  936. LCommandHandler.Command := '301'; {do not localize}
  937. LCommandHandler.OnCommand := CommandAWAY;
  938. //RPL_USERHOST
  939. LCommandHandler := CommandHandlers.Add;
  940. LCommandHandler.Command := '302'; {do not localize}
  941. LCommandHandler.OnCommand := CommandUSERHOST;
  942. LCommandHandler.ParseParams := False;
  943. //RPL_ISON
  944. LCommandHandler := CommandHandlers.Add;
  945. LCommandHandler.Command := '303'; {do not localize}
  946. LCommandHandler.OnCommand := CommandISON;
  947. //RPL_UNAWAY
  948. LCommandHandler := CommandHandlers.Add;
  949. LCommandHandler.Command := '305'; {do not localize}
  950. LCommandHandler.OnCommand := CommandAWAY;
  951. //RPL_NOWAWAY
  952. LCommandHandler := CommandHandlers.Add;
  953. LCommandHandler.Command := '306'; {do not localize}
  954. LCommandHandler.OnCommand := CommandAWAY;
  955. //RPL_WHOISUSER
  956. LCommandHandler := CommandHandlers.Add;
  957. LCommandHandler.Command := '311'; {do not localize}
  958. LCommandHandler.OnCommand := CommandWHOIS;
  959. //RPL_WHOISSERVER
  960. LCommandHandler := CommandHandlers.Add;
  961. LCommandHandler.Command := '312'; {do not localize}
  962. LCommandHandler.OnCommand := CommandWHOIS;
  963. //RPL_WHOISOPERATOR
  964. LCommandHandler := CommandHandlers.Add;
  965. LCommandHandler.Command := '313'; {do not localize}
  966. LCommandHandler.OnCommand := CommandWHOIS;
  967. //RPL_WHOWASUSER
  968. LCommandHandler := CommandHandlers.Add;
  969. LCommandHandler.Command := '314';
  970. LCommandHandler.OnCommand := CommandWHOWAS;
  971. //RPL_ENDOFWHO
  972. LCommandHandler := CommandHandlers.Add;
  973. LCommandHandler.Command := '315'; {do not localize}
  974. LCommandHandler.OnCommand := CommandENDOFWHO;
  975. //RPL_WHOISIDLE
  976. LCommandHandler := CommandHandlers.Add;
  977. LCommandHandler.Command := '317'; {do not localize}
  978. LCommandHandler.OnCommand := CommandWHOIS;
  979. //RPL_ENDOFWHOIS
  980. LCommandHandler := CommandHandlers.Add;
  981. LCommandHandler.Command := '318'; {do not localize}
  982. LCommandHandler.OnCommand := CommandENDOFWHOIS;
  983. //RPL_WHOISCHANNELS
  984. LCommandHandler := CommandHandlers.Add;
  985. LCommandHandler.Command := '319'; {do not localize}
  986. LCommandHandler.OnCommand := CommandWHOIS;
  987. {TODO:
  988. 320 RPL_WHOISVIRT AustHex
  989. 320 RPL_WHOIS_HIDDEN Anothernet
  990. 320 RPL_WHOISSPECIAL Unreal
  991. }
  992. //RPL_LISTSTART
  993. LCommandHandler := CommandHandlers.Add;
  994. LCommandHandler.Command := '321'; {do not localize}
  995. LCommandHandler.OnCommand := CommandLISTSTART;
  996. //RPL_LIST
  997. LCommandHandler := CommandHandlers.Add;
  998. LCommandHandler.Command := '322'; {do not localize}
  999. LCommandHandler.OnCommand := CommandLIST;
  1000. //RPL_LISTEND
  1001. LCommandHandler := CommandHandlers.Add;
  1002. LCommandHandler.Command := '323'; {do not localize}
  1003. LCommandHandler.OnCommand := CommandLISTEND;
  1004. //RPL_CHANMODEIS
  1005. LCommandHandler := CommandHandlers.Add;
  1006. LCommandHandler.Command := '324'; {do not localize}
  1007. LCommandHandler.OnCommand := CommandCHANMODE;
  1008. //RPL_UNIQOPIS
  1009. LCommandHandler := CommandHandlers.Add;
  1010. LCommandHandler.Command := '325'; {do not localize}
  1011. //LCommandHandler.OnCommand := CommandUNIQOP;
  1012. {TODO:
  1013. 326 RPL_NOCHANPASS
  1014. 327 RPL_CHPASSUNKNOWN
  1015. 328 RPL_CHANNEL_URL Bahamut, AustHex
  1016. 329 RPL_CREATIONTIME Bahamut
  1017. }
  1018. //RPL_NOTOPIC
  1019. LCommandHandler := CommandHandlers.Add;
  1020. LCommandHandler.Command := '331'; {do not localize}
  1021. LCommandHandler.OnCommand := CommandTOPIC;
  1022. //RPL_TOPIC
  1023. LCommandHandler := CommandHandlers.Add;
  1024. LCommandHandler.Command := '332';
  1025. LCommandHandler.OnCommand := CommandTOPIC;
  1026. {TODO:
  1027. 333 RPL_TOPICWHOTIME ircu
  1028. 339 RPL_BADCHANPASS
  1029. 340 RPL_USERIP ircu
  1030. }
  1031. //RPL_INVITING
  1032. LCommandHandler := CommandHandlers.Add;
  1033. LCommandHandler.Command := '341'; {do not localize}
  1034. LCommandHandler.OnCommand := CommandINVITING;
  1035. //RPL_SUMMONING
  1036. LCommandHandler := CommandHandlers.Add;
  1037. LCommandHandler.Command := '342'; {do not localize}
  1038. LCommandHandler.OnCommand := CommandSUMMONING;
  1039. {TODO:
  1040. 345 RPL_INVITED GameSurge <channel> <user being invited> <user issuing invite> :<user being invited> has been invited by <user issuing invite> Sent to users on a channel when an INVITE command has been issued
  1041. }
  1042. //RPL_INVITELIST
  1043. LCommandHandler := CommandHandlers.Add;
  1044. LCommandHandler.Command := '346'; {do not localize}
  1045. LCommandHandler.OnCommand := CommandINVITELIST;
  1046. //RPL_ENDOFINVITELIST
  1047. LCommandHandler := CommandHandlers.Add;
  1048. LCommandHandler.Command := '347'; {do not localize}
  1049. LCommandHandler.OnCommand := CommandENDOFINVITELIST;
  1050. //RPL_EXCEPTLIST
  1051. LCommandHandler := CommandHandlers.Add;
  1052. LCommandHandler.Command := '348'; {do not localize}
  1053. LCommandHandler.OnCommand := CommandEXCEPTLIST;
  1054. //RPL_ENDOFEXCEPTLIST
  1055. LCommandHandler := CommandHandlers.Add;
  1056. LCommandHandler.Command := '349'; {do not localize}
  1057. LCommandHandler.OnCommand := CommandENDOFEXCEPTLIST;
  1058. //RPL_VERSION
  1059. LCommandHandler := CommandHandlers.Add;
  1060. LCommandHandler.Command := '351'; {do not localize}
  1061. LCommandHandler.OnCommand := CommandVERSION;
  1062. //RPL_WHOREPLY
  1063. LCommandHandler := CommandHandlers.Add;
  1064. LCommandHandler.Command := '352'; {do not localize}
  1065. LCommandHandler.OnCommand := CommandWHOREPLY;
  1066. //RPL_NAMEREPLY
  1067. LCommandHandler := CommandHandlers.Add;
  1068. LCommandHandler.Command := '353'; {do not localize}
  1069. LCommandHandler.OnCommand := CommandNAMEREPLY;
  1070. { TODO:
  1071. 354 RPL_WHOSPCRPL ircu Reply to WHO, however it is a 'special' reply because it is returned using a non-standard (non-RFC1459) format. The format is dictated by the command given by the user, and can vary widely. When this is used, the WHO command was invoked in its 'extended' form, as announced by the 'WHOX' ISUPPORT tag.
  1072. 355 RPL_NAMREPLY_ QuakeNet ( '=' / '*' / '@' ) <channel> ' ' : [ '@' / '+' ] <nick> *( ' ' [ '@' / '+' ] <nick> ) Reply to the "NAMES -d" command - used to show invisible users (when the channel is set +D, QuakeNet relative). The proper define name for this numeric is unknown at this time Also see #353.
  1073. }
  1074. //RPL_LINKS
  1075. LCommandHandler := CommandHandlers.Add;
  1076. LCommandHandler.Command := '364'; {do not localize}
  1077. LCommandHandler.OnCommand := CommandLINKS;
  1078. //RPL_ENDOFLINKS
  1079. LCommandHandler := CommandHandlers.Add;
  1080. LCommandHandler.Command := '365'; {do not localize}
  1081. LCommandHandler.OnCommand := CommandENDOFLINKS;
  1082. //RPL_ENDOFNAMES
  1083. LCommandHandler := CommandHandlers.Add;
  1084. LCommandHandler.Command := '366'; {do not localize}
  1085. LCommandHandler.OnCommand := CommandENDOFNAMES;
  1086. // RPL_BANLIST
  1087. LCommandHandler := CommandHandlers.Add;
  1088. LCommandHandler.Command := '367'; {do not localize}
  1089. LCommandHandler.OnCommand := CommandBANLIST;
  1090. //RPL_ENDOFBANLIST
  1091. LCommandHandler := CommandHandlers.Add;
  1092. LCommandHandler.Command := '368'; {do not localize}
  1093. LCommandHandler.OnCommand := CommandENDOFBANLIST;
  1094. //RPL_ENDOFWHOWAS
  1095. LCommandHandler := CommandHandlers.Add;
  1096. LCommandHandler.Command := '369'; {do not localize}
  1097. LCommandHandler.OnCommand := CommandENDOFWHOWAS;
  1098. //RPL_INFO
  1099. LCommandHandler := CommandHandlers.Add;
  1100. LCommandHandler.Command := '371'; {do not localize}
  1101. LCommandHandler.OnCommand := CommandINFO;
  1102. //RPL_MOTD
  1103. LCommandHandler := CommandHandlers.Add;
  1104. LCommandHandler.Command := '372'; {do not localize}
  1105. LCommandHandler.OnCommand := CommandMOTD;
  1106. //RPL_ENDOFINFO
  1107. LCommandHandler := CommandHandlers.Add;
  1108. LCommandHandler.Command := '374'; {do not localize}
  1109. LCommandHandler.OnCommand := CommandENDOFINFO;
  1110. LCommandHandler.ParseParams := False;
  1111. //RPL_MOTDSTART
  1112. LCommandHandler := CommandHandlers.Add;
  1113. LCommandHandler.Command := '375'; {do not localize}
  1114. LCommandHandler.OnCommand := CommandMOTD;
  1115. //RPL_ENDOFMOTD
  1116. LCommandHandler := CommandHandlers.Add;
  1117. LCommandHandler.Command := '376'; {do not localize}
  1118. LCommandHandler.OnCommand := CommandENDOFMOTD;
  1119. //RPL_YOUREOPER
  1120. LCommandHandler := CommandHandlers.Add;
  1121. LCommandHandler.Command := '381'; {do not localize}
  1122. //LCommandHandler.OnCommand := CommandYOUAREOPER;
  1123. //RPL_REHASHING
  1124. LCommandHandler := CommandHandlers.Add;
  1125. LCommandHandler.Command := '382'; {do not localize}
  1126. LCommandHandler.OnCommand := CommandREHASHING;
  1127. //RPL_YOUARESERVICE
  1128. LCommandHandler := CommandHandlers.Add;
  1129. LCommandHandler.Command := '383'; {do not localize}
  1130. LCommandHandler.OnCommand := CommandSERVICE;
  1131. {TODO:
  1132. 385 RPL_NOTOPERANYMORE AustHex, Hybrid, Unreal
  1133. 388 RPL_ALIST Unreal
  1134. 389 RPL_ENDOFALIST Unreal
  1135. }
  1136. //RPL_TIME
  1137. LCommandHandler := CommandHandlers.Add;
  1138. LCommandHandler.Command := '391'; {do not localize}
  1139. LCommandHandler.OnCommand := CommandTIME;
  1140. //RPL_USERSSTART
  1141. LCommandHandler := CommandHandlers.Add;
  1142. LCommandHandler.Command := '392'; {do not localize}
  1143. LCommandHandler.OnCommand := CommandUSERSSTART;
  1144. //RPL_USERS
  1145. LCommandHandler := CommandHandlers.Add;
  1146. LCommandHandler.Command := '393'; {do not localize}
  1147. LCommandHandler.OnCommand := CommandUSERS;
  1148. //RPL_ENDOFUSERS
  1149. LCommandHandler := CommandHandlers.Add;
  1150. LCommandHandler.Command := '394'; {do not localize}
  1151. LCommandHandler.OnCommand := CommandENDOFUSERS;
  1152. //RPL_NOUSERS
  1153. LCommandHandler := CommandHandlers.Add;
  1154. LCommandHandler.Command := '395'; {do not localize}
  1155. LCommandHandler.OnCommand := CommandUSERS;
  1156. //ERR_NICKNAMEINUSE
  1157. LCommandHandler := CommandHandlers.Add;
  1158. // 433 ERR_NICKNAMEINUSE RFC1459 <nick> :<reason>
  1159. // Returned by the NICK command when the given nickname is already in use
  1160. LCommandHandler.Command := '433'; {do not localize}
  1161. LCommandHandler.OnCommand := CommandNICKINUSE;
  1162. {TODO:
  1163. 396 RPL_HOSTHIDDEN Undernet Reply to a user when user mode +x (host masking) was set successfully
  1164. 400 ERR_UNKNOWNERROR <command> [<?>] :<info> Sent when an error occured executing a command, but it is not specifically known why the command could not be executed.
  1165. 401 ERR_NOSUCHNICK RFC1459 <nick> :<reason> Used to indicate the nickname parameter supplied to a command is currently unused
  1166. 402 ERR_NOSUCHSERVER RFC1459 <server> :<reason> Used to indicate the server name given currently doesn't exist
  1167. 403 ERR_NOSUCHCHANNEL RFC1459 <channel> :<reason> Used to indicate the given channel name is invalid, or does not exist
  1168. 404 ERR_CANNOTSENDTOCHAN RFC1459 <channel> :<reason> Sent to a user who does not have the rights to send a message to a channel
  1169. 405 ERR_TOOMANYCHANNELS RFC1459 <channel> :<reason> Sent to a user when they have joined the maximum number of allowed channels and they tried to join another channel
  1170. 406 ERR_WASNOSUCHNICK RFC1459 <nick> :<reason> Returned by WHOWAS to indicate there was no history information for a given nickname
  1171. 407 ERR_TOOMANYTARGETS RFC1459 <target> :<reason> The given target(s) for a command are ambiguous in that they relate to too many targets
  1172. 408 ERR_NOSUCHSERVICE RFC2812 <service_name> :<reason> Returned to a client which is attempting to send an SQUERY (or other message) to a service which does not exist
  1173. 409 ERR_NOORIGIN RFC1459 :<reason> PING or PONG message missing the originator parameter which is required since these commands must work without valid prefixes
  1174. 411 ERR_NORECIPIENT RFC1459 :<reason> Returned when no recipient is given with a command
  1175. 412 ERR_NOTEXTTOSEND RFC1459 :<reason> Returned when NOTICE/PRIVMSG is used with no message given
  1176. 413 ERR_NOTOPLEVEL RFC1459 <mask> :<reason> Used when a message is being sent to a mask without being limited to a top-level domain (i.e. * instead of *.au)
  1177. 414 ERR_WILDTOPLEVEL RFC1459 <mask> :<reason> Used when a message is being sent to a mask with a wild-card for a top level domain (i.e. *.*)
  1178. 415 ERR_BADMASK RFC2812 <mask> :<reason> Used when a message is being sent to a mask with an invalid syntax
  1179. 416 ERR_TOOMANYMATCHES IRCnet <command> [<mask>] :<info> Returned when too many matches have been found for a command and the output has been truncated. An example would be the WHO command, where by the mask '*' would match everyone on the network! Ouch!
  1180. 416 ERR_QUERYTOOLONG ircu Same as ERR_TOOMANYMATCHES
  1181. 419 ERR_LENGTHTRUNCATED aircd
  1182. 421 ERR_UNKNOWNCOMMAND RFC1459 <command> :<reason> Returned when the given command is unknown to the server (or hidden because of lack of access rights)
  1183. 422 ERR_NOMOTD RFC1459 :<reason> Sent when there is no MOTD to send the client
  1184. 423 ERR_NOADMININFO RFC1459 <server> :<reason> Returned by a server in response to an ADMIN request when no information is available. RFC1459 mentions this in the list of numerics. While it's not listed as a valid reply in section 4.3.7 ('Admin command'), it's confirmed to exist in the real world.
  1185. 424 ERR_FILEERROR RFC1459 :<reason> Generic error message used to report a failed file operation during the processing of a command
  1186. 425 ERR_NOOPERMOTD Unreal
  1187. 429 ERR_TOOMANYAWAY Bahamut
  1188. 430 ERR_EVENTNICKCHANGE AustHex Returned by NICK when the user is not allowed to change their nickname due to a channel event (channel mode +E)
  1189. 431 ERR_NONICKNAMEGIVEN RFC1459 :<reason> Returned when a nickname parameter expected for a command isn't found
  1190. 432 ERR_ERRONEUSNICKNAME RFC1459 <nick> :<reason> Returned after receiving a NICK message which contains a nickname which is considered invalid, such as it's reserved ('anonymous') or contains characters considered invalid for nicknames. This numeric is misspelt, but remains with this name for historical reasons :)
  1191. 436 ERR_NICKCOLLISION RFC1459 <nick> :<reason> Returned by a server to a client when it detects a nickname collision
  1192. 439 ERR_TARGETTOOFAST ircu Also known as many other things, RPL_INVTOOFAST, RPL_MSGTOOFAST etc
  1193. 440 ERR_SERVICESDOWN Bahamut, Unreal
  1194. 441 ERR_USERNOTINCHANNEL RFC1459 <nick> <channel> :<reason> Returned by the server to indicate that the target user of the command is not on the given channel
  1195. 442 ERR_NOTONCHANNEL RFC1459 <channel> :<reason> Returned by the server whenever a client tries to perform a channel effecting command for which the client is not a member
  1196. 443 ERR_USERONCHANNEL RFC1459 <nick> <channel> [:<reason>] Returned when a client tries to invite a user to a channel they're already on
  1197. 444 ERR_NOLOGIN RFC1459 <user> :<reason> Returned by the SUMMON command if a given user was not logged in and could not be summoned
  1198. 445 ERR_SUMMONDISABLED RFC1459 :<reason> Returned by SUMMON when it has been disabled or not implemented
  1199. 446 ERR_USERSDISABLED RFC1459 :<reason> Returned by USERS when it has been disabled or not implemented
  1200. 447 ERR_NONICKCHANGE Unreal
  1201. 449 ERR_NOTIMPLEMENTED Undernet Unspecified Returned when a requested feature is not implemented (and cannot be completed)
  1202. 451 ERR_NOTREGISTERED RFC1459 :<reason> Returned by the server to indicate that the client must be registered before the server will allow it to be parsed in detail
  1203. 452 ERR_IDCOLLISION
  1204. 453 ERR_NICKLOST
  1205. 455 ERR_HOSTILENAME Unreal
  1206. 456 ERR_ACCEPTFULL
  1207. 457 ERR_ACCEPTEXIST
  1208. 458 ERR_ACCEPTNOT
  1209. 459 ERR_NOHIDING Unreal Not allowed to become an invisible operator?
  1210. 460 ERR_NOTFORHALFOPS Unreal
  1211. 461 ERR_NEEDMOREPARAMS RFC1459 <command> :<reason> Returned by the server by any command which requires more parameters than the number of parameters given
  1212. 462 ERR_ALREADYREGISTERED RFC1459 :<reason> Returned by the server to any link which attempts to register again
  1213. 463 ERR_NOPERMFORHOST RFC1459 :<reason> Returned to a client which attempts to register with a server which has been configured to refuse connections from the client's host
  1214. 464 ERR_PASSWDMISMATCH RFC1459 :<reason> Returned by the PASS command to indicate the given password was required and was either not given or was incorrect
  1215. 465 ERR_YOUREBANNEDCREEP RFC1459 :<reason> Returned to a client after an attempt to register on a server configured to ban connections from that client
  1216. 466 ERR_YOUWILLBEBANNED RFC1459 Sent by a server to a user to inform that access to the server will soon be denied
  1217. 467 ERR_KEYSET RFC1459 <channel> :<reason> Returned when the channel key for a channel has already been set
  1218. 468 ERR_INVALIDUSERNAME ircu
  1219. 468 ERR_ONLYSERVERSCANCHANGE Bahamut, Unreal
  1220. 469 ERR_LINKSET Unreal
  1221. 470 ERR_LINKCHANNEL Unreal
  1222. 470 ERR_KICKEDFROMCHAN aircd
  1223. 471 ERR_CHANNELISFULL RFC1459 <channel> :<reason> Returned when attempting to join a channel which is set +l and is already full
  1224. 472 ERR_UNKNOWNMODE RFC1459 <char> :<reason> Returned when a given mode is unknown
  1225. 473 ERR_INVITEONLYCHAN RFC1459 <channel> :<reason> Returned when attempting to join a channel which is invite only without an invitation
  1226. 474 ERR_BANNEDFROMCHAN RFC1459 <channel> :<reason> Returned when attempting to join a channel a user is banned from
  1227. 475 ERR_BADCHANNELKEY RFC1459 <channel> :<reason> Returned when attempting to join a key-locked channel either without a key or with the wrong key
  1228. 476 ERR_BADCHANMASK RFC2812 <channel> :<reason> The given channel mask was invalid
  1229. 478 ERR_BANLISTFULL RFC2812 <channel> <char> :<reason> Returned when a channel access list (i.e. ban list etc) is full and cannot be added to
  1230. 479 ERR_BADCHANNAME Hybrid
  1231. 479 ERR_LINKFAIL Unreal
  1232. 481 ERR_NOPRIVILEGES RFC1459 :<reason> Returned by any command requiring special privileges (eg. IRC operator) to indicate the operation was unsuccessful
  1233. 482 ERR_CHANOPRIVSNEEDED RFC1459 <channel> :<reason> Returned by any command requiring special channel privileges (eg. channel operator) to indicate the operation was unsuccessful
  1234. 483 ERR_CANTKILLSERVER RFC1459 :<reason> Returned by KILL to anyone who tries to kill a server
  1235. 485 ERR_UNIQOPRIVSNEEDED RFC2812 :<reason> Any mode requiring 'channel creator' privileges returns this error if the client is attempting to use it while not a channel creator on the given channel
  1236. 488 ERR_TSLESSCHAN IRCnet
  1237. 491 ERR_NOOPERHOST RFC1459 :<reason> Returned by OPER to a client who cannot become an IRC operator because the server has been configured to disallow the client's host
  1238. 493 ERR_NOFEATURE ircu
  1239. 494 ERR_BADFEATURE ircu
  1240. 495 ERR_BADLOGTYPE ircu
  1241. 496 ERR_BADLOGSYS ircu
  1242. 497 ERR_BADLOGVALUE ircu
  1243. 498 ERR_ISOPERLCHAN ircu
  1244. 499 ERR_CHANOWNPRIVNEEDED Unreal Works just like ERR_CHANOPRIVSNEEDED except it indicates that owner status (+q) is needed. Also see #482.
  1245. 501 ERR_UMODEUNKNOWNFLAG RFC1459 :<reason> Returned by the server to indicate that a MODE message was sent with a nickname parameter and that the mode flag sent was not recognised
  1246. 502 ERR_USERSDONTMATCH RFC1459 :<reason> Error sent to any user trying to view or change the user mode for a user other than themselves
  1247. 503 ERR_GHOSTEDCLIENT Hybrid
  1248. 504 ERR_USERNOTONSERV
  1249. 511 ERR_SILELISTFULL ircu
  1250. 512 ERR_TOOMANYWATCH Bahamut Also known as ERR_NOTIFYFULL (aircd), I presume they are the same
  1251. 513 ERR_BADPING ircu Also known as ERR_NEEDPONG (Unreal/Ultimate) for use during registration, however it's not used in Unreal (and might not be used in Ultimate either).
  1252. 515 ERR_BADEXPIRE ircu
  1253. 516 ERR_DONTCHEAT ircu
  1254. 517 ERR_DISABLED ircu <command> :<info/reason>
  1255. 522 ERR_WHOSYNTAX Bahamut
  1256. 523 ERR_WHOLIMEXCEED Bahamut
  1257. 525 ERR_REMOTEPFX CAPAB USERCMDPFX <nickname> :<reason> Proposed.
  1258. 526 ERR_PFXUNROUTABLE CAPAB USERCMDPFX <nickname> :<reason> Proposed.
  1259. 550 ERR_BADHOSTMASK QuakeNet
  1260. 551 ERR_HOSTUNAVAIL QuakeNet
  1261. 552 ERR_USINGSLINE QuakeNet
  1262. 600 RPL_LOGON Bahamut, Unreal
  1263. 601 RPL_LOGOFF Bahamut, Unreal
  1264. 602 RPL_WATCHOFF Bahamut, Unreal
  1265. 603 RPL_WATCHSTAT Bahamut, Unreal
  1266. 604 RPL_NOWON Bahamut, Unreal
  1267. 605 RPL_NOWOFF Bahamut, Unreal
  1268. 606 RPL_WATCHLIST Bahamut, Unreal
  1269. 607 RPL_ENDOFWATCHLIST Bahamut, Unreal
  1270. 608 RPL_WATCHCLEAR Ultimate
  1271. 611 RPL_ISLOCOP Ultimate
  1272. 612 RPL_ISNOTOPER Ultimate
  1273. 613 RPL_ENDOFISOPER Ultimate
  1274. 618 RPL_DCCLIST
  1275. 624 RPL_OMOTDSTART Ultimate
  1276. 625 RPL_OMOTD Ultimate
  1277. 626 RPL_ENDOFO Ultimate
  1278. 630 RPL_SETTINGS Ultimate
  1279. 631 RPL_ENDOFSETTINGS Ultimate
  1280. 660 RPL_TRACEROUTE_HOP KineIRCd <target> <hop#> [<address> [<hostname> | '*'] <usec_ping>] Returned from the TRACEROUTE IRC-Op command when tracerouting a host
  1281. 661 RPL_TRACEROUTE_START KineIRCd <target> <target_FQDN> <target_address> <max_hops> Start of an RPL_TRACEROUTE_HOP list
  1282. 662 RPL_MODECHANGEWARN KineIRCd ['+' | '-']<mode_char> :<warning> Plain text warning to the user about turning on or off a user mode. If no '+' or '-' prefix is used for the mode char, '+' is presumed.
  1283. 663 RPL_CHANREDIR KineIRCd <old_chan> <new_chan> :<info> Used to notify the client upon JOIN that they are joining a different channel than expected because the IRC Daemon has been set up to map the channel they attempted to join to the channel they eventually will join.
  1284. 664 RPL_SERVMODEIS KineIRCd <server> <modes> <parameters>.. Reply to MODE <servername>. KineIRCd supports server modes to simplify configuration of servers; Similar to RPL_CHANNELMODEIS
  1285. 665 RPL_OTHERUMODEIS KineIRCd <nickname> <modes> Reply to MODE <nickname> to return the user-modes of another user to help troubleshoot connections, etc. Similar to RPL_UMODEIS, however including the target
  1286. 666 RPL_ENDOF_GENERIC KineIRCd <command> [<parameter> ...] :<info> Generic response for new lists to save numerics.
  1287. 670 RPL_WHOWASDETAILS KineIRCd <nick> <type> :<information> Returned by WHOWAS to return extended information (if available). The type field is a number indication what kind of information.
  1288. 671 RPL_WHOISSECURE KineIRCd <nick> <type> [:<info>] Reply to WHOIS command - Returned if the target is connected securely, eg. type may be TLSv1, or SSLv2 etc. If the type is unknown, a '*' may be used.
  1289. 672 RPL_UNKNOWNMODES Ithildin <modes> :<info> Returns a full list of modes that are unknown when a client issues a MODE command (rather than one numeric per mode)
  1290. 673 RPL_CANNOTSETMODES Ithildin <modes> :<info> Returns a full list of modes that cannot be set when a client issues a MODE command
  1291. 678 RPL_LUSERSTAFF KineIRCd <staff_online_count> :<info> Reply to LUSERS command - Number of network staff (or 'helpers') online (differs from Local/Global operators). Similar format to RPL_LUSEROP
  1292. 679 RPL_TIMEONSERVERIS KineIRCd <seconds> [<nanoseconds> | '0'] <timezone> <flags> :<info> Optionally sent upon connection, and/or sent as a reply to the TIME command. This returns the time on the server in a uniform manner. The seconds (and optionally nanoseconds) is the time since the UNIX Epoch, and is used since many existing timestamps in the IRC-2 protocol are done this way (i.e. ban lists). The timezone is hours and minutes each of Greenwich ('[+/-]HHMM'). Since all timestamps sent from the server are in a similar format, this numeric is designed to give clients the ability to provide accurate timestamps to their users.
  1293. 682 RPL_NETWORKS KineIRCd <name> <through_name> <hops> :<info> A reply to the NETWORKS command when requesting a list of known networks (within the IIRC domain).
  1294. 687 RPL_YOURLANGUAGEIS KineIRCd <code(s)> :<info> Reply to the LANGUAGE command, informing the client of the language(s) it has set
  1295. 688 RPL_LANGUAGE KineIRCd <code> <revision> <maintainer> <flags> * :<info> A language reply to LANGUAGE when requesting a list of known languages
  1296. 689 RPL_WHOISSTAFF KineIRCd :<info> The user is a staff member. The information may explain the user's job role, or simply state that they are a part of the network staff. Staff members are not IRC operators, but rather people who have special access in association with network services. KineIRCd uses this numeric instead of the existing numerics due to the overwhelming number of conflicts.
  1297. 690 RPL_WHOISLANGUAGE KineIRCd <nick> <language codes> Reply to WHOIS command - A list of languages someone can speak. The language codes are comma delimitered.
  1298. 702 RPL_MODLIST RatBox <?> 0x<?> <?> <?> Output from the MODLIST command
  1299. 703 RPL_ENDOFMODLIST RatBox :<text> Terminates MODLIST output
  1300. 704 RPL_HELPSTART RatBox <command> :<text> Start of HELP command output
  1301. 705 RPL_HELPTXT RatBox <command> :<text> Output from HELP command
  1302. 706 RPL_ENDOFHELP RatBox <command> :<text> End of HELP command output
  1303. 708 RPL_ETRACEFULL RatBox <?> <?> <?> <?> <?> <?> <?> :<?> Output from 'extended' trace
  1304. 709 RPL_ETRACE RatBox <?> <?> <?> <?> <?> <?> :<?> Output from 'extended' trace
  1305. 710 RPL_KNOCK RatBox <channel> <nick>!<user>@<host> :<text> Message delivered using KNOCK command
  1306. 711 RPL_KNOCKDLVR RatBox <channel> :<text> Message returned from using KNOCK command
  1307. 712 ERR_TOOMANYKNOCK RatBox <channel> :<text> Message returned when too many KNOCKs for a channel have been sent by a user
  1308. 713 ERR_CHANOPEN RatBox <channel> :<text> Message returned from KNOCK when the channel can be freely joined by the user
  1309. 714 ERR_KNOCKONCHAN RatBox <channel> :<text> Message returned from KNOCK when the user has used KNOCK on a channel they have already joined
  1310. 715 ERR_KNOCKDISABLED RatBox :<text> Returned from KNOCK when the command has been disabled
  1311. 716 RPL_TARGUMODEG RatBox <nick> :<info> Sent to indicate the given target is set +g (server-side ignore)
  1312. 717 RPL_TARGNOTIFY RatBox <nick> :<info> Sent following a PRIVMSG/NOTICE to indicate the target has been notified of an attempt to talk to them while they are set +g
  1313. 718 RPL_UMODEGMSG RatBox <nick> <user>@<host> :<info> Sent to a user who is +g to inform them that someone has attempted to talk to them (via PRIVMSG/NOTICE), and that they will need to be accepted (via the ACCEPT command) before being able to talk to them
  1314. 720 RPL_OMOTDSTART RatBox :<text> IRC Operator MOTD header, sent upon OPER command
  1315. 721 RPL_OMOTD RatBox :<text> IRC Operator MOTD text (repeated, usually)
  1316. 722 RPL_ENDOFOMOTD RatBox :<text> IRC operator MOTD footer
  1317. 723 ERR_NOPRIVS RatBox <command> :<text> Returned from an oper command when the IRC operator does not have the relevant operator privileges.
  1318. 724 RPL_TESTMARK RatBox <nick>!<user>@<host> <?> <?> :<text> Reply from an oper command reporting how many users match a given user@host mask
  1319. 725 RPL_TESTLINE RatBox <?> <?> <?> :<?> Reply from an oper command reporting relevant I/K lines that will match a given user@host
  1320. 726 RPL_NOTESTLINE RatBox <?> :<text> Reply from oper command reporting no I/K lines match the given user@host
  1321. 771 RPL_XINFO Ithildin Used to send 'eXtended info' to the client, a replacement for the STATS command to send a large variety of data and minimise numeric pollution.
  1322. 773 RPL_XINFOSTART Ithildin Start of an RPL_XINFO list
  1323. 774 RPL_XINFOEND Ithildin Termination of an RPL_XINFO list
  1324. 972 ERR_CANNOTDOCOMMAND Unreal Works similarly to all of KineIRCd's CANNOT* numerics. This one indicates that a command could not be performed for an arbitrary reason. For example, a halfop trying to kick an op.
  1325. 973 ERR_CANNOTCHANGEUMODE KineIRCd <mode_char> :<reason> Reply to MODE when a user cannot change a user mode
  1326. 974 ERR_CANNOTCHANGECHANMODE KineIRCd <mode_char> :<reason> Reply to MODE when a user cannot change a channel mode
  1327. 975 ERR_CANNOTCHANGESERVERMODE KineIRCd <mode_char> :<reason> Reply to MODE when a user cannot change a server mode
  1328. 976 ERR_CANNOTSENDTONICK KineIRCd <nick> :<reason> Returned from NOTICE, PRIVMSG or other commands to notify the user that they cannot send a message to a particular client. Similar to ERR_CANNOTSENDTOCHAN. KineIRCd uses this in conjunction with user-mode +R to allow users to block people who are not identified to services (spam avoidance)
  1329. 977 ERR_UNKNOWNSERVERMODE KineIRCd <modechar> :<info> Returned by MODE to inform the client they used an unknown server mode character.
  1330. 979 ERR_SERVERMODELOCK KineIRCd <target> :<info> Returned by MODE to inform the client the server has been set mode +L by an administrator to stop server modes being changed
  1331. 980 ERR_BADCHARENCODING KineIRCd <command> <charset> :<info> Returned by any command which may have had the given data modified because one or more glyphs were incorrectly encoded in the current charset (given). Such a use would be where an invalid UTF-8 sequence was given which may be considered insecure, or defines a character which is invalid within that context. For safety reasons, the invalid character is not returned to the client.
  1332. 981 ERR_TOOMANYLANGUAGES KineIRCd <max_langs> :<info> Returned by the LANGUAGE command to tell the client they cannot set as many languages as they have requested. To assist the client, the maximum languages which can be set at one time is given, and the language settings are not changed.
  1333. 982 ERR_NOLANGUAGE KineIRCd <language_code> :<info> Returned by the LANGUAGE command to tell the client it has specified an unknown language code.
  1334. 983 ERR_TEXTTOOSHORT KineIRCd <command> :<info> Returned by any command requiring text (such as a message or a reason), which was not long enough to be considered valid. This was created initially to combat '/wallops foo' abuse, but is also used by DIE and RESTART commands to attempt to encourage meaningful reasons.
  1335. 999 ERR_NUMERIC_ERR Bahamut
  1336. }
  1337. FCommandHandlers.OnBeforeCommandHandler := DoBeforeCmd;
  1338. end;
  1339. { Command handlers }
  1340. procedure TIdIRC.DoBeforeCmd(ASender: TIdCommandHandlers; var AData: string; AContext: TIdContext);
  1341. var
  1342. LTmp: String;
  1343. begin
  1344. AData := IRCUnquote(AData);
  1345. // ":nickname!user@host"
  1346. if TextStartsWith(AData, ':') then begin
  1347. LTmp := Fetch(AData, ' ');
  1348. Delete(LTmp, 1, 1); // remove ':'
  1349. FSenderNick := Fetch(LTmp, '!');
  1350. FSenderHost := LTmp;
  1351. end else begin
  1352. FSenderNick := '';
  1353. FSenderHost := '';
  1354. end;
  1355. if Assigned(FOnRaw) then begin
  1356. FOnRaw(AContext, True, AData);
  1357. end;
  1358. end;
  1359. procedure TIdIRC.DoReplyUnknownCommand(AContext: TIdContext; ALine: string);
  1360. var
  1361. ACmdCode: Integer;
  1362. begin
  1363. ACmdCode := IndyStrToInt(Fetch(ALine, ' '), -1);
  1364. //
  1365. case ACmdCode of
  1366. 6,
  1367. 7:
  1368. begin
  1369. //MAP
  1370. end;
  1371. 5,
  1372. 400..424,
  1373. 437..502:
  1374. begin
  1375. if Assigned(FOnServerError) then begin
  1376. OnServerError(AContext, ACmdCode, ALine);
  1377. end;
  1378. end;
  1379. 431..432,
  1380. 436:
  1381. begin
  1382. if Assigned(FOnNickError) then begin
  1383. OnNicknameError(AContext, ACmdCode);
  1384. end;
  1385. end;
  1386. end;
  1387. end;
  1388. procedure TIdIRC.CommandPRIVMSG(ASender: TIdCommand);
  1389. var
  1390. LTmp, LTarget, LData, LCTCP: String;
  1391. I: Integer;
  1392. CTCPList: TStringList;
  1393. begin
  1394. LTmp := ASender.UnparsedParams;
  1395. LTarget := FetchIRCParam(LTmp);
  1396. LData := FetchIRCParam(LTmp);
  1397. CTCPList := TStringList.Create;
  1398. try
  1399. ExtractCTCPs(LData, CTCPList);
  1400. if CTCPList.Count = 0 then begin
  1401. if Assigned(FOnPrivMessage) then begin
  1402. OnPrivateMessage(ASender.Context, FSenderNick, FSenderHost, LTarget, LData);
  1403. end;
  1404. end else
  1405. begin
  1406. if (LData <> '') and Assigned(FOnPrivMessage) then begin
  1407. OnPrivateMessage(ASender.Context, FSenderNick, FSenderHost, LTarget, LData);
  1408. end;
  1409. for I := 0 to CTCPList.Count - 1 do begin
  1410. LData := CTCPList[I];
  1411. LCTCP := Fetch(LData, ' ');
  1412. case PosInStrArray(LCTCP, IdIRCCTCP) of
  1413. 0: { ACTION }
  1414. begin
  1415. {
  1416. if Assigned(FOnAction) then begin
  1417. FOnAction(ASender.Context, FSenderNick, FSenderHost, LTarget, LData);
  1418. end;
  1419. }
  1420. if Assigned(FOnCTCPQry) then begin
  1421. FOnCTCPQry(ASender.Context, FSenderNick, FSenderHost, LTarget, LCTCP, LData);
  1422. end;
  1423. // RLebeau: CTCP ACTION does not send a reply back
  1424. //CTCPReply(FSenderNick, 'ERRMSG', LCTCP +' ' + LData + ' unknown query'); {do not localize}
  1425. end;
  1426. 1: { SOUND }
  1427. begin
  1428. {
  1429. if Assigned(FOnSound) then begin
  1430. FOnSound(ASender.Context, FSenderNick, FSenderHost, LTarget, LData);
  1431. end;
  1432. }
  1433. if Assigned(FOnCTCPQry) then begin
  1434. FOnCTCPQry(ASender.Context, FSenderNick, FSenderHost, LTarget, LCTCP, LData);
  1435. end;
  1436. CTCPReply(FSenderNick, 'ERRMSG', LCTCP +' ' + LData + ' unknown query'); {do not localize}
  1437. end;
  1438. 2: { PING }
  1439. begin
  1440. {
  1441. LTmp := '';
  1442. if Assigned(FOnPing) then begin
  1443. FOnPing(ASender.Context, LTmp);
  1444. end;
  1445. if LTmp = '' then begin
  1446. LTmp := DateTimeToStr(Now);
  1447. end;
  1448. CTCPReply(FSenderNick, LCTCP, ':' + LTmp);
  1449. }
  1450. if Assigned(FOnCTCPQry) then begin
  1451. FOnCTCPQry(ASender.Context, FSenderNick, FSenderHost, LTarget, LCTCP, LData);
  1452. end;
  1453. // AWinkelsdorf 3/10/2010 ToDo: CTCP Ping might need a CTIME result but
  1454. // many clients do not send the required CTIME with the Ping Query...
  1455. if LData = '' then begin
  1456. LData := DateTimeToStr(Now);
  1457. end;
  1458. CTCPReply(FSenderNick, LCTCP, LData); {do not localize}
  1459. end;
  1460. 3: { FINGER }
  1461. begin
  1462. CTCPReply(FSenderNick, LCTCP, Replies.Finger); {do not localize}
  1463. end;
  1464. 4: { USERINFO }
  1465. begin
  1466. CTCPReply(FSenderNick, LCTCP, Replies.UserInfo); {do not localize}
  1467. end;
  1468. 5: { VERSION }
  1469. begin
  1470. CTCPReply(FSenderNick, LCTCP, Replies.Version); {do not localize}
  1471. end;
  1472. 6: { CLIENTINFO }
  1473. begin
  1474. // TODO: add OnClientInfoQuery event to handle per-command queries
  1475. CTCPReply(FSenderNick, LCTCP, Replies.ClientInfo); {do not localize}
  1476. end;
  1477. 7: { TIME }
  1478. begin
  1479. CTCPReply(FSenderNick, LCTCP, DateTimeToStr(Now));
  1480. end;
  1481. 8: { ERROR }
  1482. begin
  1483. CTCPReply(FSenderNick, LCTCP, LData + ' No Error'); {do not localize}
  1484. end;
  1485. 9: { DCC }
  1486. begin
  1487. ParseDCC(ASender.Context, LData);
  1488. end;
  1489. 10: { SED }
  1490. begin
  1491. //ParseSED(AContext, LData);
  1492. if Assigned(FOnCTCPQry) then begin
  1493. FOnCTCPQry(ASender.Context, FSenderNick, FSenderHost, LTarget, LCTCP, LData);
  1494. end;
  1495. CTCPReply(FSenderNick, LCTCP, LData + ' unknown query'); {do not localize}
  1496. end;
  1497. 11: { ERRMSG }
  1498. begin
  1499. CTCPReply(FSenderNick, LCTCP, LData + ' No Error'); {do not localize}
  1500. end;
  1501. else
  1502. begin
  1503. if Assigned(FOnCTCPQry) then begin
  1504. FOnCTCPQry(ASender.Context, FSenderNick, FSenderHost, LTarget, LCTCP, LData);
  1505. end;
  1506. CTCPReply(FSenderNick, LCTCP, LData + ' unknown query'); {do not localize}
  1507. end;
  1508. end;
  1509. end;
  1510. end;
  1511. finally
  1512. CTCPList.Free;
  1513. end;
  1514. end;
  1515. procedure TIdIRC.CommandNOTICE(ASender: TIdCommand);
  1516. var
  1517. LTmp, LTarget, LData, LCTCP: String;
  1518. I: Integer;
  1519. CTCPList: TStringList;
  1520. begin
  1521. LTmp := ASender.UnparsedParams;
  1522. LTarget := FetchIRCParam(LTmp);
  1523. LData := FetchIRCParam(LTmp);
  1524. CTCPList := TStringList.Create;
  1525. try
  1526. ExtractCTCPs(LData, CTCPList);
  1527. if CTCPList.Count = 0 then begin
  1528. if Assigned(FOnNotice) then begin
  1529. OnNotice(ASender.Context, FSenderNick, FSenderHost, LTarget, LData);
  1530. end;
  1531. end else
  1532. begin
  1533. if (LData <> '') and Assigned(FOnNotice) then begin
  1534. OnNotice(ASender.Context, FSenderNick, FSenderHost, LTarget, LData);
  1535. end;
  1536. for I := 0 to CTCPList.Count - 1 do begin
  1537. LData := CTCPList[I];
  1538. LCTCP := Fetch(LData, ' ');
  1539. case PosInStrArray(LCTCP, IdIRCCTCP) of
  1540. 0: { ACTION }
  1541. begin
  1542. {
  1543. if Assigned(FOnAction) then begin
  1544. FOnAction(ASender.Context, FSenderNick, FSenderHost, LTarget, LData);
  1545. end;
  1546. }
  1547. if Assigned(FOnCTCPRep) then begin
  1548. FOnCTCPRep(ASender.Context, FSenderNick, FSenderHost, LTarget, LCTCP, LData);
  1549. end;
  1550. end;
  1551. 9: { DCC }
  1552. begin
  1553. ParseDCC(ASender.Context, LData);
  1554. end;
  1555. 10: { SED }
  1556. begin
  1557. //ParseSED(AContext, LData);
  1558. if Assigned(FOnCTCPRep) then begin
  1559. FOnCTCPRep(ASender.Context, FSenderNick, FSenderHost, LTarget, LCTCP, LData);
  1560. end;
  1561. end;
  1562. else
  1563. if Assigned(FOnCTCPRep) then begin
  1564. FOnCTCPRep(ASender.Context, FSenderNick, FSenderHost, LTarget, LCTCP, LData);
  1565. end;
  1566. end;
  1567. end;
  1568. end;
  1569. finally
  1570. CTCPList.Free;
  1571. end;
  1572. end;
  1573. procedure TIdIRC.CommandJOIN(ASender: TIdCommand);
  1574. begin
  1575. if Assigned(FOnJoin) then begin
  1576. OnJoin(ASender.Context, FSenderNick, FSenderHost, ASender.Params[0]);
  1577. end;
  1578. end;
  1579. procedure TIdIRC.CommandPART(ASender: TIdCommand);
  1580. var
  1581. LChannel, LMsg: string;
  1582. begin
  1583. if Assigned(FOnPart) then begin
  1584. if ASender.Params.Count > 0 then begin
  1585. LChannel := ASender.Params[0];
  1586. end;
  1587. if ASender.Params.Count > 1 then begin
  1588. LMsg := ASender.Params[1];
  1589. end;
  1590. OnPart(ASender.Context, FSenderNick, FSenderHost, LChannel, LMsg);
  1591. end;
  1592. end;
  1593. procedure TIdIRC.CommandKICK(ASender: TIdCommand);
  1594. var
  1595. LChannel, LTarget, LReason: string;
  1596. begin
  1597. if Assigned(FOnKick) then begin
  1598. if ASender.Params.Count > 0 then begin
  1599. LChannel := ASender.Params[0];
  1600. end;
  1601. if ASender.Params.Count > 1 then begin
  1602. LTarget := ASender.Params[1];
  1603. end;
  1604. if ASender.Params.Count > 2 then begin
  1605. LReason := ASender.Params[2];
  1606. end;
  1607. OnKick(ASender.Context, FSenderNick, FSenderHost, LChannel, LTarget, LReason);
  1608. end;
  1609. end;
  1610. procedure TIdIRC.CommandMODE(ASender: TIdCommand);
  1611. var
  1612. LTmp, LParam: String;
  1613. begin
  1614. LTmp := ASender.UnparsedParams;
  1615. LParam := FetchIRCParam(LTmp);
  1616. if IsChannel(LParam) then begin
  1617. if Assigned(FOnChanMode) then begin
  1618. OnChannelMode(ASender.Context, FSenderNick, FSenderHost, LParam, LTmp, '');
  1619. end;
  1620. end
  1621. else if Assigned(FOnUserMode) then begin
  1622. OnUserMode(ASender.Context, FSenderNick, FSenderHost, LTmp);
  1623. end;
  1624. end;
  1625. procedure TIdIRC.CommandNICK(ASender: TIdCommand);
  1626. begin
  1627. if Assigned(FOnNickChange) then begin
  1628. OnNicknameChange(ASender.Context, FSenderNick, FSenderHost, ASender.Params[0]);
  1629. end;
  1630. end;
  1631. procedure TIdIRC.CommandQUIT(ASender: TIdCommand);
  1632. var
  1633. LReason: string;
  1634. begin
  1635. if Assigned(FOnQuit) then begin
  1636. if ASender.Params.Count > 0 then begin
  1637. LReason := ASender.Params[0];
  1638. end;
  1639. OnQuit(ASender.Context, FSenderNick, FSenderHost, LReason);
  1640. end;
  1641. end;
  1642. procedure TIdIRC.CommandSQUIT(ASender: TIdCommand);
  1643. var
  1644. LServer, LComment: string;
  1645. begin
  1646. if Assigned(FOnSvrQuit) then begin
  1647. if ASender.Params.Count > 0 then begin
  1648. LServer := ASender.Params[0];
  1649. end;
  1650. if ASender.Params.Count > 1 then begin
  1651. LComment := ASender.Params[1];
  1652. end;
  1653. OnServerQuit(ASender.Context, FSenderNick, FSenderHost, LServer, LComment);
  1654. end;
  1655. end;
  1656. procedure TIdIRC.CommandINVITE(ASender: TIdCommand);
  1657. begin
  1658. if Assigned(FOnInvite) then begin
  1659. OnInvite(ASender.Context, FSenderNick, FSenderHost, ASender.Params[0], ASender.Params[1]);
  1660. end;
  1661. end;
  1662. procedure TIdIRC.CommandKILL(ASender: TIdCommand);
  1663. var
  1664. LTarget, LReason: string;
  1665. begin
  1666. if Assigned(FOnKill) then begin
  1667. if ASender.Params.Count > 0 then begin
  1668. LTarget := ASender.Params[0];
  1669. end;
  1670. if ASender.Params.Count > 1 then begin
  1671. LReason := ASender.Params[1];
  1672. end;
  1673. OnKill(ASender.Context, FSenderNick, FSenderHost, LTarget, LReason);
  1674. end;
  1675. end;
  1676. procedure TIdIRC.CommandPING(ASender: TIdCommand);
  1677. var
  1678. LServer1: String;
  1679. begin
  1680. if ASender.Params.Count > 0 then begin
  1681. LServer1 := ASender.Params[0];
  1682. end;
  1683. Pong(LServer1);
  1684. if Assigned(FOnPingPong) then begin
  1685. OnPingPong(ASender.Context);
  1686. end;
  1687. end;
  1688. procedure TIdIRC.CommandWALLOPS(ASender: TIdCommand);
  1689. var
  1690. LTmp: string;
  1691. begin
  1692. if Assigned(FOnWallops) then begin
  1693. LTmp := ASender.UnparsedParams;
  1694. OnWallops(ASender.Context, FSenderNick, FSenderHost, FetchIRCParam(LTmp));
  1695. end;
  1696. end;
  1697. procedure TIdIRC.CommandTOPIC(ASender: TIdCommand);
  1698. var
  1699. LChannel, LTopic: String;
  1700. begin
  1701. if Assigned(FOnTopic) then
  1702. begin
  1703. if ASender.Params.Count > 0 then begin
  1704. LChannel := ASender.Params[0];
  1705. end;
  1706. if (ASender.CommandHandler.Command <> '331') and (ASender.Params.Count > 1) then begin {do not localize}
  1707. LTopic := ASender.Params[1];
  1708. end else begin
  1709. LTopic := '';
  1710. end;
  1711. OnTopic(ASender.Context, FSenderNick, FSenderHost, LChannel, LTopic);
  1712. end;
  1713. end;
  1714. procedure TIdIRC.CommandWELCOME(ASender: TIdCommand);
  1715. var
  1716. LTmp: string;
  1717. begin
  1718. if Assigned(FOnSWelcome) then begin
  1719. LTmp := ASender.UnparsedParams;
  1720. OnServerWelcome(ASender.Context, FetchIRCParam(LTmp));
  1721. end;
  1722. end;
  1723. procedure TIdIRC.CommandERROR(ASender: TIdCommand);
  1724. var
  1725. LTmp: String;
  1726. begin
  1727. if Assigned(FOnServerError) then begin
  1728. LTmp := ASender.UnparsedParams;
  1729. OnServerError(ASender.Context, 0, FetchIRCParam(LTmp));
  1730. end;
  1731. end;
  1732. procedure TIdIRC.CommandYOURHOST(ASender: TIdCommand);
  1733. var
  1734. LTmp: String;
  1735. begin
  1736. if Assigned(FOnYourHost) then begin
  1737. LTmp := ASender.UnparsedParams;
  1738. OnYourHost(ASender.Context, FetchIRCParam(LTmp));
  1739. end;
  1740. end;
  1741. procedure TIdIRC.CommandCREATED(ASender: TIdCommand);
  1742. var
  1743. LTmp: string;
  1744. begin
  1745. if Assigned(FOnSCreated) then begin
  1746. LTmp := ASender.UnparsedParams;
  1747. OnServerCreated(ASender.Context, FetchIRCParam(LTmp));
  1748. end;
  1749. end;
  1750. procedure TIdIRC.CommandMYINFO(ASender: TIdCommand);
  1751. var
  1752. LTmp, LServer, LVersion, LUserModes, LChanModes: String;
  1753. begin
  1754. if Assigned(FOnMyInfo) then begin
  1755. LTmp := ASender.UnparsedParams;
  1756. LServer := FetchIRCParam(LTmp);
  1757. LVersion := FetchIRCParam(LTmp);
  1758. LUserModes := FetchIRCParam(LTmp);
  1759. LChanModes := FetchIRCParam(LTmp);
  1760. // TODO: <channel_modes_with_params> <user_modes_with_params> <server_modes> <server_modes_with_params>
  1761. OnMyInfo(ASender.Context, LServer, LVersion, LUserModes, LChanModes, LTmp);
  1762. end;
  1763. end;
  1764. procedure TIdIRC.DoBounce(ASender: TIdCommand; ALegacy: Boolean);
  1765. var
  1766. LHost, LPort, LInfo: string;
  1767. begin
  1768. if Assigned(FOnBounce) then begin
  1769. if ALegacy then begin
  1770. LInfo := ASender.Params[0];
  1771. LHost := FetchIRCParam(LInfo);
  1772. LPort := FetchIRCParam(LInfo);
  1773. end else
  1774. begin
  1775. LHost := ASender.Params[0];
  1776. LPort := ASender.Params[1];
  1777. if ASender.Params.Count > 2 then begin
  1778. LInfo := ASender.Params[2];
  1779. end;
  1780. end;
  1781. // TODO: reconnect automatically
  1782. OnBounce(ASender.Context, LHost, IndyStrToInt(LPort, 0), LInfo);
  1783. end;
  1784. end;
  1785. procedure TIdIRC.CommandISUPPORT(ASender: TIdCommand);
  1786. var
  1787. LParams: TStringList;
  1788. I: Integer;
  1789. begin
  1790. if ASender.Params.Count = 1 then begin
  1791. DoBounce(ASender, True); // legacy, deprecated
  1792. Exit;
  1793. end;
  1794. if Assigned(FOnISupport) then
  1795. begin
  1796. LParams := TStringList.Create;
  1797. try
  1798. for I := 1 to ASender.Params.Count-1 do // skip nickname
  1799. begin
  1800. LParams.Add(ASender.Params[I]);
  1801. end;
  1802. OnISupport(ASender.Context, LParams);
  1803. finally
  1804. LParams.Free;
  1805. end;
  1806. end;
  1807. end;
  1808. procedure TIdIRC.CommandBOUNCE(ASender: TIdCommand);
  1809. begin
  1810. DoBounce(ASender, False);
  1811. end;
  1812. procedure TIdIRC.CommandAWAY(ASender: TIdCommand);
  1813. var
  1814. LCmd: Integer;
  1815. begin
  1816. LCmd := IndyStrToInt(ASender.CommandHandler.Command, 0);
  1817. case LCmd of
  1818. 301:
  1819. begin
  1820. if Assigned(FOnAway) then begin
  1821. OnAway(ASender.Context, FSenderNick, FSenderHost, ASender.Params[0], True);
  1822. end;
  1823. end;
  1824. 305, 306:
  1825. begin
  1826. FUserAway := (LCmd = 306);
  1827. if Assigned(FOnAway) then begin
  1828. OnAway(ASender.Context, GetUsedNickname, '', ASender.Params[0], FUserAway);
  1829. end;
  1830. end;
  1831. end;
  1832. end;
  1833. procedure TIdIRC.CommandUSERHOST(ASender: TIdCommand);
  1834. begin
  1835. if Assigned(FOnUserInfo) then begin
  1836. OnUserInfoReceived(ASender.Context, ASender.UnparsedParams);
  1837. end;
  1838. end;
  1839. procedure TIdIRC.CommandISON(ASender: TIdCommand);
  1840. begin
  1841. if Assigned(FOnIsOnIRC) then begin
  1842. OnIsOnIRC(ASender.Context, FSenderNick, FSenderHost);
  1843. end;
  1844. end;
  1845. procedure TIdIRC.CommandWHOIS(ASender: TIdCommand);
  1846. begin
  1847. if not Assigned(FWhoIs) then begin
  1848. FWhoIs := TStringList.Create;
  1849. end;
  1850. FWhoIs.Add(ASender.Params[0]);
  1851. end;
  1852. procedure TIdIRC.CommandENDOFWHOIS(ASender: TIdCommand);
  1853. begin
  1854. CommandWHOIS(ASender);
  1855. if Assigned(FOnWhoIs) then begin
  1856. OnWhoIs(ASender.Context, FWhoIs);
  1857. end;
  1858. FWhoIs.Clear;
  1859. end;
  1860. procedure TIdIRC.CommandWHOWAS(ASender: TIdCommand);
  1861. begin
  1862. if not Assigned(FWhoWas) then begin
  1863. FWhoWas := TStringList.Create;
  1864. end;
  1865. FWhoWas.Add(ASender.Params[0]);
  1866. end;
  1867. procedure TIdIRC.CommandENDOFWHOWAS(ASender: TIdCommand);
  1868. begin
  1869. CommandWHOWAS(ASender);
  1870. if Assigned(FOnWhoWas) then begin
  1871. OnWhoWas(ASender.Context, FWhoWas);
  1872. end;
  1873. FWhoWas.Clear;
  1874. end;
  1875. procedure TIdIRC.CommandLISTSTART(ASender: TIdCommand);
  1876. begin
  1877. if not Assigned(FSvrList) then begin
  1878. FSvrList := TStringList.Create;
  1879. end else begin
  1880. FSvrList.Clear;
  1881. end;
  1882. end;
  1883. procedure TIdIRC.CommandLIST(ASender: TIdCommand);
  1884. begin
  1885. if not Assigned(FSvrList) then begin
  1886. FSvrList := TStringList.Create;
  1887. end;
  1888. FSvrList.Add(ASender.Params[0] + ' ' + ASender.Params[1] + ' ' + ASender.Params[2]); {do not localize}
  1889. end;
  1890. procedure TIdIRC.CommandLISTEND(ASender: TIdCommand);
  1891. begin
  1892. if not Assigned(FSvrList) then begin
  1893. FSvrList := TStringList.Create;
  1894. end;
  1895. if Assigned(FOnSvrList) then begin
  1896. OnServerListReceived(ASender.Context, FSvrList);
  1897. end;
  1898. FSvrList.Clear;
  1899. end;
  1900. procedure TIdIRC.CommandINVITING(ASender: TIdCommand);
  1901. begin
  1902. if Assigned(FOnInviting) then begin
  1903. OnInviting(ASender.Context, FSenderNick, FSenderHost);
  1904. end;
  1905. end;
  1906. procedure TIdIRC.CommandSUMMONING(ASender: TIdCommand);
  1907. begin
  1908. if Assigned(FOnSummon) then begin
  1909. OnSummon(ASender.Context, FSenderNick, FSenderHost);
  1910. end;
  1911. end;
  1912. procedure TIdIRC.CommandINVITELIST(ASender: TIdCommand);
  1913. begin
  1914. if not Assigned(FInvites) then begin
  1915. FInvites := TStringList.Create;
  1916. end;
  1917. // TODO: use a collection instead
  1918. FInvites.Add(ASender.Params[0] + ' ' + ASender.Params[1]); {do not localize}
  1919. end;
  1920. procedure TIdIRC.CommandENDOFINVITELIST(ASender: TIdCommand);
  1921. begin
  1922. if not Assigned(FInvites) then begin
  1923. FInvites := TStringList.Create;
  1924. end;
  1925. FInvites.Add(ASender.Params[0]);
  1926. if Assigned(FOnINVList) then begin
  1927. OnInvitationListReceived(ASender.Context, FSenderNick, FInvites);
  1928. end;
  1929. FInvites.Clear;
  1930. end;
  1931. procedure TIdIRC.CommandEXCEPTLIST(ASender: TIdCommand);
  1932. begin
  1933. if not Assigned(FExcepts) then begin
  1934. FExcepts := TStringList.Create;
  1935. end;
  1936. // TODO: use a collection instead
  1937. FExcepts.Add(ASender.Params[0] + ' ' + ASender.Params[1]); {do not localize}
  1938. end;
  1939. procedure TIdIRC.CommandENDOFEXCEPTLIST(ASender: TIdCommand);
  1940. begin
  1941. if not Assigned(FExcepts) then begin
  1942. FExcepts := TStringList.Create;
  1943. end;
  1944. FExcepts.Add(ASender.Params[0]);
  1945. if Assigned(FOnEXCList) then begin
  1946. OnExceptionListReceived(ASender.Context, FSenderNick, FExcepts);
  1947. end;
  1948. FExcepts.Clear;
  1949. end;
  1950. procedure TIdIRC.CommandWHOREPLY(ASender: TIdCommand);
  1951. begin
  1952. if not Assigned(FWho) then begin
  1953. FWho := TStringList.Create;
  1954. end;
  1955. FWho.Add(''); // TODO
  1956. end;
  1957. procedure TIdIRC.CommandENDOFWHO(ASender: TIdCommand);
  1958. begin
  1959. if not Assigned(FWho) then begin
  1960. FWho := TStringList.Create;
  1961. end;
  1962. FWho.Add(ASender.Params[0]);
  1963. if Assigned(FOnWho) then begin
  1964. OnWho(ASender.Context, FWho);
  1965. end;
  1966. FWho.Clear;
  1967. end;
  1968. procedure TIdIRC.CommandNAMEREPLY(ASender: TIdCommand);
  1969. var
  1970. LNames: string;
  1971. begin
  1972. if not Assigned(FNames) then begin
  1973. FNames := TStringList.Create;
  1974. end;
  1975. // AWinkelsdorf 3/10/2010 Rewrote logic to split Names into single Lines of FNames
  1976. // RLebeau 1/27/2016: Rewrote to use a Fetch() loop instead of a temp TStringList
  1977. if ASender.Params.Count >= 4 then begin // Names are in [3]
  1978. LNames := ASender.Params[3];
  1979. while LNames <> '' do begin
  1980. FNames.Add(Fetch(LNames));
  1981. end;
  1982. end else begin
  1983. FNames.Add(ASender.Params[0]);
  1984. end;
  1985. end;
  1986. procedure TIdIRC.CommandENDOFNAMES(ASender: TIdCommand);
  1987. var
  1988. LChannel: string;
  1989. begin
  1990. if not Assigned(FNames) then begin
  1991. FNames := TStringList.Create;
  1992. end;
  1993. LChannel := '';
  1994. if ASender.Params.Count > 0 then begin
  1995. LChannel := ASender.Params[1];
  1996. end;
  1997. if Assigned(FOnNickList) then begin
  1998. OnNicknamesListReceived(ASender.Context, LChannel, FNames);
  1999. end;
  2000. FNames.Clear;
  2001. end;
  2002. procedure TIdIRC.CommandLINKS(ASender: TIdCommand);
  2003. var
  2004. LHopCnt, LInfo: String;
  2005. begin
  2006. if not Assigned(FLinks) then begin
  2007. FLinks := TStringList.Create;
  2008. end;
  2009. LInfo := ASender.Params[2];
  2010. LHopCnt := Fetch(LInfo);
  2011. // TODO: use a collection instead
  2012. FLinks.Add(ASender.Params[0] + ' ' + ASender.Params[1] + ' ' + LHopCnt + ' ' + LInfo); {do not localize}
  2013. end;
  2014. procedure TIdIRC.CommandENDOFLINKS(ASender: TIdCommand);
  2015. begin
  2016. if not Assigned(FLinks) then begin
  2017. FLinks := TStringList.Create;
  2018. end;
  2019. FLinks.Add(ASender.Params[0]);
  2020. if Assigned(FOnKnownSvrs) then begin
  2021. OnKnownServersListReceived(ASender.Context, FLinks);
  2022. end;
  2023. FLinks.Clear;
  2024. end;
  2025. procedure TIdIRC.CommandBANLIST(ASender: TIdCommand);
  2026. begin
  2027. if not Assigned(FBans) then begin
  2028. FBans := TStringList.Create;
  2029. end;
  2030. // TODO: use a collection instead
  2031. FBans.Add(ASender.Params[0] + ' ' + ASender.Params[1]); {do not localize}
  2032. end;
  2033. procedure TIdIRC.CommandENDOFBANLIST(ASender: TIdCommand);
  2034. begin
  2035. if not Assigned(FBans) then begin
  2036. FBans := TStringList.Create;
  2037. end;
  2038. FBans.Add(ASender.Params[0]);
  2039. if Assigned(FOnBanList) then begin
  2040. OnBanListReceived(ASender.Context, FSenderNick, FBans);
  2041. end;
  2042. FBans.Clear;
  2043. end;
  2044. procedure TIdIRC.CommandINFO(ASender: TIdCommand);
  2045. begin
  2046. // TODO
  2047. {
  2048. if not Assigned(FInfo) then begin
  2049. FInfo := TStringList.Create;
  2050. end;
  2051. FInfo.Add(ASender.Params[0]);
  2052. }
  2053. end;
  2054. procedure TIdIRC.CommandENDOFINFO(ASender: TIdCommand);
  2055. begin
  2056. // TODO
  2057. {
  2058. if not Assigned(FInfo) then begin
  2059. FInfo := TStringList.Create;
  2060. end;
  2061. }
  2062. if Assigned(FOnUserInfo) then begin
  2063. OnUserInfoReceived(ASender.Context, ASender.UnparsedParams);
  2064. //OnUserInfoReceived(ASender.Context, FInfo);
  2065. end;
  2066. //FInfo.Clear;
  2067. end;
  2068. procedure TIdIRC.CommandMOTD(ASender: TIdCommand);
  2069. begin
  2070. if not Assigned(FMotd) then begin
  2071. FMotd := TStringList.Create;
  2072. end;
  2073. FMotd.Add(ASender.Params[0]);
  2074. end;
  2075. procedure TIdIRC.CommandENDOFMOTD(ASender: TIdCommand);
  2076. begin
  2077. if not Assigned(FMotd) then begin
  2078. FMotd := TStringList.Create;
  2079. end;
  2080. if Assigned(FOnMOTD) then begin
  2081. OnMOTD(ASender.Context, FMotd);
  2082. end;
  2083. FMotd.Clear;
  2084. end;
  2085. procedure TIdIRC.CommandREHASHING(ASender: TIdCommand);
  2086. begin
  2087. if Assigned(FOnRehash) then begin
  2088. OnRehash(ASender.Context, FSenderNick, FSenderHost);
  2089. end;
  2090. end;
  2091. procedure TIdIRC.CommandUSERSSTART(ASender: TIdCommand);
  2092. begin
  2093. if not Assigned(FUsers) then begin
  2094. FUsers := TStringList.Create;
  2095. end else begin
  2096. FUsers.Clear;
  2097. end;
  2098. end;
  2099. procedure TIdIRC.CommandUSERS(ASender: TIdCommand);
  2100. begin
  2101. if ASender.CommandHandler.Command = '393' then {do not localize}
  2102. begin
  2103. if not Assigned(FUsers) then begin
  2104. FUsers := TStringList.Create;
  2105. end;
  2106. // TODO: use a collection instead
  2107. FUsers.Add(ASender.Params[0] + ' ' + ASender.Params[1] + ' ' + ASender.Params[2]); {do not localize}
  2108. end;
  2109. end;
  2110. procedure TIdIRC.CommandENDOFUSERS(ASender: TIdCommand);
  2111. begin
  2112. if not Assigned(FUsers) then begin
  2113. FUsers := TStringList.Create;
  2114. end;
  2115. if Assigned(FOnSvrUsers) then begin
  2116. OnServerUsersListReceived(ASender.Context, FUsers);
  2117. end;
  2118. FUsers.Clear;
  2119. end;
  2120. procedure TIdIRC.CommandENDOFSTATS(ASender: TIdCommand);
  2121. begin
  2122. if Assigned(FOnSvrStats) then begin
  2123. OnServerStatsReceived(ASender.Context, nil); // TODO
  2124. end;
  2125. end;
  2126. procedure TIdIRC.CommandSERVLIST(ASender: TIdCommand);
  2127. begin
  2128. // <name> <server> <mask> <type> <hopcount> <info>
  2129. end;
  2130. procedure TIdIRC.CommandSERVLISTEND(ASender: TIdCommand);
  2131. begin
  2132. // <mask> <type> :<info>
  2133. end;
  2134. procedure TIdIRC.CommandTIME(ASender: TIdCommand);
  2135. var
  2136. LServer, LTimeString: String;
  2137. begin
  2138. if Assigned(FOnSvrTime) then begin
  2139. LServer := ASender.Params[0];
  2140. case ASender.Params.Count of
  2141. 2: begin // "<server> :<time string>"
  2142. LTimeString := ASender.Params[1];
  2143. end;
  2144. 4: begin // "<server> <timestamp> <offset> :<time string>" or "<server> <timezone name> <microseconds> :<time string>"
  2145. LTimeString := IndyFormat('%s %s %s', [ASender.Params[1], ASender.Params[2], ASender.Params[3]]); {do not localize}
  2146. end;
  2147. 7: begin // "<server> <year> <month> <day> <hour> <minute> <second>"
  2148. LTimeString := IndyFormat('%s %s %s %s %s %s', {do not localize}
  2149. [ASender.Params[1], ASender.Params[2], ASender.Params[3],
  2150. ASender.Params[4], ASender.Params[5], ASender.Params[6]]);
  2151. end;
  2152. end;
  2153. OnServerTime(ASender.Context, LServer, LTimeString);
  2154. end;
  2155. end;
  2156. procedure TIdIRC.CommandSERVICE(ASender: TIdCommand);
  2157. begin
  2158. if Assigned(FOnService) then begin
  2159. OnService(ASender.Context);
  2160. end;
  2161. end;
  2162. procedure TIdIRC.CommandVERSION(ASender: TIdCommand);
  2163. begin
  2164. if Assigned(FOnSvrVersion) then begin
  2165. OnServerVersion(ASender.Context, ASender.Params[0], ASender.Params[1], ASender.Params[2]);
  2166. end;
  2167. end;
  2168. procedure TIdIRC.CommandCHANMODE(ASender: TIdCommand);
  2169. begin
  2170. if Assigned(FOnChanMode) then begin
  2171. OnChannelMode(ASender.Context, FSenderNick, FSenderHost, ASender.Params[0], ASender.Params[1], ASender.Params[2]);
  2172. end;
  2173. end;
  2174. procedure TIdIRC.CommandOPER(ASender: TIdCommand);
  2175. begin
  2176. if Assigned(FOnOp) then begin
  2177. OnOp(ASender.Context, FSenderNick, FSenderHost, ASender.Params[0]);
  2178. end;
  2179. end;
  2180. procedure TIdIRC.CommandNICKINUSE(ASender: TIdCommand);
  2181. begin
  2182. if ASender.CommandHandler.Command = '433' then {do not localize}
  2183. begin
  2184. if (Connected) and (FAltNickname <> '') then
  2185. begin
  2186. if not FAltNickUsed then begin
  2187. // try only once using AltNickname (FAltNickUsed is cleared in .Connect)
  2188. SetNickname(FAltNickname);
  2189. FAltNickUsed := True;
  2190. end
  2191. else
  2192. begin
  2193. // already tried to use AltNickName...
  2194. if Assigned(FOnNickError) then begin
  2195. OnNicknameError(ASender.Context, IndyStrToInt(ASender.CommandHandler.Command));
  2196. end;
  2197. end;
  2198. end;
  2199. end;
  2200. end;
  2201. procedure TIdIRC.ParseDCC(AContext: TIdContext; const ADCC: String);
  2202. const
  2203. IdIRCDCC: array[0..3] of String = ('SEND', 'CHAT', 'RESUME', 'ACCEPT'); {do not localize}
  2204. var
  2205. LTmp, LType, LArg, LAddr, LPort, LSize: String;
  2206. begin
  2207. LTmp := ADCC;
  2208. LType := FetchIRCParam(LTmp);
  2209. LArg := FetchIRCParam(LTmp);
  2210. LAddr := FetchIRCParam(LTmp);
  2211. LPort := FetchIRCParam(LTmp);
  2212. LSize := FetchIRCParam(LTmp);
  2213. //
  2214. case PosInStrArray(LType, IdIRCDCC) of
  2215. 0: {SEND}
  2216. begin
  2217. if Assigned(FOnDCCSend) then begin
  2218. FOnDCCSend(AContext, FSenderNick, LAddr, ExtractFileName(LArg), IndyStrToInt(LPort), IndyStrToInt64(LSize));
  2219. end;
  2220. end;
  2221. 1: {CHAT}
  2222. begin
  2223. if Assigned(FOnDCCChat) then begin
  2224. FOnDCCChat(AContext, FSenderNick, LAddr, IndyStrToInt(LPort));
  2225. end;
  2226. end;
  2227. 2: {RESUME}
  2228. begin
  2229. if Assigned(FOnDCCResume) then begin
  2230. FOnDCCResume(AContext, FSenderNick, LAddr, LArg, IndyStrToInt(LPort), IndyStrToInt64(LSize));
  2231. end;
  2232. end;
  2233. 3: {ACCEPT}
  2234. begin
  2235. if Assigned(FOnDCCAccept) then begin
  2236. FOnDCCAccept(AContext, FSenderNick, LAddr, LArg, IndyStrToInt(LPort), IndyStrToInt64(LSize));
  2237. end;
  2238. end;
  2239. end;
  2240. end;
  2241. function TIdIRC.GetUsedNickname: String;
  2242. begin
  2243. if FAltNickUsed then
  2244. Result := FAltNickname
  2245. else
  2246. Result := FNickname;
  2247. end;
  2248. procedure TIdIRC.SetNickname(const AValue: String);
  2249. begin
  2250. if not Connected then begin
  2251. FNickname := AValue;
  2252. end else begin
  2253. Raw(IndyFormat('NICK %s', [AValue])); {do not localize}
  2254. end;
  2255. end;
  2256. procedure TIdIRC.SetUsername(const AValue: String);
  2257. begin
  2258. if not Connected then begin
  2259. FUsername := AValue;
  2260. end else begin
  2261. Raw(IndyFormat('USER %s %s %s :%s', [AValue, GetUserMode, '*', FRealName])); {do not localize}
  2262. end;
  2263. end;
  2264. procedure TIdIRC.SetIdIRCUserMode(AValue: TIdIRCUserModes);
  2265. begin
  2266. FUserMode := AValue;
  2267. end;
  2268. procedure TIdIRC.SetIdIRCReplies(AValue: TIdIRCReplies);
  2269. begin
  2270. FReplies.Assign(AValue);
  2271. end;
  2272. function TIdIRC.IsChannel(const AChannel: String): Boolean;
  2273. begin
  2274. //Result := (Length(AChannel) > 0) and CharIsInSet(AChannel, 1, ['&','#','+','!']); {do not localize}
  2275. Result := CharIsInSet(AChannel, 1, '&#+!'); {do not localize}
  2276. end;
  2277. function TIdIRC.IsOp(const ANickname: String): Boolean;
  2278. begin
  2279. Result := TextStartsWith(ANickname, '@');
  2280. end;
  2281. function TIdIRC.IsVoice(const ANickname: String): Boolean;
  2282. begin
  2283. Result := TextEndsWith(ANickname, '+');
  2284. end;
  2285. procedure TIdIRC.Say(const ATarget, AMsg: String);
  2286. begin
  2287. Raw(IndyFormat('PRIVMSG %s :%s', [ATarget, AMsg])); {do not localize}
  2288. end;
  2289. procedure TIdIRC.Notice(const ATarget, AMsg: String);
  2290. begin
  2291. Raw(IndyFormat('NOTICE %s :%s', [ATarget, AMsg])); {do not localize}
  2292. end;
  2293. procedure TIdIRC.Action(const ATarget, AMsg: String);
  2294. begin
  2295. CTCPQuery(ATarget, 'ACTION', AMsg); {do not localize}
  2296. end;
  2297. procedure TIdIRC.CTCPQuery(const ATarget, ACommand, AParameters: String);
  2298. var
  2299. LTmp: String;
  2300. begin
  2301. LTmp := UpperCase(ACommand);
  2302. if AParameters <> '' then begin
  2303. LTmp := LTmp + ' ' + AParameters;
  2304. end;
  2305. Say(ATarget, XDelim+CTCPQuote(LTmp)+XDelim); {do not localize}
  2306. end;
  2307. procedure TIdIRC.CTCPReply(const ATarget, ACTCP, AReply: String);
  2308. var
  2309. LTmp: String;
  2310. begin
  2311. LTmp := ACTCP;
  2312. if AReply <> '' then begin
  2313. LTmp := LTmp + ' ' + AReply;
  2314. end;
  2315. Notice(ATarget, XDelim+CTCPQuote(LTmp)+XDelim); {do not localize}
  2316. end;
  2317. procedure TIdIRC.Join(const AChannel: String; const AKey: String = '');
  2318. begin
  2319. if IsChannel(AChannel) then begin
  2320. if AKey <> '' then begin
  2321. Raw(IndyFormat('JOIN %s %s', [AChannel, AKey])) {do not localize}
  2322. end else begin
  2323. Raw(IndyFormat('JOIN %s', [AChannel])); {do not localize}
  2324. end;
  2325. end;
  2326. end;
  2327. procedure TIdIRC.Part(const AChannel: String; const AReason: String = '');
  2328. begin
  2329. if IsChannel(AChannel) then begin
  2330. if AReason <> '' then begin
  2331. Raw(IndyFormat('PART %s :%s', [AChannel, AReason])) {do not localize}
  2332. end else begin
  2333. Raw(IndyFormat('PART %s', [AChannel])); {do not localize}
  2334. end;
  2335. end;
  2336. end;
  2337. procedure TIdIRC.Kick(const AChannel, ANickname: String; const AReason: String = '');
  2338. begin
  2339. if IsChannel(AChannel) then begin
  2340. if AReason <> '' then begin
  2341. Raw(IndyFormat('KICK %s %s :%s', [AChannel, ANickname, AReason])); {do not localize}
  2342. end else begin
  2343. Raw(IndyFormat('KICK %s %s', [AChannel, ANickname])); {do not localize}
  2344. end;
  2345. end;
  2346. end;
  2347. procedure TIdIRC.SetChannelMode(const AChannel, AMode: String; const AParams: String = '');
  2348. begin
  2349. if IsChannel(AChannel) then begin
  2350. if AParams = '' then begin
  2351. Raw(IndyFormat('MODE %s %s', [AChannel, AMode])); {do not localize}
  2352. end else begin
  2353. Raw(IndyFormat('MODE %s %s %s', [AChannel, AMode, AParams])); {do not localize}
  2354. end;
  2355. end;
  2356. end;
  2357. procedure TIdIRC.SetUserMode(const ANickname, AMode: String);
  2358. begin
  2359. Raw(IndyFormat('MODE %s %s', [ANickname, AMode])); {do not localize}
  2360. end;
  2361. procedure TIdIRC.GetChannelTopic(const AChannel: String);
  2362. begin
  2363. if IsChannel(AChannel) then begin
  2364. Raw(IndyFormat('TOPIC %s', [AChannel])); {do not localize}
  2365. end;
  2366. end;
  2367. procedure TIdIRC.SetChannelTopic(const AChannel, ATopic: String);
  2368. begin
  2369. if IsChannel(AChannel) then begin
  2370. Raw(IndyFormat('TOPIC %s :%s', [AChannel, ATopic])); {do not localize}
  2371. end;
  2372. end;
  2373. procedure TIdIRC.SetAway(const AMsg: String);
  2374. begin
  2375. if AMsg <> '' then begin
  2376. Raw(IndyFormat('AWAY :%s', [AMsg])); {do not localize}
  2377. end else begin
  2378. Raw('AWAY'); {do not localize}
  2379. end;
  2380. end;
  2381. procedure TIdIRC.Op(const AChannel, ANickname: String);
  2382. begin
  2383. SetChannelMode(AChannel, '+o', ANickname); {do not localize}
  2384. end;
  2385. procedure TIdIRC.Deop(const AChannel, ANickname: String);
  2386. begin
  2387. SetChannelMode(AChannel, '-o', ANickname); {do not localize}
  2388. end;
  2389. procedure TIdIRC.Voice(const AChannel, ANickname: String);
  2390. begin
  2391. SetChannelMode(AChannel, '+v', ANickname); {do not localize}
  2392. end;
  2393. procedure TIdIRC.Devoice(const AChannel, ANickname: String);
  2394. begin
  2395. SetChannelMode(AChannel, '-v', ANickname); {do not localize}
  2396. end;
  2397. procedure TIdIRC.Ban(const AChannel, AHostmask: String);
  2398. begin
  2399. SetChannelMode(AChannel, '+b', AHostmask); {do not localize}
  2400. end;
  2401. procedure TIdIRC.Unban(const AChannel, AHostmask: String);
  2402. begin
  2403. SetChannelMode(AChannel, '-b', AHostmask); {do not localize}
  2404. end;
  2405. procedure TIdIRC.RegisterService(const ANickname, ADistribution, AInfo: String; AType: Integer);
  2406. begin
  2407. Raw(IndyFormat('SERVICE %s * %s %s 0 :%s', {do not localize}
  2408. [ANickname, ADistribution, AType, AInfo]));
  2409. end;
  2410. procedure TIdIRC.ListChannelNicknames(const AChannel: String; const ATarget: String = '');
  2411. begin
  2412. if IsChannel(AChannel) then begin
  2413. if ATarget <> '' then begin
  2414. Raw(IndyFormat('NAMES %s %s', [AChannel, ATarget])); {do not localize}
  2415. end else begin
  2416. Raw(IndyFormat('NAMES %s', [AChannel])); {do not localize}
  2417. end;
  2418. end;
  2419. end;
  2420. procedure TIdIRC.ListChannel(const AChannel: String; const ATarget: String = '');
  2421. begin
  2422. if IsChannel(AChannel) then begin
  2423. if ATarget <> '' then begin
  2424. Raw(IndyFormat('LIST %s %s', [AChannel, ATarget])); {do not localize}
  2425. end else begin
  2426. Raw(IndyFormat('LIST %s', [AChannel])); {do not localize}
  2427. end;
  2428. end;
  2429. end;
  2430. procedure TIdIRC.Invite(const ANickname, AChannel: String);
  2431. begin
  2432. if IsChannel(AChannel) then begin
  2433. Raw(IndyFormat('INVITE %s %s', [ANickname, AChannel])); {do not localize}
  2434. end;
  2435. end;
  2436. procedure TIdIRC.GetMessageOfTheDay(const ATarget: String = '');
  2437. begin
  2438. if ATarget <> '' then begin
  2439. Raw(IndyFormat('MOTD %s', [ATarget])); {do not localize}
  2440. end else begin
  2441. Raw('MOTD'); {do not localize}
  2442. end;
  2443. end;
  2444. procedure TIdIRC.GetNetworkStatus(const AHostMask: String = ''; const ATarget: String = '');
  2445. begin
  2446. if (AHostMask = '') and (ATarget = '') then begin
  2447. Raw('LUSERS'); {do not localize}
  2448. end
  2449. else if AHostMask = '' then begin
  2450. Raw(IndyFormat('LUSERS %s', [ATarget])); {do not localize}
  2451. end
  2452. else if ATarget = '' then begin
  2453. Raw(IndyFormat('LUSERS %s', [AHostMask])); {do not localize}
  2454. end else begin
  2455. Raw(IndyFormat('LUSERS %s %s', [AHostMask, ATarget])); {do not localize}
  2456. end;
  2457. end;
  2458. procedure TIdIRC.GetServerVersion(const ATarget: String = '');
  2459. begin
  2460. if ATarget = '' then begin
  2461. Raw('VERSION'); {do not localize}
  2462. end else begin
  2463. Raw(IndyFormat('VERSION %s', [ATarget])); {do not localize}
  2464. end;
  2465. end;
  2466. procedure TIdIRC.GetServerStatus(AQuery: TIdIRCStat; const ATarget: String = '');
  2467. const
  2468. IdIRCStatChars: array[TIdIRCStat] of Char = ('l', 'm', 'o', 'u'); {do not localize}
  2469. begin
  2470. if ATarget <> '' then begin
  2471. Raw(IndyFormat('STATS %s %s', [IdIRCStatChars[AQuery], ATarget])); {do not localize}
  2472. end else begin
  2473. Raw(IndyFormat('STATS %s', [IdIRCStatChars[AQuery]])); {do not localize}
  2474. end;
  2475. end;
  2476. procedure TIdIRC.ListKnownServerNames(const ARemoteHost: String = ''; const AHostMask: String = '');
  2477. begin
  2478. if (ARemoteHost = '') and (AHostMask = '') then begin
  2479. Raw('LINKS'); {do not localize}
  2480. end
  2481. else if ARemoteHost = '' then begin
  2482. Raw(IndyFormat('LINKS %s', [AHostMask])); {do not localize}
  2483. end else begin
  2484. Raw(IndyFormat('LINKS %s %s', [ARemoteHost, AHostMask])); {do not localize}
  2485. end;
  2486. end;
  2487. procedure TIdIRC.QueryServerTime(const ATarget: String = '');
  2488. begin
  2489. if ATarget <> '' then begin
  2490. Raw(IndyFormat('TIME %s', [ATarget])); {do not localize}
  2491. end else begin
  2492. Raw('TIME'); {do not localize}
  2493. end;
  2494. end;
  2495. procedure TIdIRC.RequestServerConnect(const ATargetHost: String; APort: Integer;
  2496. const ARemoteHost: String = '');
  2497. begin
  2498. if ARemoteHost <> '' then begin
  2499. Raw(IndyFormat('CONNECT %s %d %s', [ATargetHost, APort, ARemoteHost])); {do not localize}
  2500. end else begin
  2501. Raw(IndyFormat('CONNECT %s %d', [ATargetHost, APort])); {do not localize}
  2502. end;
  2503. end;
  2504. procedure TIdIRC.TraceServer(const ATarget: String = '');
  2505. begin
  2506. if ATarget <> '' then begin
  2507. Raw(IndyFormat('TRACE %s', [ATarget])); {do not localize}
  2508. end else begin
  2509. Raw('TRACE'); {do not localize}
  2510. end;
  2511. end;
  2512. procedure TIdIRC.GetAdminInfo(const ATarget: String = '');
  2513. begin
  2514. if ATarget <> '' then begin
  2515. Raw(IndyFormat('ADMIN %s', [ATarget])); {do not localize}
  2516. end else begin
  2517. Raw('ADMIN'); {do not localize}
  2518. end;
  2519. end;
  2520. procedure TIdIRC.GetServerInfo(const ATarget: String = '');
  2521. begin
  2522. if ATarget <> '' then begin
  2523. Raw(IndyFormat('INFO %s', [ATarget])); {do not localize}
  2524. end else begin
  2525. Raw('INFO'); {do not localize}
  2526. end;
  2527. end;
  2528. procedure TIdIRC.ListNetworkServices(const AHostMask: String = ''; const AType: String = '');
  2529. begin
  2530. if (AHostMask = '') and (AType = '') then begin
  2531. Raw('SERVLIST'); {do not localize}
  2532. end
  2533. else if AType <> '' then begin
  2534. Raw(IndyFormat('SERVLIST %s %s', [AHostMask, AType])); {do not localize}
  2535. end else begin
  2536. Raw(IndyFormat('SERVLIST %s', [AHostMask])); {do not localize}
  2537. end;
  2538. end;
  2539. procedure TIdIRC.QueryService(const AServiceName, AMessage: String);
  2540. begin
  2541. Raw(IndyFormat('SQUERY %s :%s', [AServiceName, AMessage])); {do not localize}
  2542. end;
  2543. procedure TIdIRC.Who(const AMask: String; AOnlyAdmins: Boolean);
  2544. begin
  2545. if (AMask = '') and (not AOnlyAdmins) then begin
  2546. Raw('WHO'); {do not localize}
  2547. end
  2548. else if AOnlyAdmins then begin
  2549. Raw(IndyFormat('WHO %s o', [AMask])); {do not localize}
  2550. end else begin
  2551. Raw(IndyFormat('WHO %s', [AMask])); {do not localize}
  2552. end;
  2553. end;
  2554. procedure TIdIRC.WhoIs(const AMask: String; const ATarget: String = '');
  2555. begin
  2556. if ATarget <> '' then begin
  2557. Raw(IndyFormat('WHOIS %s %s', [ATarget, AMask])); {do not localize}
  2558. end else begin
  2559. Raw(IndyFormat('WHOIS %s', [AMask])); {do not localize}
  2560. end;
  2561. end;
  2562. procedure TIdIRC.WhoWas(const ANickname: String; ACount: Integer = -1; const ATarget: String = '');
  2563. begin
  2564. if (ATarget = '') and (ACount < 0) then begin
  2565. Raw(IndyFormat('WHOWAS %s', [ANickname])); {do not localize}
  2566. end
  2567. else if ATarget <> '' then begin
  2568. Raw(IndyFormat('WHOWAS %s %d %s', [ANickname, ACount, ATarget])); {do not localize}
  2569. end
  2570. else begin
  2571. Raw(IndyFormat('WHOWAS %s %d', [ANickname, ACount])); {do not localize}
  2572. end;
  2573. end;
  2574. procedure TIdIRC.Kill(const ANickname, AComment: String);
  2575. begin
  2576. Raw(IndyFormat('KILL %s :%s', [ANickname, AComment])); {do not localize}
  2577. end;
  2578. procedure TIdIRC.Ping(const AServer1: String; const AServer2: String = '');
  2579. begin
  2580. if AServer2 <> '' then begin
  2581. Raw(IndyFormat('PING %s %s', [AServer1, AServer2])); {do not localize}
  2582. end else begin
  2583. Raw(IndyFormat('PING %s', [AServer1])); {do not localize}
  2584. end;
  2585. end;
  2586. procedure TIdIRC.Pong(const AServer1: String; const AServer2: String = '');
  2587. begin
  2588. if AServer2 <> '' then begin
  2589. Raw(IndyFormat('PONG %s %s', [AServer1, AServer2])); {do not localize}
  2590. end else begin
  2591. Raw(IndyFormat('PONG %s', [AServer1])); {do not localize}
  2592. end;
  2593. end;
  2594. procedure TIdIRC.Error(const AMessage: String);
  2595. begin
  2596. Raw(IndyFormat('ERROR :%s', [AMessage])); {do not localize}
  2597. end;
  2598. procedure TIdIRC.ReHash;
  2599. begin
  2600. Raw('REHASH'); {do not localize}
  2601. end;
  2602. procedure TIdIRC.Die;
  2603. begin
  2604. Raw('DIE'); {do not localize}
  2605. end;
  2606. procedure TIdIRC.Restart;
  2607. begin
  2608. Raw('RESTART'); {do not localize}
  2609. end;
  2610. procedure TIdIRC.Summon(const ANickname: String; const ATarget: String = '';
  2611. const AChannel: String = '');
  2612. begin
  2613. if (ATarget = '') and (AChannel = '') then begin
  2614. Raw(IndyFormat('SUMMON %s', [ANickname])); {do not localize}
  2615. end
  2616. else if AChannel <> '' then
  2617. begin
  2618. if IsChannel(AChannel) then begin
  2619. Raw(IndyFormat('SUMMON %s %s %s', [ANickname, ATarget, AChannel])); {do not localize}
  2620. end;
  2621. end else begin
  2622. Raw(IndyFormat('SUMMON %s %s', [ANickname, ATarget])); {do not localize}
  2623. end;
  2624. end;
  2625. procedure TIdIRC.ListServerUsers(const ATarget: String = '');
  2626. begin
  2627. if ATarget <> '' then begin
  2628. Raw(IndyFormat('USERS %s', [ATarget])); {do not localize}
  2629. end else begin
  2630. Raw('USERS'); {do not localize}
  2631. end;
  2632. end;
  2633. procedure TIdIRC.SayWALLOPS(const AMessage: String);
  2634. begin
  2635. Raw(IndyFormat('WALLOPS :%s', [AMessage])); {do not localize}
  2636. end;
  2637. procedure TIdIRC.GetUserInfo(const ANickname: String);
  2638. begin
  2639. Raw(IndyFormat('USERHOST %s', [ANickname])); {do not localize}
  2640. end;
  2641. procedure TIdIRC.GetUsersInfo(const ANicknames: array of string);
  2642. var
  2643. I: Integer;
  2644. S: string;
  2645. begin
  2646. if Length(ANicknames) > 0 then
  2647. begin
  2648. for I := Low(ANicknames) to High(ANicknames) do begin
  2649. S := S + ' ' + ANicknames[I]; {do not localize}
  2650. end;
  2651. Raw(IndyFormat('USERHOST%s', [S])); {do not localize}
  2652. end;
  2653. end;
  2654. procedure TIdIRC.IsOnIRC(const ANickname: String);
  2655. begin
  2656. Raw(IndyFormat('ISON %s', [ANickname])); {do not localize}
  2657. end;
  2658. procedure TIdIRC.IsOnIRC(const ANicknames: array of String);
  2659. var
  2660. I: Integer;
  2661. S: string;
  2662. begin
  2663. if Length(ANicknames) > 0 then
  2664. begin
  2665. for I := Low(ANicknames) to High(ANicknames) do begin
  2666. S := S + ' ' + ANicknames[I]; {do not localize}
  2667. end;
  2668. Raw(IndyFormat('ISON%s', [S])); {do not localize}
  2669. end;
  2670. end;
  2671. procedure TIdIRC.BecomeOp(const ANickname, APassword: String);
  2672. begin
  2673. Raw(IndyFormat('OPER %s %s', [ANickname, APassword])); {do not localize}
  2674. end;
  2675. procedure TIdIRC.SQuit(const AHost, AComment: String);
  2676. begin
  2677. Raw(IndyFormat('SQUIT %s :%s', [AHost, AComment])); {do not localize}
  2678. end;
  2679. procedure TIdIRC.SetChannelLimit(const AChannel: String; ALimit: Integer);
  2680. begin
  2681. SetChannelMode(AChannel, '+l', IntToStr(ALimit)); {do not localize}
  2682. end;
  2683. procedure TIdIRC.SetChannelKey(const AChannel, AKey: String);
  2684. begin
  2685. SetChannelMode(AChannel, '+k', AKey); {do not localize}
  2686. end;
  2687. procedure TIdIRC.SetIOHandler(AValue: TIdIOHandler);
  2688. begin
  2689. inherited SetIOHandler(AValue);
  2690. //we do it this way so that if a user is using a custom value <> default, the port
  2691. //is not set when the IOHandler is changed.
  2692. if (IOHandler is TIdSSLIOHandlerSocketBase) then begin
  2693. if Port = IdPORT_IRC then begin
  2694. Port := IdPORT_IRCS;
  2695. end;
  2696. end else begin
  2697. if Port = IdPORT_IRCS then begin
  2698. Port := IdPORT_IRC;
  2699. end;
  2700. end;
  2701. end;
  2702. end.